/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _UI_INPUT_DISPATCHER_H #define _UI_INPUT_DISPATCHER_H #include "CancelationOptions.h" #include "Entry.h" #include "InjectionState.h" #include "InputDispatcherConfiguration.h" #include "InputDispatcherInterface.h" #include "InputDispatcherPolicyInterface.h" #include "InputState.h" #include "InputTarget.h" #include "Monitor.h" #include "Queue.h" #include "TouchState.h" #include "TouchedWindow.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace android::inputdispatcher { class Connection; /* Dispatches events to input targets. Some functions of the input dispatcher, such as * identifying input targets, are controlled by a separate policy object. * * IMPORTANT INVARIANT: * Because the policy can potentially block or cause re-entrance into the input dispatcher, * the input dispatcher never calls into the policy while holding its internal locks. * The implementation is also carefully designed to recover from scenarios such as an * input channel becoming unregistered while identifying input targets or processing timeouts. * * Methods marked 'Locked' must be called with the lock acquired. * * Methods marked 'LockedInterruptible' must be called with the lock acquired but * may during the course of their execution release the lock, call into the policy, and * then reacquire the lock. The caller is responsible for recovering gracefully. * * A 'LockedInterruptible' method may called a 'Locked' method, but NOT vice-versa. */ class InputDispatcher : public android::InputDispatcherInterface { protected: virtual ~InputDispatcher(); public: explicit InputDispatcher(const sp& policy); virtual void dump(std::string& dump) override; virtual void monitor() override; virtual void dispatchOnce() override; virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override; virtual void notifyKey(const NotifyKeyArgs* args) override; virtual void notifyMotion(const NotifyMotionArgs* args) override; virtual void notifySwitch(const NotifySwitchArgs* args) override; virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override; virtual int32_t injectInputEvent(const InputEvent* event, int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis, uint32_t policyFlags) override; virtual void setInputWindows( const std::vector>& inputWindowHandles, int32_t displayId, const sp& setInputWindowsListener = nullptr) override; virtual void setFocusedApplication( int32_t displayId, const sp& inputApplicationHandle) override; virtual void setFocusedDisplay(int32_t displayId) override; virtual void setInputDispatchMode(bool enabled, bool frozen) override; virtual void setInputFilterEnabled(bool enabled) override; virtual bool transferTouchFocus(const sp& fromToken, const sp& toToken) override; virtual status_t registerInputChannel(const sp& inputChannel, int32_t displayId) override; virtual status_t registerInputMonitor(const sp& inputChannel, int32_t displayId, bool isGestureMonitor) override; virtual status_t unregisterInputChannel(const sp& inputChannel) override; virtual status_t pilferPointers(const sp& token) override; private: enum DropReason { DROP_REASON_NOT_DROPPED = 0, DROP_REASON_POLICY = 1, DROP_REASON_APP_SWITCH = 2, DROP_REASON_DISABLED = 3, DROP_REASON_BLOCKED = 4, DROP_REASON_STALE = 5, }; sp mPolicy; android::InputDispatcherConfiguration mConfig; std::mutex mLock; std::condition_variable mDispatcherIsAlive; sp mLooper; EventEntry* mPendingEvent GUARDED_BY(mLock); Queue mInboundQueue GUARDED_BY(mLock); Queue mRecentQueue GUARDED_BY(mLock); Queue mCommandQueue GUARDED_BY(mLock); DropReason mLastDropReason GUARDED_BY(mLock); void dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) REQUIRES(mLock); // Enqueues an inbound event. Returns true if mLooper->wake() should be called. bool enqueueInboundEventLocked(EventEntry* entry) REQUIRES(mLock); // Cleans up input state when dropping an inbound event. void dropInboundEventLocked(EventEntry* entry, DropReason dropReason) REQUIRES(mLock); // Adds an event to a queue of recent events for debugging purposes. void addRecentEventLocked(EventEntry* entry) REQUIRES(mLock); // App switch latency optimization. bool mAppSwitchSawKeyDown GUARDED_BY(mLock); nsecs_t mAppSwitchDueTime GUARDED_BY(mLock); bool isAppSwitchKeyEvent(KeyEntry* keyEntry); bool isAppSwitchPendingLocked() REQUIRES(mLock); void resetPendingAppSwitchLocked(bool handled) REQUIRES(mLock); // Stale event latency optimization. static bool isStaleEvent(nsecs_t currentTime, EventEntry* entry); // Blocked event latency optimization. Drops old events when the user intends // to transfer focus to a new application. EventEntry* mNextUnblockedEvent GUARDED_BY(mLock); sp findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y, bool addOutsideTargets = false, bool addPortalWindows = false) REQUIRES(mLock); // All registered connections mapped by channel file descriptor. KeyedVector> mConnectionsByFd GUARDED_BY(mLock); struct IBinderHash { std::size_t operator()(const sp& b) const { return std::hash{}(b.get()); } }; std::unordered_map, sp, IBinderHash> mInputChannelsByToken GUARDED_BY(mLock); // Finds the display ID of the gesture monitor identified by the provided token. std::optional findGestureMonitorDisplayByTokenLocked(const sp& token) REQUIRES(mLock); ssize_t getConnectionIndexLocked(const sp& inputChannel) REQUIRES(mLock); // Input channels that will receive a copy of all input events sent to the provided display. std::unordered_map> mGlobalMonitorsByDisplay GUARDED_BY(mLock); // Input channels that will receive pointer events that start within the corresponding display. // These are a bit special when compared to global monitors since they'll cause gesture streams // to continue even when there isn't a touched window,and have the ability to steal the rest of // the pointer stream in order to claim it for a system gesture. std::unordered_map> mGestureMonitorsByDisplay GUARDED_BY(mLock); // Event injection and synchronization. std::condition_variable mInjectionResultAvailable; bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid); void setInjectionResult(EventEntry* entry, int32_t injectionResult); std::condition_variable mInjectionSyncFinished; void incrementPendingForegroundDispatches(EventEntry* entry); void decrementPendingForegroundDispatches(EventEntry* entry); // Key repeat tracking. struct KeyRepeatState { KeyEntry* lastKeyEntry; // or null if no repeat nsecs_t nextRepeatTime; } mKeyRepeatState GUARDED_BY(mLock); void resetKeyRepeatLocked() REQUIRES(mLock); KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime) REQUIRES(mLock); // Key replacement tracking struct KeyReplacement { int32_t keyCode; int32_t deviceId; bool operator==(const KeyReplacement& rhs) const { return keyCode == rhs.keyCode && deviceId == rhs.deviceId; } bool operator<(const KeyReplacement& rhs) const { return keyCode != rhs.keyCode ? keyCode < rhs.keyCode : deviceId < rhs.deviceId; } }; // Maps the key code replaced, device id tuple to the key code it was replaced with KeyedVector mReplacedKeys GUARDED_BY(mLock); // Process certain Meta + Key combinations void accelerateMetaShortcuts(const int32_t deviceId, const int32_t action, int32_t& keyCode, int32_t& metaState); // Deferred command processing. bool haveCommandsLocked() const REQUIRES(mLock); bool runCommandsLockedInterruptible() REQUIRES(mLock); CommandEntry* postCommandLocked(Command command) REQUIRES(mLock); // Input filter processing. bool shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) REQUIRES(mLock); bool shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) REQUIRES(mLock); // Inbound event processing. void drainInboundQueueLocked() REQUIRES(mLock); void releasePendingEventLocked() REQUIRES(mLock); void releaseInboundEventLocked(EventEntry* entry) REQUIRES(mLock); // Dispatch state. bool mDispatchEnabled GUARDED_BY(mLock); bool mDispatchFrozen GUARDED_BY(mLock); bool mInputFilterEnabled GUARDED_BY(mLock); std::unordered_map>> mWindowHandlesByDisplay GUARDED_BY(mLock); // Get window handles by display, return an empty vector if not found. std::vector> getWindowHandlesLocked(int32_t displayId) const REQUIRES(mLock); sp getWindowHandleLocked(const sp& windowHandleToken) const REQUIRES(mLock); sp getInputChannelLocked(const sp& windowToken) const REQUIRES(mLock); bool hasWindowHandleLocked(const sp& windowHandle) const REQUIRES(mLock); // Focus tracking for keys, trackball, etc. std::unordered_map> mFocusedWindowHandlesByDisplay GUARDED_BY(mLock); KeyedVector mTouchStatesByDisplay GUARDED_BY(mLock); TouchState mTempTouchState GUARDED_BY(mLock); // Focused applications. std::unordered_map> mFocusedApplicationHandlesByDisplay GUARDED_BY(mLock); // Top focused display. int32_t mFocusedDisplayId GUARDED_BY(mLock); // Dispatcher state at time of last ANR. std::string mLastANRState GUARDED_BY(mLock); // Dispatch inbound events. bool dispatchConfigurationChangedLocked(nsecs_t currentTime, ConfigurationChangedEntry* entry) REQUIRES(mLock); bool dispatchDeviceResetLocked(nsecs_t currentTime, DeviceResetEntry* entry) REQUIRES(mLock); bool dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) REQUIRES(mLock); bool dispatchMotionLocked(nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) REQUIRES(mLock); void dispatchEventLocked(nsecs_t currentTime, EventEntry* entry, const std::vector& inputTargets) REQUIRES(mLock); void logOutboundKeyDetails(const char* prefix, const KeyEntry* entry); void logOutboundMotionDetails(const char* prefix, const MotionEntry* entry); // Keeping track of ANR timeouts. enum InputTargetWaitCause { INPUT_TARGET_WAIT_CAUSE_NONE, INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY, INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY, }; InputTargetWaitCause mInputTargetWaitCause GUARDED_BY(mLock); nsecs_t mInputTargetWaitStartTime GUARDED_BY(mLock); nsecs_t mInputTargetWaitTimeoutTime GUARDED_BY(mLock); bool mInputTargetWaitTimeoutExpired GUARDED_BY(mLock); sp mInputTargetWaitApplicationToken GUARDED_BY(mLock); // Contains the last window which received a hover event. sp mLastHoverWindowHandle GUARDED_BY(mLock); // Finding targets for input events. int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry, const sp& applicationHandle, const sp& windowHandle, nsecs_t* nextWakeupTime, const char* reason) REQUIRES(mLock); void removeWindowByTokenLocked(const sp& token) REQUIRES(mLock); void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout, const sp& inputChannel) REQUIRES(mLock); nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime) REQUIRES(mLock); void resetANRTimeoutsLocked() REQUIRES(mLock); int32_t getTargetDisplayId(const EventEntry* entry); int32_t findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry* entry, std::vector& inputTargets, nsecs_t* nextWakeupTime) REQUIRES(mLock); int32_t findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry* entry, std::vector& inputTargets, nsecs_t* nextWakeupTime, bool* outConflictingPointerActions) REQUIRES(mLock); std::vector findTouchedGestureMonitorsLocked( int32_t displayId, const std::vector>& portalWindows) REQUIRES(mLock); void addGestureMonitors(const std::vector& monitors, std::vector& outTouchedMonitors, float xOffset = 0, float yOffset = 0); void addWindowTargetLocked(const sp& windowHandle, int32_t targetFlags, BitSet32 pointerIds, std::vector& inputTargets) REQUIRES(mLock); void addMonitoringTargetLocked(const Monitor& monitor, float xOffset, float yOffset, std::vector& inputTargets) REQUIRES(mLock); void addGlobalMonitoringTargetsLocked(std::vector& inputTargets, int32_t displayId, float xOffset = 0, float yOffset = 0) REQUIRES(mLock); void pokeUserActivityLocked(const EventEntry* eventEntry) REQUIRES(mLock); bool checkInjectionPermission(const sp& windowHandle, const InjectionState* injectionState); bool isWindowObscuredAtPointLocked(const sp& windowHandle, int32_t x, int32_t y) const REQUIRES(mLock); bool isWindowObscuredLocked(const sp& windowHandle) const REQUIRES(mLock); std::string getApplicationWindowLabel(const sp& applicationHandle, const sp& windowHandle); std::string checkWindowReadyForMoreInputLocked(nsecs_t currentTime, const sp& windowHandle, const EventEntry* eventEntry, const char* targetType) REQUIRES(mLock); // Manage the dispatch cycle for a single connection. // These methods are deliberately not Interruptible because doing all of the work // with the mutex held makes it easier to ensure that connection invariants are maintained. // If needed, the methods post commands to run later once the critical bits are done. void prepareDispatchCycleLocked(nsecs_t currentTime, const sp& connection, EventEntry* eventEntry, const InputTarget* inputTarget) REQUIRES(mLock); void enqueueDispatchEntriesLocked(nsecs_t currentTime, const sp& connection, EventEntry* eventEntry, const InputTarget* inputTarget) REQUIRES(mLock); void enqueueDispatchEntryLocked(const sp& connection, EventEntry* eventEntry, const InputTarget* inputTarget, int32_t dispatchMode) REQUIRES(mLock); void startDispatchCycleLocked(nsecs_t currentTime, const sp& connection) REQUIRES(mLock); void finishDispatchCycleLocked(nsecs_t currentTime, const sp& connection, uint32_t seq, bool handled) REQUIRES(mLock); void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp& connection, bool notify) REQUIRES(mLock); void drainDispatchQueue(Queue* queue); void releaseDispatchEntry(DispatchEntry* dispatchEntry); static int handleReceiveCallback(int fd, int events, void* data); // The action sent should only be of type AMOTION_EVENT_* void dispatchPointerDownOutsideFocus(uint32_t source, int32_t action, const sp& newToken) REQUIRES(mLock); void synthesizeCancelationEventsForAllConnectionsLocked(const CancelationOptions& options) REQUIRES(mLock); void synthesizeCancelationEventsForMonitorsLocked(const CancelationOptions& options) REQUIRES(mLock); void synthesizeCancelationEventsForMonitorsLocked( const CancelationOptions& options, std::unordered_map>& monitorsByDisplay) REQUIRES(mLock); void synthesizeCancelationEventsForInputChannelLocked(const sp& channel, const CancelationOptions& options) REQUIRES(mLock); void synthesizeCancelationEventsForConnectionLocked(const sp& connection, const CancelationOptions& options) REQUIRES(mLock); // Splitting motion events across windows. MotionEntry* splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds); // Reset and drop everything the dispatcher is doing. void resetAndDropEverythingLocked(const char* reason) REQUIRES(mLock); // Dump state. void dumpDispatchStateLocked(std::string& dump) REQUIRES(mLock); void dumpMonitors(std::string& dump, const std::vector& monitors); void logDispatchStateLocked() REQUIRES(mLock); // Registration. void removeMonitorChannelLocked(const sp& inputChannel) REQUIRES(mLock); void removeMonitorChannelLocked( const sp& inputChannel, std::unordered_map>& monitorsByDisplay) REQUIRES(mLock); status_t unregisterInputChannelLocked(const sp& inputChannel, bool notify) REQUIRES(mLock); // Interesting events that we might like to log or tell the framework about. void onDispatchCycleFinishedLocked(nsecs_t currentTime, const sp& connection, uint32_t seq, bool handled) REQUIRES(mLock); void onDispatchCycleBrokenLocked(nsecs_t currentTime, const sp& connection) REQUIRES(mLock); void onFocusChangedLocked(const sp& oldFocus, const sp& newFocus) REQUIRES(mLock); void onANRLocked(nsecs_t currentTime, const sp& applicationHandle, const sp& windowHandle, nsecs_t eventTime, nsecs_t waitStartTime, const char* reason) REQUIRES(mLock); // Outbound policy interactions. void doNotifyConfigurationChangedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyFocusChangedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doNotifyANRLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); bool afterKeyEventLockedInterruptible(const sp& connection, DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled) REQUIRES(mLock); bool afterMotionEventLockedInterruptible(const sp& connection, DispatchEntry* dispatchEntry, MotionEntry* motionEntry, bool handled) REQUIRES(mLock); void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); void initializeKeyEvent(KeyEvent* event, const KeyEntry* entry); void doOnPointerDownOutsideFocusLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); // Statistics gathering. void updateDispatchStatistics(nsecs_t currentTime, const EventEntry* entry, int32_t injectionResult, nsecs_t timeSpentWaitingForApplication); void traceInboundQueueLengthLocked() REQUIRES(mLock); void traceOutboundQueueLength(const sp& connection); void traceWaitQueueLength(const sp& connection); sp mReporter; }; } // namespace android::inputdispatcher #endif // _UI_INPUT_DISPATCHER_H