summaryrefslogtreecommitdiffstats
path: root/services/input/InputDispatcher.h
diff options
context:
space:
mode:
Diffstat (limited to 'services/input/InputDispatcher.h')
-rw-r--r--services/input/InputDispatcher.h170
1 files changed, 132 insertions, 38 deletions
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index dd89328..9ac5b75 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -86,20 +86,40 @@ enum {
struct InputTarget {
enum {
/* This flag indicates that the event is being delivered to a foreground application. */
- FLAG_FOREGROUND = 0x01,
-
- /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
- * of the area of this target and so should instead be delivered as an
- * AMOTION_EVENT_ACTION_OUTSIDE to this target. */
- FLAG_OUTSIDE = 0x02,
+ FLAG_FOREGROUND = 1 << 0,
/* This flag indicates that the target of a MotionEvent is partly or wholly
* obscured by another visible window above it. The motion event should be
* delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */
- FLAG_WINDOW_IS_OBSCURED = 0x04,
+ FLAG_WINDOW_IS_OBSCURED = 1 << 1,
/* This flag indicates that a motion event is being split across multiple windows. */
- FLAG_SPLIT = 0x08,
+ FLAG_SPLIT = 1 << 2,
+
+ /* This flag indicates that the event should be sent as is.
+ * Should always be set unless the event is to be transmuted. */
+ FLAG_DISPATCH_AS_IS = 1 << 8,
+
+ /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
+ * of the area of this target and so should instead be delivered as an
+ * AMOTION_EVENT_ACTION_OUTSIDE to this target. */
+ FLAG_DISPATCH_AS_OUTSIDE = 1 << 9,
+
+ /* This flag indicates that a hover sequence is starting in the given window.
+ * The event is transmuted into ACTION_HOVER_ENTER. */
+ FLAG_DISPATCH_AS_HOVER_ENTER = 1 << 10,
+
+ /* This flag indicates that a hover event happened outside of a window which handled
+ * previous hover events, signifying the end of the current hover sequence for that
+ * window.
+ * The event is transmuted into ACTION_HOVER_ENTER. */
+ FLAG_DISPATCH_AS_HOVER_EXIT = 1 << 11,
+
+ /* Mask for all dispatch modes. */
+ FLAG_DISPATCH_MASK = FLAG_DISPATCH_AS_IS
+ | FLAG_DISPATCH_AS_OUTSIDE
+ | FLAG_DISPATCH_AS_HOVER_ENTER
+ | FLAG_DISPATCH_AS_HOVER_EXIT,
};
// The input channel to be targeted.
@@ -160,6 +180,13 @@ public:
*/
virtual int32_t getMaxEventsPerSecond() = 0;
+ /* Filters an input event.
+ * Return true to dispatch the event unmodified, false to consume the event.
+ * A filter can also transform and inject events later by passing POLICY_FLAG_FILTERED
+ * to injectInputEvent.
+ */
+ virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) = 0;
+
/* Intercepts a key event immediately before queueing it.
* The policy can use this method as an opportunity to perform power management functions
* and early event preprocessing such as updating policy flags.
@@ -236,8 +263,9 @@ public:
int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;
virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t source,
uint32_t policyFlags, int32_t action, int32_t flags,
- int32_t metaState, int32_t edgeFlags,
- uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
+ int32_t metaState, int32_t buttonState, int32_t edgeFlags,
+ uint32_t pointerCount, const PointerProperties* pointerProperties,
+ const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime) = 0;
virtual void notifySwitch(nsecs_t when,
int32_t switchCode, int32_t switchValue, uint32_t policyFlags) = 0;
@@ -250,7 +278,8 @@ public:
* This method may be called on any thread (usually by the input manager).
*/
virtual int32_t injectInputEvent(const InputEvent* event,
- int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) = 0;
+ int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
+ uint32_t policyFlags) = 0;
/* Sets the list of input windows.
*
@@ -270,6 +299,14 @@ public:
*/
virtual void setInputDispatchMode(bool enabled, bool frozen) = 0;
+ /* Sets whether input event filtering is enabled.
+ * When enabled, incoming input events are sent to the policy's filterInputEvent
+ * method instead of being dispatched. The filter is expected to use
+ * injectInputEvent to inject the events it would like to have dispatched.
+ * It should include POLICY_FLAG_FILTERED in the policy flags during injection.
+ */
+ virtual void setInputFilterEnabled(bool enabled) = 0;
+
/* Transfers touch focus from the window associated with one channel to the
* window associated with the other channel.
*
@@ -322,18 +359,21 @@ public:
int32_t scanCode, int32_t metaState, nsecs_t downTime);
virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t source,
uint32_t policyFlags, int32_t action, int32_t flags,
- int32_t metaState, int32_t edgeFlags,
- uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
+ int32_t metaState, int32_t buttonState, int32_t edgeFlags,
+ uint32_t pointerCount, const PointerProperties* pointerProperties,
+ const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime);
virtual void notifySwitch(nsecs_t when,
int32_t switchCode, int32_t switchValue, uint32_t policyFlags) ;
virtual int32_t injectInputEvent(const InputEvent* event,
- int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis);
+ int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
+ uint32_t policyFlags);
virtual void setInputWindows(const Vector<InputWindow>& inputWindows);
virtual void setFocusedApplication(const InputApplication* inputApplication);
virtual void setInputDispatchMode(bool enabled, bool frozen);
+ virtual void setInputFilterEnabled(bool enabled);
virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
const sp<InputChannel>& toChannel);
@@ -375,7 +415,7 @@ private:
bool dispatchInProgress; // initially false, set to true while dispatching
- inline bool isInjected() { return injectionState != NULL; }
+ inline bool isInjected() const { return injectionState != NULL; }
};
struct ConfigurationChangedEntry : EventEntry {
@@ -405,7 +445,8 @@ private:
struct MotionSample {
MotionSample* next;
- nsecs_t eventTime;
+ nsecs_t eventTime; // may be updated during coalescing
+ nsecs_t eventTimeBeforeCoalescing; // not updated during coalescing
PointerCoords pointerCoords[MAX_POINTERS];
};
@@ -415,18 +456,23 @@ private:
int32_t action;
int32_t flags;
int32_t metaState;
+ int32_t buttonState;
int32_t edgeFlags;
float xPrecision;
float yPrecision;
nsecs_t downTime;
uint32_t pointerCount;
- int32_t pointerIds[MAX_POINTERS];
+ PointerProperties pointerProperties[MAX_POINTERS];
// Linked list of motion samples associated with this motion event.
MotionSample firstSample;
MotionSample* lastSample;
uint32_t countSamples() const;
+
+ // Checks whether we can append samples, assuming the device id and source are the same.
+ bool canAppendSamples(int32_t action, uint32_t pointerCount,
+ const PointerProperties* pointerProperties) const;
};
// Tracks the progress of dispatching a particular event to a particular connection.
@@ -559,10 +605,10 @@ private:
int32_t repeatCount, nsecs_t downTime);
MotionEntry* obtainMotionEntry(nsecs_t eventTime,
int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action,
- int32_t flags, int32_t metaState, int32_t edgeFlags,
+ int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
float xPrecision, float yPrecision,
nsecs_t downTime, uint32_t pointerCount,
- const int32_t* pointerIds, const PointerCoords* pointerCoords);
+ const PointerProperties* pointerProperties, const PointerCoords* pointerCoords);
DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry,
int32_t targetFlags, float xOffset, float yOffset, float scaleFactor);
CommandEntry* obtainCommandEntry(Command command);
@@ -572,6 +618,7 @@ private:
void releaseConfigurationChangedEntry(ConfigurationChangedEntry* entry);
void releaseKeyEntry(KeyEntry* entry);
void releaseMotionEntry(MotionEntry* entry);
+ void freeMotionSample(MotionSample* sample);
void releaseDispatchEntry(DispatchEntry* entry);
void releaseCommandEntry(CommandEntry* entry);
@@ -594,18 +641,32 @@ private:
void releaseEventEntryInjectionState(EventEntry* entry);
};
- /* Tracks dispatched key and motion event state so that cancelation events can be
- * synthesized when events are dropped. */
- class InputState {
- public:
- // Specifies the sources to cancel.
- enum CancelationOptions {
+ /* Specifies which events are to be canceled and why. */
+ struct CancelationOptions {
+ enum Mode {
CANCEL_ALL_EVENTS = 0,
CANCEL_POINTER_EVENTS = 1,
CANCEL_NON_POINTER_EVENTS = 2,
CANCEL_FALLBACK_EVENTS = 3,
};
+ // The criterion to use to determine which events should be canceled.
+ Mode mode;
+
+ // Descriptive reason for the cancelation.
+ const char* reason;
+
+ // The specific keycode of the key event to cancel, or -1 to cancel any key event.
+ int32_t keyCode;
+
+ CancelationOptions(Mode mode, const char* reason) :
+ mode(mode), reason(reason), keyCode(-1) { }
+ };
+
+ /* Tracks dispatched key and motion event state so that cancelation events can be
+ * synthesized when events are dropped. */
+ class InputState {
+ public:
InputState();
~InputState();
@@ -613,17 +674,17 @@ private:
bool isNeutral() const;
// Records tracking information for an event that has just been published.
- void trackEvent(const EventEntry* entry);
+ void trackEvent(const EventEntry* entry, int32_t action);
// Records tracking information for a key event that has just been published.
- void trackKey(const KeyEntry* entry);
+ void trackKey(const KeyEntry* entry, int32_t action);
// Records tracking information for a motion event that has just been published.
- void trackMotion(const MotionEntry* entry);
+ void trackMotion(const MotionEntry* entry, int32_t action);
// Synthesizes cancelation events for the current state and resets the tracked state.
void synthesizeCancelationEvents(nsecs_t currentTime, Allocator* allocator,
- Vector<EventEntry*>& outEvents, CancelationOptions options);
+ Vector<EventEntry*>& outEvents, const CancelationOptions& options);
// Clears the current state.
void clear();
@@ -631,6 +692,21 @@ private:
// Copies pointer-related parts of the input state to another instance.
void copyPointerStateTo(InputState& other) const;
+ // Gets the fallback key associated with a keycode.
+ // Returns -1 if none.
+ // Returns AKEYCODE_UNKNOWN if we are only dispatching the unhandled key to the policy.
+ int32_t getFallbackKey(int32_t originalKeyCode);
+
+ // Sets the fallback key for a particular keycode.
+ void setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode);
+
+ // Removes the fallback key for a particular keycode.
+ void removeFallbackKey(int32_t originalKeyCode);
+
+ inline const KeyedVector<int32_t, int32_t>& getFallbackKeys() const {
+ return mFallbackKeys;
+ }
+
private:
struct KeyMemento {
int32_t deviceId;
@@ -648,19 +724,21 @@ private:
float yPrecision;
nsecs_t downTime;
uint32_t pointerCount;
- int32_t pointerIds[MAX_POINTERS];
+ PointerProperties pointerProperties[MAX_POINTERS];
PointerCoords pointerCoords[MAX_POINTERS];
+ bool hovering;
void setPointers(const MotionEntry* entry);
};
Vector<KeyMemento> mKeyMementos;
Vector<MotionMemento> mMotionMementos;
+ KeyedVector<int32_t, int32_t> mFallbackKeys;
static bool shouldCancelKey(const KeyMemento& memento,
- CancelationOptions options);
+ const CancelationOptions& options);
static bool shouldCancelMotion(const MotionMemento& memento,
- CancelationOptions options);
+ const CancelationOptions& options);
};
/* Manages the dispatch state associated with a single input channel. */
@@ -687,7 +765,6 @@ private:
nsecs_t lastEventTime; // the time when the event was originally captured
nsecs_t lastDispatchTime; // the time when the last event was dispatched
- int32_t originalKeyCodeForFallback; // original keycode for fallback in progress, -1 if none
explicit Connection(const sp<InputChannel>& inputChannel,
const sp<InputWindowHandle>& inputWindowHandle);
@@ -738,6 +815,11 @@ private:
void dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout, nsecs_t keyRepeatDelay,
nsecs_t* nextWakeupTime);
+ // Batches a new sample onto a motion entry.
+ // Assumes that the we have already checked that we can append samples.
+ void batchMotionLocked(MotionEntry* entry, nsecs_t eventTime, int32_t metaState,
+ const PointerCoords* pointerCoords, const char* eventDescription);
+
// Enqueues an inbound event. Returns true if mLooper->wake() should be called.
bool enqueueInboundEventLocked(EventEntry* entry);
@@ -817,6 +899,7 @@ private:
// Dispatch state.
bool mDispatchEnabled;
bool mDispatchFrozen;
+ bool mInputFilterEnabled;
Vector<InputWindow> mWindows;
@@ -844,7 +927,7 @@ private:
void reset();
void copyFrom(const TouchState& other);
void addOrUpdateWindow(const InputWindow* window, int32_t targetFlags, BitSet32 pointerIds);
- void removeOutsideTouchWindows();
+ void filterNonAsIsTouchWindows();
const InputWindow* getFirstForegroundWindow();
};
@@ -887,6 +970,9 @@ private:
bool mInputTargetWaitTimeoutExpired;
sp<InputApplicationHandle> mInputTargetWaitApplication;
+ // Contains the last window which received a hover event.
+ const InputWindow* mLastHoverWindow;
+
// Finding targets for input events.
void resetTargetsLocked();
void commitTargetsLocked();
@@ -901,7 +987,8 @@ private:
int32_t findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry* entry,
nsecs_t* nextWakeupTime);
int32_t findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry* entry,
- nsecs_t* nextWakeupTime, bool* outConflictingPointerActions);
+ nsecs_t* nextWakeupTime, bool* outConflictingPointerActions,
+ const MotionSample** outSplitBatchAfterSample);
void addWindowTargetLocked(const InputWindow* window, int32_t targetFlags,
BitSet32 pointerIds);
@@ -920,6 +1007,9 @@ private:
void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
EventEntry* eventEntry, const InputTarget* inputTarget,
bool resumeWithAppendedMotionSample);
+ void enqueueDispatchEntryLocked(const sp<Connection>& connection,
+ EventEntry* eventEntry, const InputTarget* inputTarget,
+ bool resumeWithAppendedMotionSample, int32_t dispatchMode);
void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
bool handled);
@@ -929,11 +1019,11 @@ private:
static int handleReceiveCallback(int receiveFd, int events, void* data);
void synthesizeCancelationEventsForAllConnectionsLocked(
- InputState::CancelationOptions options, const char* reason);
+ const CancelationOptions& options);
void synthesizeCancelationEventsForInputChannelLocked(const sp<InputChannel>& channel,
- InputState::CancelationOptions options, const char* reason);
+ const CancelationOptions& options);
void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection,
- InputState::CancelationOptions options, const char* reason);
+ const CancelationOptions& options);
// Splitting motion events across windows.
MotionEntry* splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds);
@@ -966,6 +1056,10 @@ private:
void doNotifyANRLockedInterruptible(CommandEntry* commandEntry);
void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry);
void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry);
+ bool afterKeyEventLockedInterruptible(const sp<Connection>& connection,
+ DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled);
+ bool afterMotionEventLockedInterruptible(const sp<Connection>& connection,
+ DispatchEntry* dispatchEntry, MotionEntry* motionEntry, bool handled);
void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry);
void initializeKeyEvent(KeyEvent* event, const KeyEntry* entry);