am 41aabeb5: am 1e6a3a53: Merge "Added more robust tracking and cancelation of events." into gingerbread
Merge commit '41aabeb51305d19747687f246080f44fc2a74435' * commit '41aabeb51305d19747687f246080f44fc2a74435': Added more robust tracking and cancelation of events.
This commit is contained in:
commit
d129348647
|
@ -71,6 +71,8 @@ namespace android {
|
|||
/*
|
||||
* Flags that flow alongside events in the input dispatch system to help with certain
|
||||
* policy decisions such as waking from device sleep.
|
||||
*
|
||||
* These flags are also defined in frameworks/base/core/java/android/view/WindowManagerPolicy.java.
|
||||
*/
|
||||
enum {
|
||||
/* These flags originate in RawEvents and are generally set in the key map.
|
||||
|
@ -102,6 +104,11 @@ enum {
|
|||
// Indicates that the screen was dim when the event was received and the event
|
||||
// should brighten the device.
|
||||
POLICY_FLAG_BRIGHT_HERE = 0x20000000,
|
||||
|
||||
// Indicates that the event should be dispatched to applications.
|
||||
// The input event should still be sent to the InputDispatcher so that it can see all
|
||||
// input events received include those that it will not deliver.
|
||||
POLICY_FLAG_PASS_TO_USER = 0x40000000,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -282,10 +282,35 @@ public:
|
|||
*/
|
||||
virtual int32_t getMaxEventsPerSecond() = 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.
|
||||
*
|
||||
* This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
|
||||
* should be dispatched to applications.
|
||||
*/
|
||||
virtual void interceptKeyBeforeQueueing(nsecs_t when, int32_t deviceId,
|
||||
int32_t action, int32_t& flags, int32_t keyCode, int32_t scanCode,
|
||||
uint32_t& policyFlags) = 0;
|
||||
|
||||
/* Intercepts a generic touch, trackball or other event 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.
|
||||
*
|
||||
* This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
|
||||
* should be dispatched to applications.
|
||||
*/
|
||||
virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
|
||||
|
||||
/* Allows the policy a chance to intercept a key before dispatching. */
|
||||
virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
|
||||
const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
|
||||
|
||||
/* Notifies the policy about switch events.
|
||||
*/
|
||||
virtual void notifySwitch(nsecs_t when,
|
||||
int32_t switchCode, int32_t switchValue, uint32_t policyFlags) = 0;
|
||||
|
||||
/* Poke user activity for an event dispatched to a window. */
|
||||
virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) = 0;
|
||||
|
||||
|
@ -333,6 +358,8 @@ public:
|
|||
int32_t metaState, int32_t edgeFlags,
|
||||
uint32_t pointerCount, const int32_t* pointerIds, 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;
|
||||
|
||||
/* Injects an input event and optionally waits for sync.
|
||||
* The synchronization mode determines whether the method blocks while waiting for
|
||||
|
@ -416,6 +443,8 @@ public:
|
|||
int32_t metaState, int32_t edgeFlags,
|
||||
uint32_t pointerCount, const int32_t* pointerIds, 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);
|
||||
|
@ -458,6 +487,7 @@ private:
|
|||
mutable int32_t refCount;
|
||||
int32_t type;
|
||||
nsecs_t eventTime;
|
||||
uint32_t policyFlags;
|
||||
InjectionState* injectionState;
|
||||
|
||||
bool dispatchInProgress; // initially false, set to true while dispatching
|
||||
|
@ -471,7 +501,6 @@ private:
|
|||
struct KeyEntry : EventEntry {
|
||||
int32_t deviceId;
|
||||
int32_t source;
|
||||
uint32_t policyFlags;
|
||||
int32_t action;
|
||||
int32_t flags;
|
||||
int32_t keyCode;
|
||||
|
@ -500,7 +529,6 @@ private:
|
|||
struct MotionEntry : EventEntry {
|
||||
int32_t deviceId;
|
||||
int32_t source;
|
||||
uint32_t policyFlags;
|
||||
int32_t action;
|
||||
int32_t flags;
|
||||
int32_t metaState;
|
||||
|
@ -675,7 +703,8 @@ private:
|
|||
Pool<DispatchEntry> mDispatchEntryPool;
|
||||
Pool<CommandEntry> mCommandEntryPool;
|
||||
|
||||
void initializeEventEntry(EventEntry* entry, int32_t type, nsecs_t eventTime);
|
||||
void initializeEventEntry(EventEntry* entry, int32_t type, nsecs_t eventTime,
|
||||
uint32_t policyFlags);
|
||||
void releaseEventEntryInjectionState(EventEntry* entry);
|
||||
};
|
||||
|
||||
|
@ -696,21 +725,19 @@ private:
|
|||
BROKEN
|
||||
};
|
||||
|
||||
// Specifies the sources to cancel.
|
||||
enum CancelationOptions {
|
||||
CANCEL_ALL_EVENTS = 0,
|
||||
CANCEL_POINTER_EVENTS = 1,
|
||||
CANCEL_NON_POINTER_EVENTS = 2,
|
||||
};
|
||||
|
||||
InputState();
|
||||
~InputState();
|
||||
|
||||
// Returns true if there is no state to be canceled.
|
||||
bool isNeutral() const;
|
||||
|
||||
// Returns true if the input state believes it is out of sync.
|
||||
bool isOutOfSync() const;
|
||||
|
||||
// Sets the input state to be out of sync if it is not neutral.
|
||||
void setOutOfSync();
|
||||
|
||||
// Resets the input state out of sync flag.
|
||||
void resetOutOfSync();
|
||||
|
||||
// Records tracking information for an event that has just been published.
|
||||
// Returns whether the event is consistent with the current input state.
|
||||
Consistency trackEvent(const EventEntry* entry);
|
||||
|
@ -723,16 +750,14 @@ private:
|
|||
// Returns whether the event is consistent with the current input state.
|
||||
Consistency trackMotion(const MotionEntry* entry);
|
||||
|
||||
// Synthesizes cancelation events for the current state.
|
||||
void synthesizeCancelationEvents(Allocator* allocator,
|
||||
Vector<EventEntry*>& outEvents) const;
|
||||
// Synthesizes cancelation events for the current state and resets the tracked state.
|
||||
void synthesizeCancelationEvents(nsecs_t currentTime, Allocator* allocator,
|
||||
Vector<EventEntry*>& outEvents, CancelationOptions options);
|
||||
|
||||
// Clears the current state.
|
||||
void clear();
|
||||
|
||||
private:
|
||||
bool mIsOutOfSync;
|
||||
|
||||
struct KeyMemento {
|
||||
int32_t deviceId;
|
||||
int32_t source;
|
||||
|
@ -756,6 +781,8 @@ private:
|
|||
|
||||
Vector<KeyMemento> mKeyMementos;
|
||||
Vector<MotionMemento> mMotionMementos;
|
||||
|
||||
static bool shouldCancelEvent(int32_t eventSource, CancelationOptions options);
|
||||
};
|
||||
|
||||
/* Manages the dispatch state associated with a single input channel. */
|
||||
|
@ -805,6 +832,13 @@ private:
|
|||
status_t initialize();
|
||||
};
|
||||
|
||||
enum DropReason {
|
||||
DROP_REASON_NOT_DROPPED = 0,
|
||||
DROP_REASON_POLICY = 1,
|
||||
DROP_REASON_APP_SWITCH = 2,
|
||||
DROP_REASON_DISABLED = 3,
|
||||
};
|
||||
|
||||
sp<InputDispatcherPolicyInterface> mPolicy;
|
||||
|
||||
Mutex mLock;
|
||||
|
@ -824,12 +858,16 @@ private:
|
|||
// Enqueues an inbound event. Returns true if mLooper->wake() should be called.
|
||||
bool enqueueInboundEventLocked(EventEntry* entry);
|
||||
|
||||
// Cleans up input state when dropping an inbound event.
|
||||
void dropInboundEventLocked(EventEntry* entry, DropReason dropReason);
|
||||
|
||||
// App switch latency optimization.
|
||||
bool mAppSwitchSawKeyDown;
|
||||
nsecs_t mAppSwitchDueTime;
|
||||
|
||||
static bool isAppSwitchKey(int32_t keyCode);
|
||||
static bool isAppSwitchKeyCode(int32_t keyCode);
|
||||
bool isAppSwitchKeyEventLocked(KeyEntry* keyEntry);
|
||||
bool isAppSwitchPendingLocked();
|
||||
bool detectPendingAppSwitchLocked(KeyEntry* inboundKeyEntry);
|
||||
void resetPendingAppSwitchLocked(bool handled);
|
||||
|
||||
// All registered connections mapped by receive pipe file descriptor.
|
||||
|
@ -851,7 +889,7 @@ private:
|
|||
|
||||
// Event injection and synchronization.
|
||||
Condition mInjectionResultAvailableCondition;
|
||||
EventEntry* createEntryFromInjectedInputEventLocked(const InputEvent* event);
|
||||
bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid);
|
||||
void setInjectionResultLocked(EventEntry* entry, int32_t injectionResult);
|
||||
|
||||
Condition mInjectionSyncFinishedCondition;
|
||||
|
@ -886,7 +924,7 @@ private:
|
|||
void drainInboundQueueLocked();
|
||||
void releasePendingEventLocked();
|
||||
void releaseInboundEventLocked(EventEntry* entry);
|
||||
bool isEventFromReliableSourceLocked(EventEntry* entry);
|
||||
bool isEventFromTrustedSourceLocked(EventEntry* entry);
|
||||
|
||||
// Dispatch state.
|
||||
bool mDispatchEnabled;
|
||||
|
@ -995,11 +1033,17 @@ private:
|
|||
void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
|
||||
void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
|
||||
void startNextDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
|
||||
void abortDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
|
||||
bool broken);
|
||||
void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
|
||||
void drainOutboundQueueLocked(Connection* connection);
|
||||
static int handleReceiveCallback(int receiveFd, int events, void* data);
|
||||
|
||||
void synthesizeCancelationEventsForAllConnectionsLocked(
|
||||
InputState::CancelationOptions options, const char* reason);
|
||||
void synthesizeCancelationEventsForInputChannelLocked(const sp<InputChannel>& channel,
|
||||
InputState::CancelationOptions options, const char* reason);
|
||||
void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection,
|
||||
InputState::CancelationOptions options, const char* reason);
|
||||
|
||||
// Splitting motion events across windows.
|
||||
MotionEntry* splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds);
|
||||
|
||||
|
|
|
@ -87,49 +87,12 @@ public:
|
|||
ROTATION_270 = 3
|
||||
};
|
||||
|
||||
/* Actions returned by interceptXXX methods. */
|
||||
enum {
|
||||
// The input dispatcher should do nothing and discard the input unless other
|
||||
// flags are set.
|
||||
ACTION_NONE = 0,
|
||||
|
||||
// The input dispatcher should dispatch the input to the application.
|
||||
ACTION_DISPATCH = 0x00000001,
|
||||
};
|
||||
|
||||
/* Gets information about the display with the specified id.
|
||||
* Returns true if the display info is available, false otherwise.
|
||||
*/
|
||||
virtual bool getDisplayInfo(int32_t displayId,
|
||||
int32_t* width, int32_t* height, int32_t* orientation) = 0;
|
||||
|
||||
/* Intercepts a key event.
|
||||
* The policy can use this method as an opportunity to perform power management functions
|
||||
* and early event preprocessing such as updating policy flags.
|
||||
*
|
||||
* Returns a policy action constant such as ACTION_DISPATCH.
|
||||
*/
|
||||
virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
|
||||
bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) = 0;
|
||||
|
||||
/* Intercepts a switch event.
|
||||
* The policy can use this method as an opportunity to perform power management functions
|
||||
* and early event preprocessing such as updating policy flags.
|
||||
*
|
||||
* Switches are not dispatched to applications so this method should
|
||||
* usually return ACTION_NONE.
|
||||
*/
|
||||
virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
|
||||
uint32_t& policyFlags) = 0;
|
||||
|
||||
/* Intercepts a generic touch, trackball or other event.
|
||||
* The policy can use this method as an opportunity to perform power management functions
|
||||
* and early event preprocessing such as updating policy flags.
|
||||
*
|
||||
* Returns a policy action constant such as ACTION_DISPATCH.
|
||||
*/
|
||||
virtual int32_t interceptGeneric(nsecs_t when, uint32_t& policyFlags) = 0;
|
||||
|
||||
/* Determines whether to turn on some hacks we have to improve the touch interaction with a
|
||||
* certain device whose screen currently is not all that good.
|
||||
*/
|
||||
|
@ -403,8 +366,6 @@ public:
|
|||
protected:
|
||||
InputDevice* mDevice;
|
||||
InputReaderContext* mContext;
|
||||
|
||||
bool applyStandardPolicyActions(nsecs_t when, int32_t policyActions);
|
||||
};
|
||||
|
||||
|
||||
|
@ -466,8 +427,6 @@ private:
|
|||
|
||||
void processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode,
|
||||
uint32_t policyFlags);
|
||||
void applyPolicyAndDispatch(nsecs_t when, uint32_t policyFlags,
|
||||
bool down, int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime);
|
||||
|
||||
ssize_t findKeyDownLocked(int32_t scanCode);
|
||||
};
|
||||
|
@ -525,8 +484,6 @@ private:
|
|||
void initializeLocked();
|
||||
|
||||
void sync(nsecs_t when);
|
||||
void applyPolicyAndDispatch(nsecs_t when, int32_t motionEventAction,
|
||||
PointerCoords* pointerCoords, nsecs_t downTime);
|
||||
};
|
||||
|
||||
|
||||
|
@ -829,10 +786,6 @@ private:
|
|||
BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
|
||||
int32_t motionEventAction);
|
||||
|
||||
void applyPolicyAndDispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
|
||||
int32_t keyEventAction, int32_t keyEventFlags,
|
||||
int32_t keyCode, int32_t scanCode, nsecs_t downTime);
|
||||
|
||||
bool isPointInsideSurfaceLocked(int32_t x, int32_t y);
|
||||
const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y);
|
||||
|
||||
|
|
|
@ -95,16 +95,19 @@ static bool validateKeyEvent(int32_t action) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool isValidMotionAction(int32_t action) {
|
||||
static bool isValidMotionAction(int32_t action, size_t pointerCount) {
|
||||
switch (action & AMOTION_EVENT_ACTION_MASK) {
|
||||
case AMOTION_EVENT_ACTION_DOWN:
|
||||
case AMOTION_EVENT_ACTION_UP:
|
||||
case AMOTION_EVENT_ACTION_CANCEL:
|
||||
case AMOTION_EVENT_ACTION_MOVE:
|
||||
case AMOTION_EVENT_ACTION_POINTER_DOWN:
|
||||
case AMOTION_EVENT_ACTION_POINTER_UP:
|
||||
case AMOTION_EVENT_ACTION_OUTSIDE:
|
||||
return true;
|
||||
case AMOTION_EVENT_ACTION_POINTER_DOWN:
|
||||
case AMOTION_EVENT_ACTION_POINTER_UP: {
|
||||
int32_t index = getMotionEventActionPointerIndex(action);
|
||||
return index >= 0 && size_t(index) < pointerCount;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -112,7 +115,7 @@ static bool isValidMotionAction(int32_t action) {
|
|||
|
||||
static bool validateMotionEvent(int32_t action, size_t pointerCount,
|
||||
const int32_t* pointerIds) {
|
||||
if (! isValidMotionAction(action)) {
|
||||
if (! isValidMotionAction(action, pointerCount)) {
|
||||
LOGE("Motion event has invalid action code 0x%x", action);
|
||||
return false;
|
||||
}
|
||||
|
@ -235,16 +238,6 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
|
|||
resetKeyRepeatLocked();
|
||||
}
|
||||
|
||||
// If dispatching is disabled, drop all events in the queue.
|
||||
if (! mDispatchEnabled) {
|
||||
if (mPendingEvent || ! mInboundQueue.isEmpty()) {
|
||||
LOGI("Dropping pending events because input dispatch is disabled.");
|
||||
releasePendingEventLocked();
|
||||
drainInboundQueueLocked();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// If dispatching is frozen, do not process timeouts or try to deliver any new events.
|
||||
if (mDispatchFrozen) {
|
||||
#if DEBUG_FOCUS
|
||||
|
@ -294,7 +287,11 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
|
|||
// samples may be appended to this event by the time the throttling timeout
|
||||
// expires.
|
||||
// TODO Make this smarter and consider throttling per device independently.
|
||||
if (entry->type == EventEntry::TYPE_MOTION) {
|
||||
if (entry->type == EventEntry::TYPE_MOTION
|
||||
&& !isAppSwitchDue
|
||||
&& mDispatchEnabled
|
||||
&& (entry->policyFlags & POLICY_FLAG_PASS_TO_USER)
|
||||
&& !entry->isInjected()) {
|
||||
MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
|
||||
int32_t deviceId = motionEntry->deviceId;
|
||||
uint32_t source = motionEntry->source;
|
||||
|
@ -347,39 +344,43 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
|
|||
// Now we have an event to dispatch.
|
||||
assert(mPendingEvent != NULL);
|
||||
bool done = false;
|
||||
DropReason dropReason = DROP_REASON_NOT_DROPPED;
|
||||
if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
|
||||
dropReason = DROP_REASON_POLICY;
|
||||
} else if (!mDispatchEnabled) {
|
||||
dropReason = DROP_REASON_DISABLED;
|
||||
}
|
||||
switch (mPendingEvent->type) {
|
||||
case EventEntry::TYPE_CONFIGURATION_CHANGED: {
|
||||
ConfigurationChangedEntry* typedEntry =
|
||||
static_cast<ConfigurationChangedEntry*>(mPendingEvent);
|
||||
done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
|
||||
dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
|
||||
break;
|
||||
}
|
||||
|
||||
case EventEntry::TYPE_KEY: {
|
||||
KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
|
||||
bool appSwitchKey = isAppSwitchKey(typedEntry->keyCode);
|
||||
bool dropEvent = isAppSwitchDue && ! appSwitchKey;
|
||||
done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout, dropEvent,
|
||||
nextWakeupTime);
|
||||
if (done) {
|
||||
if (dropEvent) {
|
||||
LOGI("Dropped key because of pending overdue app switch.");
|
||||
} else if (appSwitchKey) {
|
||||
if (isAppSwitchDue) {
|
||||
if (isAppSwitchKeyEventLocked(typedEntry)) {
|
||||
resetPendingAppSwitchLocked(true);
|
||||
isAppSwitchDue = false;
|
||||
} else if (dropReason == DROP_REASON_NOT_DROPPED) {
|
||||
dropReason = DROP_REASON_APP_SWITCH;
|
||||
}
|
||||
}
|
||||
done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
|
||||
dropReason != DROP_REASON_NOT_DROPPED, nextWakeupTime);
|
||||
break;
|
||||
}
|
||||
|
||||
case EventEntry::TYPE_MOTION: {
|
||||
MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
|
||||
bool dropEvent = isAppSwitchDue;
|
||||
done = dispatchMotionLocked(currentTime, typedEntry, dropEvent, nextWakeupTime);
|
||||
if (done) {
|
||||
if (dropEvent) {
|
||||
LOGI("Dropped motion because of pending overdue app switch.");
|
||||
}
|
||||
if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
|
||||
dropReason = DROP_REASON_APP_SWITCH;
|
||||
}
|
||||
done = dispatchMotionLocked(currentTime, typedEntry,
|
||||
dropReason != DROP_REASON_NOT_DROPPED, nextWakeupTime);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -389,6 +390,10 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
|
|||
}
|
||||
|
||||
if (done) {
|
||||
if (dropReason != DROP_REASON_NOT_DROPPED) {
|
||||
dropInboundEventLocked(mPendingEvent, dropReason);
|
||||
}
|
||||
|
||||
releasePendingEventLocked();
|
||||
*nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
|
||||
}
|
||||
|
@ -399,36 +404,83 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
|
|||
mInboundQueue.enqueueAtTail(entry);
|
||||
|
||||
switch (entry->type) {
|
||||
case EventEntry::TYPE_KEY:
|
||||
needWake |= detectPendingAppSwitchLocked(static_cast<KeyEntry*>(entry));
|
||||
case EventEntry::TYPE_KEY: {
|
||||
KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
|
||||
if (isAppSwitchKeyEventLocked(keyEntry)) {
|
||||
if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
|
||||
mAppSwitchSawKeyDown = true;
|
||||
} else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
|
||||
if (mAppSwitchSawKeyDown) {
|
||||
#if DEBUG_APP_SWITCH
|
||||
LOGD("App switch is pending!");
|
||||
#endif
|
||||
mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
|
||||
mAppSwitchSawKeyDown = false;
|
||||
needWake = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return needWake;
|
||||
}
|
||||
|
||||
bool InputDispatcher::isAppSwitchKey(int32_t keyCode) {
|
||||
void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
|
||||
const char* reason;
|
||||
switch (dropReason) {
|
||||
case DROP_REASON_POLICY:
|
||||
reason = "inbound event was dropped because the policy requested that it not be "
|
||||
"delivered to the application";
|
||||
break;
|
||||
case DROP_REASON_DISABLED:
|
||||
LOGI("Dropped event because input dispatch is disabled.");
|
||||
reason = "inbound event was dropped because input dispatch is disabled";
|
||||
break;
|
||||
case DROP_REASON_APP_SWITCH:
|
||||
LOGI("Dropped event because of pending overdue app switch.");
|
||||
reason = "inbound event was dropped because of pending overdue app switch";
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (entry->type) {
|
||||
case EventEntry::TYPE_KEY:
|
||||
synthesizeCancelationEventsForAllConnectionsLocked(
|
||||
InputState::CANCEL_NON_POINTER_EVENTS, reason);
|
||||
break;
|
||||
case EventEntry::TYPE_MOTION: {
|
||||
MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
|
||||
if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
|
||||
synthesizeCancelationEventsForAllConnectionsLocked(
|
||||
InputState::CANCEL_POINTER_EVENTS, reason);
|
||||
} else {
|
||||
synthesizeCancelationEventsForAllConnectionsLocked(
|
||||
InputState::CANCEL_NON_POINTER_EVENTS, reason);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool InputDispatcher::isAppSwitchKeyCode(int32_t keyCode) {
|
||||
return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
|
||||
}
|
||||
|
||||
bool InputDispatcher::isAppSwitchKeyEventLocked(KeyEntry* keyEntry) {
|
||||
return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
|
||||
&& isAppSwitchKeyCode(keyEntry->keyCode)
|
||||
&& isEventFromTrustedSourceLocked(keyEntry)
|
||||
&& (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
|
||||
}
|
||||
|
||||
bool InputDispatcher::isAppSwitchPendingLocked() {
|
||||
return mAppSwitchDueTime != LONG_LONG_MAX;
|
||||
}
|
||||
|
||||
bool InputDispatcher::detectPendingAppSwitchLocked(KeyEntry* inboundKeyEntry) {
|
||||
if (inboundKeyEntry->action == AKEY_EVENT_ACTION_UP
|
||||
&& ! (inboundKeyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
|
||||
&& isAppSwitchKey(inboundKeyEntry->keyCode)
|
||||
&& isEventFromReliableSourceLocked(inboundKeyEntry)) {
|
||||
#if DEBUG_APP_SWITCH
|
||||
LOGD("App switch is pending!");
|
||||
#endif
|
||||
mAppSwitchDueTime = inboundKeyEntry->eventTime + APP_SWITCH_TIMEOUT;
|
||||
return true; // need wake
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void InputDispatcher::resetPendingAppSwitchLocked(bool handled) {
|
||||
mAppSwitchDueTime = LONG_LONG_MAX;
|
||||
|
||||
|
@ -489,12 +541,10 @@ void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) {
|
|||
mAllocator.releaseEventEntry(entry);
|
||||
}
|
||||
|
||||
bool InputDispatcher::isEventFromReliableSourceLocked(EventEntry* entry) {
|
||||
bool InputDispatcher::isEventFromTrustedSourceLocked(EventEntry* entry) {
|
||||
InjectionState* injectionState = entry->injectionState;
|
||||
return ! injectionState
|
||||
|| injectionState->injectorUid == 0
|
||||
|| mPolicy->checkInjectEventsPermissionNonReentrant(
|
||||
injectionState->injectorPid, injectionState->injectorUid);
|
||||
|| hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid);
|
||||
}
|
||||
|
||||
void InputDispatcher::resetKeyRepeatLocked() {
|
||||
|
@ -509,7 +559,7 @@ InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(
|
|||
KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
|
||||
|
||||
// Reuse the repeated key entry if it is otherwise unreferenced.
|
||||
uint32_t policyFlags = entry->policyFlags & POLICY_FLAG_RAW_MASK;
|
||||
uint32_t policyFlags = entry->policyFlags & (POLICY_FLAG_RAW_MASK | POLICY_FLAG_PASS_TO_USER);
|
||||
if (entry->refCount == 1) {
|
||||
mAllocator.recycleKeyEntry(entry);
|
||||
entry->eventTime = currentTime;
|
||||
|
@ -565,7 +615,7 @@ bool InputDispatcher::dispatchKeyLocked(
|
|||
if (! dropEvent && mFocusedWindow) {
|
||||
trusted = checkInjectionPermission(mFocusedWindow, entry->injectionState);
|
||||
} else {
|
||||
trusted = isEventFromReliableSourceLocked(entry);
|
||||
trusted = isEventFromTrustedSourceLocked(entry);
|
||||
}
|
||||
if (trusted) {
|
||||
CommandEntry* commandEntry = postCommandLocked(
|
||||
|
@ -793,9 +843,11 @@ void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTi
|
|||
prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
|
||||
resumeWithAppendedMotionSample);
|
||||
} else {
|
||||
LOGW("Framework requested delivery of an input event to channel '%s' but it "
|
||||
"is not registered with the input dispatcher.",
|
||||
#if DEBUG_FOCUS
|
||||
LOGD("Dropping event delivery to target with channel '%s' because it "
|
||||
"is no longer registered with the input dispatcher.",
|
||||
inputTarget.inputChannel->getName().string());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -876,7 +928,9 @@ void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout
|
|||
ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
|
||||
if (connectionIndex >= 0) {
|
||||
sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
|
||||
connection->inputState.setOutOfSync();
|
||||
synthesizeCancelationEventsForConnectionLocked(
|
||||
connection, InputState::CANCEL_ALL_EVENTS,
|
||||
"application not responding");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1236,7 +1290,9 @@ Failed:
|
|||
} else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
|
||||
// First pointer went down.
|
||||
if (mTouchState.down) {
|
||||
LOGW("Pointer down received while already down.");
|
||||
#if DEBUG_FOCUS
|
||||
LOGD("Pointer down received while already down.");
|
||||
#endif
|
||||
}
|
||||
} else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
|
||||
// One pointer went up.
|
||||
|
@ -1307,23 +1363,19 @@ void InputDispatcher::addMonitoringTargetsLocked() {
|
|||
bool InputDispatcher::checkInjectionPermission(const InputWindow* window,
|
||||
const InjectionState* injectionState) {
|
||||
if (injectionState
|
||||
&& injectionState->injectorUid > 0
|
||||
&& (window == NULL || window->ownerUid != injectionState->injectorUid)) {
|
||||
bool result = mPolicy->checkInjectEventsPermissionNonReentrant(
|
||||
injectionState->injectorPid, injectionState->injectorUid);
|
||||
if (! result) {
|
||||
if (window) {
|
||||
LOGW("Permission denied: injecting event from pid %d uid %d to window "
|
||||
"with input channel %s owned by uid %d",
|
||||
injectionState->injectorPid, injectionState->injectorUid,
|
||||
window->inputChannel->getName().string(),
|
||||
window->ownerUid);
|
||||
} else {
|
||||
LOGW("Permission denied: injecting event from pid %d uid %d",
|
||||
injectionState->injectorPid, injectionState->injectorUid);
|
||||
}
|
||||
return false;
|
||||
&& (window == NULL || window->ownerUid != injectionState->injectorUid)
|
||||
&& !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
|
||||
if (window) {
|
||||
LOGW("Permission denied: injecting event from pid %d uid %d to window "
|
||||
"with input channel %s owned by uid %d",
|
||||
injectionState->injectorPid, injectionState->injectorUid,
|
||||
window->inputChannel->getName().string(),
|
||||
window->ownerUid);
|
||||
} else {
|
||||
LOGW("Permission denied: injecting event from pid %d uid %d",
|
||||
injectionState->injectorPid, injectionState->injectorUid);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1408,8 +1460,10 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
|
|||
// Skip this event if the connection status is not normal.
|
||||
// We don't want to enqueue additional outbound events if the connection is broken.
|
||||
if (connection->status != Connection::STATUS_NORMAL) {
|
||||
LOGW("channel '%s' ~ Dropping event because the channel status is %s",
|
||||
#if DEBUG_DISPATCH_CYCLE
|
||||
LOGD("channel '%s' ~ Dropping event because the channel status is %s",
|
||||
connection->getInputChannelName(), connection->getStatusLabel());
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1508,40 +1562,6 @@ void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
|
|||
}
|
||||
}
|
||||
|
||||
// Bring the input state back in line with reality in case it drifted off during an ANR.
|
||||
if (connection->inputState.isOutOfSync()) {
|
||||
mTempCancelationEvents.clear();
|
||||
connection->inputState.synthesizeCancelationEvents(& mAllocator, mTempCancelationEvents);
|
||||
connection->inputState.resetOutOfSync();
|
||||
|
||||
if (! mTempCancelationEvents.isEmpty()) {
|
||||
LOGI("channel '%s' ~ Generated %d cancelation events to bring channel back in sync "
|
||||
"with reality.",
|
||||
connection->getInputChannelName(), mTempCancelationEvents.size());
|
||||
|
||||
for (size_t i = 0; i < mTempCancelationEvents.size(); i++) {
|
||||
EventEntry* cancelationEventEntry = mTempCancelationEvents.itemAt(i);
|
||||
switch (cancelationEventEntry->type) {
|
||||
case EventEntry::TYPE_KEY:
|
||||
logOutboundKeyDetailsLocked(" ",
|
||||
static_cast<KeyEntry*>(cancelationEventEntry));
|
||||
break;
|
||||
case EventEntry::TYPE_MOTION:
|
||||
logOutboundMotionDetailsLocked(" ",
|
||||
static_cast<MotionEntry*>(cancelationEventEntry));
|
||||
break;
|
||||
}
|
||||
|
||||
DispatchEntry* cancelationDispatchEntry =
|
||||
mAllocator.obtainDispatchEntry(cancelationEventEntry,
|
||||
0, inputTarget->xOffset, inputTarget->yOffset); // increments ref
|
||||
connection->outboundQueue.enqueueAtTail(cancelationDispatchEntry);
|
||||
|
||||
mAllocator.releaseEventEntry(cancelationEventEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is a new event.
|
||||
// Enqueue a new dispatch entry onto the outbound queue for this connection.
|
||||
DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry, // increments ref
|
||||
|
@ -1635,7 +1655,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
|
|||
if (status) {
|
||||
LOGE("channel '%s' ~ Could not publish key event, "
|
||||
"status=%d", connection->getInputChannelName(), status);
|
||||
abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
|
||||
abortBrokenDispatchCycleLocked(currentTime, connection);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
@ -1685,7 +1705,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
|
|||
if (status) {
|
||||
LOGE("channel '%s' ~ Could not publish motion event, "
|
||||
"status=%d", connection->getInputChannelName(), status);
|
||||
abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
|
||||
abortBrokenDispatchCycleLocked(currentTime, connection);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1706,7 +1726,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
|
|||
LOGE("channel '%s' ~ Could not append motion sample "
|
||||
"for a reason other than out of memory, status=%d",
|
||||
connection->getInputChannelName(), status);
|
||||
abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
|
||||
abortBrokenDispatchCycleLocked(currentTime, connection);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1727,7 +1747,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
|
|||
if (status) {
|
||||
LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
|
||||
connection->getInputChannelName(), status);
|
||||
abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
|
||||
abortBrokenDispatchCycleLocked(currentTime, connection);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1764,7 +1784,7 @@ void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
|
|||
if (status) {
|
||||
LOGE("channel '%s' ~ Could not reset publisher, status=%d",
|
||||
connection->getInputChannelName(), status);
|
||||
abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
|
||||
abortBrokenDispatchCycleLocked(currentTime, connection);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1806,28 +1826,23 @@ void InputDispatcher::startNextDispatchCycleLocked(nsecs_t currentTime,
|
|||
deactivateConnectionLocked(connection.get());
|
||||
}
|
||||
|
||||
void InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime,
|
||||
const sp<Connection>& connection, bool broken) {
|
||||
void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
|
||||
const sp<Connection>& connection) {
|
||||
#if DEBUG_DISPATCH_CYCLE
|
||||
LOGD("channel '%s' ~ abortDispatchCycle - broken=%s",
|
||||
LOGD("channel '%s' ~ abortBrokenDispatchCycle - broken=%s",
|
||||
connection->getInputChannelName(), toString(broken));
|
||||
#endif
|
||||
|
||||
// Input state will no longer be realistic.
|
||||
connection->inputState.setOutOfSync();
|
||||
|
||||
// Clear the outbound queue.
|
||||
drainOutboundQueueLocked(connection.get());
|
||||
|
||||
// Handle the case where the connection appears to be unrecoverably broken.
|
||||
// The connection appears to be unrecoverably broken.
|
||||
// Ignore already broken or zombie connections.
|
||||
if (broken) {
|
||||
if (connection->status == Connection::STATUS_NORMAL) {
|
||||
connection->status = Connection::STATUS_BROKEN;
|
||||
if (connection->status == Connection::STATUS_NORMAL) {
|
||||
connection->status = Connection::STATUS_BROKEN;
|
||||
|
||||
// Notify other system components.
|
||||
onDispatchCycleBrokenLocked(currentTime, connection);
|
||||
}
|
||||
// Notify other system components.
|
||||
onDispatchCycleBrokenLocked(currentTime, connection);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1862,7 +1877,7 @@ int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data
|
|||
if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
|
||||
LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
|
||||
"events=0x%x", connection->getInputChannelName(), events);
|
||||
d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
|
||||
d->abortBrokenDispatchCycleLocked(currentTime, connection);
|
||||
d->runCommandsLockedInterruptible();
|
||||
return 0; // remove the callback
|
||||
}
|
||||
|
@ -1877,7 +1892,7 @@ int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data
|
|||
if (status) {
|
||||
LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
|
||||
connection->getInputChannelName(), status);
|
||||
d->abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
|
||||
d->abortBrokenDispatchCycleLocked(currentTime, connection);
|
||||
d->runCommandsLockedInterruptible();
|
||||
return 0; // remove the callback
|
||||
}
|
||||
|
@ -1888,6 +1903,77 @@ int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data
|
|||
} // release lock
|
||||
}
|
||||
|
||||
void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked(
|
||||
InputState::CancelationOptions options, const char* reason) {
|
||||
for (size_t i = 0; i < mConnectionsByReceiveFd.size(); i++) {
|
||||
synthesizeCancelationEventsForConnectionLocked(
|
||||
mConnectionsByReceiveFd.valueAt(i), options, reason);
|
||||
}
|
||||
}
|
||||
|
||||
void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked(
|
||||
const sp<InputChannel>& channel, InputState::CancelationOptions options,
|
||||
const char* reason) {
|
||||
ssize_t index = getConnectionIndexLocked(channel);
|
||||
if (index >= 0) {
|
||||
synthesizeCancelationEventsForConnectionLocked(
|
||||
mConnectionsByReceiveFd.valueAt(index), options, reason);
|
||||
}
|
||||
}
|
||||
|
||||
void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
|
||||
const sp<Connection>& connection, InputState::CancelationOptions options,
|
||||
const char* reason) {
|
||||
nsecs_t currentTime = now();
|
||||
|
||||
mTempCancelationEvents.clear();
|
||||
connection->inputState.synthesizeCancelationEvents(currentTime, & mAllocator,
|
||||
mTempCancelationEvents, options);
|
||||
|
||||
if (! mTempCancelationEvents.isEmpty()
|
||||
&& connection->status != Connection::STATUS_BROKEN) {
|
||||
#if DEBUG_OUTBOUND_EVENT_DETAILS
|
||||
LOGD("channel '%s' ~ Synthesized %d cancelation events to bring channel back in sync "
|
||||
"with reality: %s, options=%d.",
|
||||
connection->getInputChannelName(), mTempCancelationEvents.size(), reason, options);
|
||||
#endif
|
||||
for (size_t i = 0; i < mTempCancelationEvents.size(); i++) {
|
||||
EventEntry* cancelationEventEntry = mTempCancelationEvents.itemAt(i);
|
||||
switch (cancelationEventEntry->type) {
|
||||
case EventEntry::TYPE_KEY:
|
||||
logOutboundKeyDetailsLocked("cancel - ",
|
||||
static_cast<KeyEntry*>(cancelationEventEntry));
|
||||
break;
|
||||
case EventEntry::TYPE_MOTION:
|
||||
logOutboundMotionDetailsLocked("cancel - ",
|
||||
static_cast<MotionEntry*>(cancelationEventEntry));
|
||||
break;
|
||||
}
|
||||
|
||||
int32_t xOffset, yOffset;
|
||||
const InputWindow* window = getWindowLocked(connection->inputChannel);
|
||||
if (window) {
|
||||
xOffset = -window->frameLeft;
|
||||
yOffset = -window->frameTop;
|
||||
} else {
|
||||
xOffset = 0;
|
||||
yOffset = 0;
|
||||
}
|
||||
|
||||
DispatchEntry* cancelationDispatchEntry =
|
||||
mAllocator.obtainDispatchEntry(cancelationEventEntry, // increments ref
|
||||
0, xOffset, yOffset);
|
||||
connection->outboundQueue.enqueueAtTail(cancelationDispatchEntry);
|
||||
|
||||
mAllocator.releaseEventEntry(cancelationEventEntry);
|
||||
}
|
||||
|
||||
if (!connection->outboundQueue.headSentinel.next->inProgress) {
|
||||
startDispatchCycleLocked(currentTime, connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InputDispatcher::MotionEntry*
|
||||
InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds) {
|
||||
assert(pointerIds.value != 0);
|
||||
|
@ -1999,6 +2085,9 @@ void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t sou
|
|||
return;
|
||||
}
|
||||
|
||||
mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
|
||||
keyCode, scanCode, /*byref*/ policyFlags);
|
||||
|
||||
bool needWake;
|
||||
{ // acquire lock
|
||||
AutoMutex _l(mLock);
|
||||
|
@ -2041,6 +2130,8 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t
|
|||
return;
|
||||
}
|
||||
|
||||
mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
|
||||
|
||||
bool needWake;
|
||||
{ // acquire lock
|
||||
AutoMutex _l(mLock);
|
||||
|
@ -2165,6 +2256,16 @@ NoBatchingOrStreaming:;
|
|||
}
|
||||
}
|
||||
|
||||
void InputDispatcher::notifySwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
|
||||
uint32_t policyFlags) {
|
||||
#if DEBUG_INBOUND_EVENT_DETAILS
|
||||
LOGD("notifySwitch - switchCode=%d, switchValue=%d, policyFlags=0x%x",
|
||||
switchCode, switchValue, policyFlags);
|
||||
#endif
|
||||
|
||||
mPolicy->notifySwitch(when, switchCode, switchValue, policyFlags);
|
||||
}
|
||||
|
||||
int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
|
||||
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
|
||||
#if DEBUG_INBOUND_EVENT_DETAILS
|
||||
|
@ -2174,27 +2275,84 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
|
|||
#endif
|
||||
|
||||
nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
|
||||
bool trusted = hasInjectionPermission(injectorPid, injectorUid);
|
||||
|
||||
InjectionState* injectionState;
|
||||
bool needWake;
|
||||
{ // acquire lock
|
||||
AutoMutex _l(mLock);
|
||||
|
||||
EventEntry* injectedEntry = createEntryFromInjectedInputEventLocked(event);
|
||||
if (! injectedEntry) {
|
||||
EventEntry* injectedEntry;
|
||||
switch (event->getType()) {
|
||||
case AINPUT_EVENT_TYPE_KEY: {
|
||||
const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
|
||||
int32_t action = keyEvent->getAction();
|
||||
if (! validateKeyEvent(action)) {
|
||||
return INPUT_EVENT_INJECTION_FAILED;
|
||||
}
|
||||
|
||||
injectionState = mAllocator.obtainInjectionState(injectorPid, injectorUid);
|
||||
if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
|
||||
injectionState->injectionIsAsync = true;
|
||||
nsecs_t eventTime = keyEvent->getEventTime();
|
||||
int32_t deviceId = keyEvent->getDeviceId();
|
||||
int32_t flags = keyEvent->getFlags();
|
||||
int32_t keyCode = keyEvent->getKeyCode();
|
||||
int32_t scanCode = keyEvent->getScanCode();
|
||||
uint32_t policyFlags = POLICY_FLAG_INJECTED;
|
||||
if (trusted) {
|
||||
mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
|
||||
keyCode, scanCode, /*byref*/ policyFlags);
|
||||
}
|
||||
|
||||
injectionState->refCount += 1;
|
||||
injectedEntry->injectionState = injectionState;
|
||||
mLock.lock();
|
||||
injectedEntry = mAllocator.obtainKeyEntry(eventTime, deviceId, keyEvent->getSource(),
|
||||
policyFlags, action, flags, keyCode, scanCode, keyEvent->getMetaState(),
|
||||
keyEvent->getRepeatCount(), keyEvent->getDownTime());
|
||||
break;
|
||||
}
|
||||
|
||||
needWake = enqueueInboundEventLocked(injectedEntry);
|
||||
} // release lock
|
||||
case AINPUT_EVENT_TYPE_MOTION: {
|
||||
const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
|
||||
int32_t action = motionEvent->getAction();
|
||||
size_t pointerCount = motionEvent->getPointerCount();
|
||||
const int32_t* pointerIds = motionEvent->getPointerIds();
|
||||
if (! validateMotionEvent(action, pointerCount, pointerIds)) {
|
||||
return INPUT_EVENT_INJECTION_FAILED;
|
||||
}
|
||||
|
||||
nsecs_t eventTime = motionEvent->getEventTime();
|
||||
uint32_t policyFlags = POLICY_FLAG_INJECTED;
|
||||
if (trusted) {
|
||||
mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
|
||||
}
|
||||
|
||||
mLock.lock();
|
||||
const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
|
||||
const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
|
||||
MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
|
||||
motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
|
||||
action, motionEvent->getFlags(),
|
||||
motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
|
||||
motionEvent->getXPrecision(), motionEvent->getYPrecision(),
|
||||
motionEvent->getDownTime(), uint32_t(pointerCount),
|
||||
pointerIds, samplePointerCoords);
|
||||
for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
|
||||
sampleEventTimes += 1;
|
||||
samplePointerCoords += pointerCount;
|
||||
mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
|
||||
}
|
||||
injectedEntry = motionEntry;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
LOGW("Cannot inject event of type %d", event->getType());
|
||||
return INPUT_EVENT_INJECTION_FAILED;
|
||||
}
|
||||
|
||||
InjectionState* injectionState = mAllocator.obtainInjectionState(injectorPid, injectorUid);
|
||||
if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
|
||||
injectionState->injectionIsAsync = true;
|
||||
}
|
||||
|
||||
injectionState->refCount += 1;
|
||||
injectedEntry->injectionState = injectionState;
|
||||
|
||||
bool needWake = enqueueInboundEventLocked(injectedEntry);
|
||||
mLock.unlock();
|
||||
|
||||
if (needWake) {
|
||||
mLooper->wake();
|
||||
|
@ -2260,6 +2418,11 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
|
|||
return injectionResult;
|
||||
}
|
||||
|
||||
bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) {
|
||||
return injectorUid == 0
|
||||
|| mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
|
||||
}
|
||||
|
||||
void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
|
||||
InjectionState* injectionState = entry->injectionState;
|
||||
if (injectionState) {
|
||||
|
@ -2310,59 +2473,6 @@ void InputDispatcher::decrementPendingForegroundDispatchesLocked(EventEntry* ent
|
|||
}
|
||||
}
|
||||
|
||||
InputDispatcher::EventEntry* InputDispatcher::createEntryFromInjectedInputEventLocked(
|
||||
const InputEvent* event) {
|
||||
switch (event->getType()) {
|
||||
case AINPUT_EVENT_TYPE_KEY: {
|
||||
const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
|
||||
if (! validateKeyEvent(keyEvent->getAction())) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t policyFlags = POLICY_FLAG_INJECTED;
|
||||
|
||||
KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
|
||||
keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags,
|
||||
keyEvent->getAction(), keyEvent->getFlags(),
|
||||
keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
|
||||
keyEvent->getRepeatCount(), keyEvent->getDownTime());
|
||||
return keyEntry;
|
||||
}
|
||||
|
||||
case AINPUT_EVENT_TYPE_MOTION: {
|
||||
const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
|
||||
if (! validateMotionEvent(motionEvent->getAction(),
|
||||
motionEvent->getPointerCount(), motionEvent->getPointerIds())) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t policyFlags = POLICY_FLAG_INJECTED;
|
||||
|
||||
const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
|
||||
const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
|
||||
size_t pointerCount = motionEvent->getPointerCount();
|
||||
|
||||
MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
|
||||
motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
|
||||
motionEvent->getAction(), motionEvent->getFlags(),
|
||||
motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
|
||||
motionEvent->getXPrecision(), motionEvent->getYPrecision(),
|
||||
motionEvent->getDownTime(), uint32_t(pointerCount),
|
||||
motionEvent->getPointerIds(), samplePointerCoords);
|
||||
for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
|
||||
sampleEventTimes += 1;
|
||||
samplePointerCoords += pointerCount;
|
||||
mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
|
||||
}
|
||||
return motionEntry;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const InputWindow* InputDispatcher::getWindowLocked(const sp<InputChannel>& inputChannel) {
|
||||
for (size_t i = 0; i < mWindows.size(); i++) {
|
||||
const InputWindow* window = & mWindows[i];
|
||||
|
@ -2381,7 +2491,12 @@ void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
|
|||
AutoMutex _l(mLock);
|
||||
|
||||
// Clear old window pointers.
|
||||
mFocusedWindow = NULL;
|
||||
sp<InputChannel> oldFocusedWindowChannel;
|
||||
if (mFocusedWindow) {
|
||||
oldFocusedWindowChannel = mFocusedWindow->inputChannel;
|
||||
mFocusedWindow = NULL;
|
||||
}
|
||||
|
||||
mWindows.clear();
|
||||
|
||||
// Loop over new windows and rebuild the necessary window pointers for
|
||||
|
@ -2397,6 +2512,24 @@ void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
|
|||
}
|
||||
}
|
||||
|
||||
if (oldFocusedWindowChannel != NULL) {
|
||||
if (!mFocusedWindow || oldFocusedWindowChannel != mFocusedWindow->inputChannel) {
|
||||
#if DEBUG_FOCUS
|
||||
LOGD("Focus left window: %s",
|
||||
oldFocusedWindowChannel->getName().string());
|
||||
#endif
|
||||
synthesizeCancelationEventsForInputChannelLocked(oldFocusedWindowChannel,
|
||||
InputState::CANCEL_NON_POINTER_EVENTS, "focus left window");
|
||||
oldFocusedWindowChannel.clear();
|
||||
}
|
||||
}
|
||||
if (mFocusedWindow && oldFocusedWindowChannel == NULL) {
|
||||
#if DEBUG_FOCUS
|
||||
LOGD("Focus entered window: %s",
|
||||
mFocusedWindow->inputChannel->getName().string());
|
||||
#endif
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mTouchState.windows.size(); ) {
|
||||
TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i);
|
||||
const InputWindow* window = getWindowLocked(touchedWindow.channel);
|
||||
|
@ -2404,12 +2537,17 @@ void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
|
|||
touchedWindow.window = window;
|
||||
i += 1;
|
||||
} else {
|
||||
#if DEBUG_FOCUS
|
||||
LOGD("Touched window was removed: %s", touchedWindow.channel->getName().string());
|
||||
#endif
|
||||
mTouchState.windows.removeAt(i);
|
||||
synthesizeCancelationEventsForInputChannelLocked(touchedWindow.channel,
|
||||
InputState::CANCEL_POINTER_EVENTS, "touched window was removed");
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG_FOCUS
|
||||
logDispatchStateLocked();
|
||||
//logDispatchStateLocked();
|
||||
#endif
|
||||
} // release lock
|
||||
|
||||
|
@ -2432,7 +2570,7 @@ void InputDispatcher::setFocusedApplication(const InputApplication* inputApplica
|
|||
}
|
||||
|
||||
#if DEBUG_FOCUS
|
||||
logDispatchStateLocked();
|
||||
//logDispatchStateLocked();
|
||||
#endif
|
||||
} // release lock
|
||||
|
||||
|
@ -2469,7 +2607,7 @@ void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
|
|||
}
|
||||
|
||||
#if DEBUG_FOCUS
|
||||
logDispatchStateLocked();
|
||||
//logDispatchStateLocked();
|
||||
#endif
|
||||
} // release lock
|
||||
|
||||
|
@ -2635,11 +2773,10 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
|
|||
for (size_t i = 0; i < mActiveConnections.size(); i++) {
|
||||
const Connection* connection = mActiveConnections[i];
|
||||
dump.appendFormat(INDENT2 "%d: '%s', status=%s, outboundQueueLength=%u"
|
||||
"inputState.isNeutral=%s, inputState.isOutOfSync=%s\n",
|
||||
"inputState.isNeutral=%s\n",
|
||||
i, connection->getInputChannelName(), connection->getStatusLabel(),
|
||||
connection->outboundQueue.count(),
|
||||
toString(connection->inputState.isNeutral()),
|
||||
toString(connection->inputState.isOutOfSync()));
|
||||
toString(connection->inputState.isNeutral()));
|
||||
}
|
||||
} else {
|
||||
dump.append(INDENT "ActiveConnections: <none>\n");
|
||||
|
@ -2720,7 +2857,7 @@ status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputCh
|
|||
mLooper->removeFd(inputChannel->getReceivePipeFd());
|
||||
|
||||
nsecs_t currentTime = now();
|
||||
abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
|
||||
abortBrokenDispatchCycleLocked(currentTime, connection);
|
||||
|
||||
runCommandsLockedInterruptible();
|
||||
} // release lock
|
||||
|
@ -2901,11 +3038,12 @@ InputDispatcher::Allocator::obtainInjectionState(int32_t injectorPid, int32_t in
|
|||
}
|
||||
|
||||
void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
|
||||
nsecs_t eventTime) {
|
||||
nsecs_t eventTime, uint32_t policyFlags) {
|
||||
entry->type = type;
|
||||
entry->refCount = 1;
|
||||
entry->dispatchInProgress = false;
|
||||
entry->eventTime = eventTime;
|
||||
entry->policyFlags = policyFlags;
|
||||
entry->injectionState = NULL;
|
||||
}
|
||||
|
||||
|
@ -2919,7 +3057,7 @@ void InputDispatcher::Allocator::releaseEventEntryInjectionState(EventEntry* ent
|
|||
InputDispatcher::ConfigurationChangedEntry*
|
||||
InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
|
||||
ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
|
||||
initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime);
|
||||
initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime, 0);
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
@ -2928,11 +3066,10 @@ InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t ev
|
|||
int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
|
||||
int32_t repeatCount, nsecs_t downTime) {
|
||||
KeyEntry* entry = mKeyEntryPool.alloc();
|
||||
initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime);
|
||||
initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime, policyFlags);
|
||||
|
||||
entry->deviceId = deviceId;
|
||||
entry->source = source;
|
||||
entry->policyFlags = policyFlags;
|
||||
entry->action = action;
|
||||
entry->flags = flags;
|
||||
entry->keyCode = keyCode;
|
||||
|
@ -2951,12 +3088,11 @@ InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsec
|
|||
nsecs_t downTime, uint32_t pointerCount,
|
||||
const int32_t* pointerIds, const PointerCoords* pointerCoords) {
|
||||
MotionEntry* entry = mMotionEntryPool.alloc();
|
||||
initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime);
|
||||
initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime, policyFlags);
|
||||
|
||||
entry->eventTime = eventTime;
|
||||
entry->deviceId = deviceId;
|
||||
entry->source = source;
|
||||
entry->policyFlags = policyFlags;
|
||||
entry->action = action;
|
||||
entry->flags = flags;
|
||||
entry->metaState = metaState;
|
||||
|
@ -3103,8 +3239,7 @@ uint32_t InputDispatcher::MotionEntry::countSamples() const {
|
|||
|
||||
// --- InputDispatcher::InputState ---
|
||||
|
||||
InputDispatcher::InputState::InputState() :
|
||||
mIsOutOfSync(false) {
|
||||
InputDispatcher::InputState::InputState() {
|
||||
}
|
||||
|
||||
InputDispatcher::InputState::~InputState() {
|
||||
|
@ -3114,20 +3249,6 @@ bool InputDispatcher::InputState::isNeutral() const {
|
|||
return mKeyMementos.isEmpty() && mMotionMementos.isEmpty();
|
||||
}
|
||||
|
||||
bool InputDispatcher::InputState::isOutOfSync() const {
|
||||
return mIsOutOfSync;
|
||||
}
|
||||
|
||||
void InputDispatcher::InputState::setOutOfSync() {
|
||||
if (! isNeutral()) {
|
||||
mIsOutOfSync = true;
|
||||
}
|
||||
}
|
||||
|
||||
void InputDispatcher::InputState::resetOutOfSync() {
|
||||
mIsOutOfSync = false;
|
||||
}
|
||||
|
||||
InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackEvent(
|
||||
const EventEntry* entry) {
|
||||
switch (entry->type) {
|
||||
|
@ -3154,9 +3275,6 @@ InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackKey(
|
|||
switch (action) {
|
||||
case AKEY_EVENT_ACTION_UP:
|
||||
mKeyMementos.removeAt(i);
|
||||
if (isNeutral()) {
|
||||
mIsOutOfSync = false;
|
||||
}
|
||||
return CONSISTENT;
|
||||
|
||||
case AKEY_EVENT_ACTION_DOWN:
|
||||
|
@ -3196,9 +3314,6 @@ InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackMotio
|
|||
case AMOTION_EVENT_ACTION_UP:
|
||||
case AMOTION_EVENT_ACTION_CANCEL:
|
||||
mMotionMementos.removeAt(i);
|
||||
if (isNeutral()) {
|
||||
mIsOutOfSync = false;
|
||||
}
|
||||
return CONSISTENT;
|
||||
|
||||
case AMOTION_EVENT_ACTION_DOWN:
|
||||
|
@ -3256,30 +3371,52 @@ void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry*
|
|||
}
|
||||
}
|
||||
|
||||
void InputDispatcher::InputState::synthesizeCancelationEvents(
|
||||
Allocator* allocator, Vector<EventEntry*>& outEvents) const {
|
||||
for (size_t i = 0; i < mKeyMementos.size(); i++) {
|
||||
void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime,
|
||||
Allocator* allocator, Vector<EventEntry*>& outEvents,
|
||||
CancelationOptions options) {
|
||||
for (size_t i = 0; i < mKeyMementos.size(); ) {
|
||||
const KeyMemento& memento = mKeyMementos.itemAt(i);
|
||||
outEvents.push(allocator->obtainKeyEntry(now(),
|
||||
memento.deviceId, memento.source, 0,
|
||||
AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_CANCELED,
|
||||
memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
|
||||
if (shouldCancelEvent(memento.source, options)) {
|
||||
outEvents.push(allocator->obtainKeyEntry(currentTime,
|
||||
memento.deviceId, memento.source, 0,
|
||||
AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_CANCELED,
|
||||
memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
|
||||
mKeyMementos.removeAt(i);
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mMotionMementos.size(); i++) {
|
||||
const MotionMemento& memento = mMotionMementos.itemAt(i);
|
||||
outEvents.push(allocator->obtainMotionEntry(now(),
|
||||
memento.deviceId, memento.source, 0,
|
||||
AMOTION_EVENT_ACTION_CANCEL, 0, 0, 0,
|
||||
memento.xPrecision, memento.yPrecision, memento.downTime,
|
||||
memento.pointerCount, memento.pointerIds, memento.pointerCoords));
|
||||
if (shouldCancelEvent(memento.source, options)) {
|
||||
outEvents.push(allocator->obtainMotionEntry(currentTime,
|
||||
memento.deviceId, memento.source, 0,
|
||||
AMOTION_EVENT_ACTION_CANCEL, 0, 0, 0,
|
||||
memento.xPrecision, memento.yPrecision, memento.downTime,
|
||||
memento.pointerCount, memento.pointerIds, memento.pointerCoords));
|
||||
mMotionMementos.removeAt(i);
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputDispatcher::InputState::clear() {
|
||||
mKeyMementos.clear();
|
||||
mMotionMementos.clear();
|
||||
mIsOutOfSync = false;
|
||||
}
|
||||
|
||||
bool InputDispatcher::InputState::shouldCancelEvent(int32_t eventSource,
|
||||
CancelationOptions options) {
|
||||
switch (options) {
|
||||
case CANCEL_POINTER_EVENTS:
|
||||
return eventSource & AINPUT_SOURCE_CLASS_POINTER;
|
||||
case CANCEL_NON_POINTER_EVENTS:
|
||||
return !(eventSource & AINPUT_SOURCE_CLASS_POINTER);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -796,10 +796,6 @@ int32_t InputMapper::getMetaState() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool InputMapper::applyStandardPolicyActions(nsecs_t when, int32_t policyActions) {
|
||||
return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
|
||||
}
|
||||
|
||||
|
||||
// --- SwitchInputMapper ---
|
||||
|
||||
|
@ -823,11 +819,7 @@ void SwitchInputMapper::process(const RawEvent* rawEvent) {
|
|||
}
|
||||
|
||||
void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
|
||||
uint32_t policyFlags = 0;
|
||||
int32_t policyActions = getPolicy()->interceptSwitch(
|
||||
when, switchCode, switchValue, policyFlags);
|
||||
|
||||
applyStandardPolicyActions(when, policyActions);
|
||||
getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
|
||||
}
|
||||
|
||||
int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
|
||||
|
@ -983,29 +975,9 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
|
|||
getContext()->updateGlobalMetaState();
|
||||
}
|
||||
|
||||
applyPolicyAndDispatch(when, policyFlags, down, keyCode, scanCode, newMetaState, downTime);
|
||||
}
|
||||
|
||||
void KeyboardInputMapper::applyPolicyAndDispatch(nsecs_t when, uint32_t policyFlags, bool down,
|
||||
int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
|
||||
int32_t policyActions = getPolicy()->interceptKey(when,
|
||||
getDeviceId(), down, keyCode, scanCode, policyFlags);
|
||||
|
||||
if (! applyStandardPolicyActions(when, policyActions)) {
|
||||
return; // event dropped
|
||||
}
|
||||
|
||||
int32_t keyEventAction = down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP;
|
||||
int32_t keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM;
|
||||
if (policyFlags & POLICY_FLAG_WOKE_HERE) {
|
||||
keyEventFlags |= AKEY_EVENT_FLAG_WOKE_HERE;
|
||||
}
|
||||
if (policyFlags & POLICY_FLAG_VIRTUAL) {
|
||||
keyEventFlags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
|
||||
}
|
||||
|
||||
getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
|
||||
keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
|
||||
down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
|
||||
AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
|
||||
}
|
||||
|
||||
ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
|
||||
|
@ -1215,26 +1187,13 @@ void TrackballInputMapper::sync(nsecs_t when) {
|
|||
}
|
||||
} // release lock
|
||||
|
||||
applyPolicyAndDispatch(when, motionEventAction, & pointerCoords, downTime);
|
||||
|
||||
mAccumulator.clear();
|
||||
}
|
||||
|
||||
void TrackballInputMapper::applyPolicyAndDispatch(nsecs_t when, int32_t motionEventAction,
|
||||
PointerCoords* pointerCoords, nsecs_t downTime) {
|
||||
uint32_t policyFlags = 0;
|
||||
int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
|
||||
|
||||
if (! applyStandardPolicyActions(when, policyActions)) {
|
||||
return; // event dropped
|
||||
}
|
||||
|
||||
int32_t metaState = mContext->getGlobalMetaState();
|
||||
int32_t pointerId = 0;
|
||||
|
||||
getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, policyFlags,
|
||||
getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, 0,
|
||||
motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
|
||||
1, & pointerId, pointerCoords, mXPrecision, mYPrecision, downTime);
|
||||
1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
|
||||
|
||||
mAccumulator.clear();
|
||||
}
|
||||
|
||||
int32_t TrackballInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
|
||||
|
@ -2012,15 +1971,7 @@ void TouchInputMapper::reset() {
|
|||
}
|
||||
|
||||
void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
|
||||
// Apply generic policy actions.
|
||||
|
||||
uint32_t policyFlags = 0;
|
||||
int32_t policyActions = getPolicy()->interceptGeneric(when, policyFlags);
|
||||
|
||||
if (! applyStandardPolicyActions(when, policyActions)) {
|
||||
mLastTouch.clear();
|
||||
return; // event dropped
|
||||
}
|
||||
|
||||
// Preprocess pointer data.
|
||||
|
||||
|
@ -2160,24 +2111,11 @@ TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
|
|||
} // release lock
|
||||
|
||||
// Dispatch virtual key.
|
||||
applyPolicyAndDispatchVirtualKey(when, policyFlags, keyEventAction, keyEventFlags,
|
||||
keyCode, scanCode, downTime);
|
||||
return touchResult;
|
||||
}
|
||||
|
||||
void TouchInputMapper::applyPolicyAndDispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
|
||||
int32_t keyEventAction, int32_t keyEventFlags,
|
||||
int32_t keyCode, int32_t scanCode, nsecs_t downTime) {
|
||||
int32_t metaState = mContext->getGlobalMetaState();
|
||||
|
||||
policyFlags |= POLICY_FLAG_VIRTUAL;
|
||||
int32_t policyActions = getPolicy()->interceptKey(when, getDeviceId(),
|
||||
keyEventAction == AKEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
|
||||
|
||||
if (applyStandardPolicyActions(when, policyActions)) {
|
||||
getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
|
||||
keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
|
||||
}
|
||||
getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
|
||||
keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
|
||||
return touchResult;
|
||||
}
|
||||
|
||||
void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
|
||||
|
|
Loading…
Reference in New Issue