blob: bde07f2a090bc1a79d6ec48fb4f813d9d77009fa [file] [log] [blame]
Jeff Browne839a582010-04-22 18:58:52 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _UI_INPUT_DISPATCHER_H
18#define _UI_INPUT_DISPATCHER_H
19
20#include <ui/Input.h>
21#include <ui/InputDispatchPolicy.h>
22#include <ui/InputTransport.h>
23#include <utils/KeyedVector.h>
24#include <utils/Vector.h>
25#include <utils/threads.h>
26#include <utils/Timers.h>
27#include <utils/RefBase.h>
28#include <utils/String8.h>
29#include <utils/PollLoop.h>
30#include <utils/Pool.h>
31
32#include <stddef.h>
33#include <unistd.h>
34
35
36namespace android {
37
38/* Notifies the system about input events generated by the input reader.
39 * The dispatcher is expected to be mostly asynchronous. */
40class InputDispatcherInterface : public virtual RefBase {
41protected:
42 InputDispatcherInterface() { }
43 virtual ~InputDispatcherInterface() { }
44
45public:
46 /* Runs a single iteration of the dispatch loop.
47 * Nominally processes one queued event, a timeout, or a response from an input consumer.
48 *
49 * This method should only be called on the input dispatcher thread.
50 */
51 virtual void dispatchOnce() = 0;
52
53 /* Notifies the dispatcher about new events.
54 * The dispatcher will process most of these events asynchronously although some
55 * policy processing may occur synchronously.
56 *
57 * These methods should only be called on the input reader thread.
58 */
59 virtual void notifyConfigurationChanged(nsecs_t eventTime,
60 int32_t touchScreenConfig, int32_t keyboardConfig, int32_t navigationConfig) = 0;
61 virtual void notifyLidSwitchChanged(nsecs_t eventTime, bool lidOpen) = 0;
62 virtual void notifyAppSwitchComing(nsecs_t eventTime) = 0;
63 virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
64 uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
65 int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;
66 virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t nature,
67 uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
68 uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
69 float xPrecision, float yPrecision, nsecs_t downTime) = 0;
70
71 /* Registers or unregister input channels that may be used as targets for input events.
72 *
73 * These methods may be called on any thread (usually by the input manager).
74 */
75 virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel) = 0;
76 virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
77};
78
79/* Dispatches events. */
80class InputDispatcher : public InputDispatcherInterface {
81protected:
82 virtual ~InputDispatcher();
83
84public:
85 explicit InputDispatcher(const sp<InputDispatchPolicyInterface>& policy);
86
87 virtual void dispatchOnce();
88
89 virtual void notifyConfigurationChanged(nsecs_t eventTime,
90 int32_t touchScreenConfig, int32_t keyboardConfig, int32_t navigationConfig);
91 virtual void notifyLidSwitchChanged(nsecs_t eventTime, bool lidOpen);
92 virtual void notifyAppSwitchComing(nsecs_t eventTime);
93 virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
94 uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
95 int32_t scanCode, int32_t metaState, nsecs_t downTime);
96 virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t nature,
97 uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
98 uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
99 float xPrecision, float yPrecision, nsecs_t downTime);
100
101 virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel);
102 virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
103
104private:
105 template <typename T>
106 struct Link {
107 T* next;
108 T* prev;
109 };
110
111 struct EventEntry : Link<EventEntry> {
112 enum {
113 TYPE_SENTINEL,
114 TYPE_CONFIGURATION_CHANGED,
115 TYPE_KEY,
116 TYPE_MOTION
117 };
118
119 int32_t refCount;
120 int32_t type;
121 nsecs_t eventTime;
122 };
123
124 struct ConfigurationChangedEntry : EventEntry {
125 int32_t touchScreenConfig;
126 int32_t keyboardConfig;
127 int32_t navigationConfig;
128 };
129
130 struct KeyEntry : EventEntry {
131 int32_t deviceId;
132 int32_t nature;
133 uint32_t policyFlags;
134 int32_t action;
135 int32_t flags;
136 int32_t keyCode;
137 int32_t scanCode;
138 int32_t metaState;
139 int32_t repeatCount;
140 nsecs_t downTime;
141 };
142
143 struct MotionSample {
144 MotionSample* next;
145
146 nsecs_t eventTime;
147 PointerCoords pointerCoords[MAX_POINTERS];
148 };
149
150 struct MotionEntry : EventEntry {
151 int32_t deviceId;
152 int32_t nature;
153 uint32_t policyFlags;
154 int32_t action;
155 int32_t metaState;
156 int32_t edgeFlags;
157 float xPrecision;
158 float yPrecision;
159 nsecs_t downTime;
160 uint32_t pointerCount;
161 int32_t pointerIds[MAX_POINTERS];
162
163 // Linked list of motion samples associated with this motion event.
164 MotionSample firstSample;
165 MotionSample* lastSample;
166 };
167
168 struct DispatchEntry : Link<DispatchEntry> {
169 EventEntry* eventEntry; // the event to dispatch
170 int32_t targetFlags;
171 float xOffset;
172 float yOffset;
173 nsecs_t timeout;
174
175 // True if dispatch has started.
176 bool inProgress;
177
178 // For motion events:
179 // Pointer to the first motion sample to dispatch in this cycle.
180 // Usually NULL to indicate that the list of motion samples begins at
181 // MotionEntry::firstSample. Otherwise, some samples were dispatched in a previous
182 // cycle and this pointer indicates the location of the first remainining sample
183 // to dispatch during the current cycle.
184 MotionSample* headMotionSample;
185 // Pointer to a motion sample to dispatch in the next cycle if the dispatcher was
186 // unable to send all motion samples during this cycle. On the next cycle,
187 // headMotionSample will be initialized to tailMotionSample and tailMotionSample
188 // will be set to NULL.
189 MotionSample* tailMotionSample;
190 };
191
192 template <typename T>
193 struct Queue {
194 T head;
195 T tail;
196
197 inline Queue() {
198 head.prev = NULL;
199 head.next = & tail;
200 tail.prev = & head;
201 tail.next = NULL;
202 }
203
204 inline bool isEmpty() {
205 return head.next == & tail;
206 }
207
208 inline void enqueueAtTail(T* entry) {
209 T* last = tail.prev;
210 last->next = entry;
211 entry->prev = last;
212 entry->next = & tail;
213 tail.prev = entry;
214 }
215
216 inline void enqueueAtHead(T* entry) {
217 T* first = head.next;
218 head.next = entry;
219 entry->prev = & head;
220 entry->next = first;
221 first->prev = entry;
222 }
223
224 inline void dequeue(T* entry) {
225 entry->prev->next = entry->next;
226 entry->next->prev = entry->prev;
227 }
228
229 inline T* dequeueAtHead() {
230 T* first = head.next;
231 dequeue(first);
232 return first;
233 }
234 };
235
236 /* Allocates queue entries and performs reference counting as needed. */
237 class Allocator {
238 public:
239 Allocator();
240
241 ConfigurationChangedEntry* obtainConfigurationChangedEntry();
242 KeyEntry* obtainKeyEntry();
243 MotionEntry* obtainMotionEntry();
244 DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry);
245
246 void releaseEventEntry(EventEntry* entry);
247 void releaseConfigurationChangedEntry(ConfigurationChangedEntry* entry);
248 void releaseKeyEntry(KeyEntry* entry);
249 void releaseMotionEntry(MotionEntry* entry);
250 void releaseDispatchEntry(DispatchEntry* entry);
251
252 void appendMotionSample(MotionEntry* motionEntry,
253 nsecs_t eventTime, int32_t pointerCount, const PointerCoords* pointerCoords);
254 void freeMotionSample(MotionSample* sample);
255 void freeMotionSampleList(MotionSample* head);
256
257 private:
258 Pool<ConfigurationChangedEntry> mConfigurationChangeEntryPool;
259 Pool<KeyEntry> mKeyEntryPool;
260 Pool<MotionEntry> mMotionEntryPool;
261 Pool<MotionSample> mMotionSamplePool;
262 Pool<DispatchEntry> mDispatchEntryPool;
263 };
264
265 /* Manages the dispatch state associated with a single input channel. */
266 class Connection : public RefBase {
267 protected:
268 virtual ~Connection();
269
270 public:
271 enum Status {
272 // Everything is peachy.
273 STATUS_NORMAL,
274 // An unrecoverable communication error has occurred.
275 STATUS_BROKEN,
276 // The client is not responding.
277 STATUS_NOT_RESPONDING,
278 // The input channel has been unregistered.
279 STATUS_ZOMBIE
280 };
281
282 Status status;
283 sp<InputChannel> inputChannel;
284 InputPublisher inputPublisher;
285 Queue<DispatchEntry> outboundQueue;
286 nsecs_t nextTimeoutTime; // next timeout time (LONG_LONG_MAX if none)
287
288 nsecs_t lastEventTime; // the time when the event was originally captured
289 nsecs_t lastDispatchTime; // the time when the last event was dispatched
290 nsecs_t lastANRTime; // the time when the last ANR was recorded
291
292 explicit Connection(const sp<InputChannel>& inputChannel);
293
294 inline const char* getInputChannelName() { return inputChannel->getName().string(); }
295
296 // Finds a DispatchEntry in the outbound queue associated with the specified event.
297 // Returns NULL if not found.
298 DispatchEntry* findQueuedDispatchEntryForEvent(const EventEntry* eventEntry) const;
299
300 // Determine whether this connection has a pending synchronous dispatch target.
301 // Since there can only ever be at most one such target at a time, if there is one,
302 // it must be at the tail because nothing else can be enqueued after it.
303 inline bool hasPendingSyncTarget() {
304 return ! outboundQueue.isEmpty()
305 && (outboundQueue.tail.prev->targetFlags & InputTarget::FLAG_SYNC);
306 }
307
308 // Gets the time since the current event was originally obtained from the input driver.
309 inline double getEventLatencyMillis(nsecs_t currentTime) {
310 return (currentTime - lastEventTime) / 1000000.0;
311 }
312
313 // Gets the time since the current event entered the outbound dispatch queue.
314 inline double getDispatchLatencyMillis(nsecs_t currentTime) {
315 return (currentTime - lastDispatchTime) / 1000000.0;
316 }
317
318 // Gets the time since the current event ANR was declared, if applicable.
319 inline double getANRLatencyMillis(nsecs_t currentTime) {
320 return (currentTime - lastANRTime) / 1000000.0;
321 }
322
323 status_t initialize();
324 };
325
326 sp<InputDispatchPolicyInterface> mPolicy;
327
328 Mutex mLock;
329
330 Queue<EventEntry> mInboundQueue;
331 Allocator mAllocator;
332
333 sp<PollLoop> mPollLoop;
334
335 // All registered connections mapped by receive pipe file descriptor.
336 KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd;
337
338 // Active connections are connections that have a non-empty outbound queue.
339 Vector<Connection*> mActiveConnections;
340
341 // Pool of key and motion event objects used only to ask the input dispatch policy
342 // for the targets of an event that is to be dispatched.
343 KeyEvent mReusableKeyEvent;
344 MotionEvent mReusableMotionEvent;
345
346 // The input targets that were most recently identified for dispatch.
347 // If there is a synchronous event dispatch in progress, the current input targets will
348 // remain unchanged until the dispatch has completed or been aborted.
349 Vector<InputTarget> mCurrentInputTargets;
350
351 // Key repeat tracking.
352 // XXX Move this up to the input reader instead.
353 struct KeyRepeatState {
354 KeyEntry* lastKeyEntry; // or null if no repeat
355 nsecs_t nextRepeatTime;
356 } mKeyRepeatState;
357
358 void resetKeyRepeatLocked();
359
360 // Process events that have just been dequeued from the head of the input queue.
361 void processConfigurationChangedLocked(nsecs_t currentTime, ConfigurationChangedEntry* entry);
362 void processKeyLocked(nsecs_t currentTime, KeyEntry* entry);
363 void processKeyRepeatLocked(nsecs_t currentTime);
364 void processMotionLocked(nsecs_t currentTime, MotionEntry* entry);
365
366 // Identify input targets for an event and dispatch to them.
367 void identifyInputTargetsAndDispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry);
368 void identifyInputTargetsAndDispatchMotionLocked(nsecs_t currentTime, MotionEntry* entry);
369 void dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime, EventEntry* entry,
370 bool resumeWithAppendedMotionSample);
371
372 // Manage the dispatch cycle for a single connection.
373 void prepareDispatchCycleLocked(nsecs_t currentTime, Connection* connection,
374 EventEntry* eventEntry, const InputTarget* inputTarget,
375 bool resumeWithAppendedMotionSample);
376 void startDispatchCycleLocked(nsecs_t currentTime, Connection* connection);
377 void finishDispatchCycleLocked(nsecs_t currentTime, Connection* connection);
378 bool timeoutDispatchCycleLocked(nsecs_t currentTime, Connection* connection);
379 bool abortDispatchCycleLocked(nsecs_t currentTime, Connection* connection,
380 bool broken);
381 static bool handleReceiveCallback(int receiveFd, int events, void* data);
382
383 // Add or remove a connection to the mActiveConnections vector.
384 void activateConnectionLocked(Connection* connection);
385 void deactivateConnectionLocked(Connection* connection);
386
387 // Interesting events that we might like to log or tell the framework about.
388 void onDispatchCycleStartedLocked(nsecs_t currentTime, Connection* connection);
389 void onDispatchCycleFinishedLocked(nsecs_t currentTime, Connection* connection,
390 bool recoveredFromANR);
391 void onDispatchCycleANRLocked(nsecs_t currentTime, Connection* connection);
392 void onDispatchCycleBrokenLocked(nsecs_t currentTime, Connection* connection);
393};
394
395/* Enqueues and dispatches input events, endlessly. */
396class InputDispatcherThread : public Thread {
397public:
398 explicit InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher);
399 ~InputDispatcherThread();
400
401private:
402 virtual bool threadLoop();
403
404 sp<InputDispatcherInterface> mDispatcher;
405};
406
407} // namespace android
408
409#endif // _UI_INPUT_DISPATCHER_PRIV_H