Loading include/ui/InputDispatcher.h +32 −89 Original line number Diff line number Diff line Loading @@ -81,9 +81,8 @@ enum { */ struct InputTarget { enum { /* This flag indicates that subsequent event delivery should be held until the * current event is delivered to this target or a timeout occurs. */ FLAG_SYNC = 0x01, /* 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 Loading @@ -109,12 +108,6 @@ struct InputTarget { // Flags for the input target. int32_t flags; // The timeout for event delivery to this target in nanoseconds, or -1 to wait indefinitely. nsecs_t timeout; // The time already spent waiting for this target in nanoseconds, or 0 if none. nsecs_t timeSpentWaitingForApplication; // The x and y offset to add to a MotionEvent as it is delivered. // (ignored for KeyEvents) float xOffset, yOffset; Loading Loading @@ -190,6 +183,7 @@ struct InputWindow { }; sp<InputChannel> inputChannel; String8 name; int32_t layoutParamsFlags; int32_t layoutParamsType; nsecs_t dispatchingTimeout; Loading @@ -206,9 +200,11 @@ struct InputWindow { int32_t touchableAreaRight; int32_t touchableAreaBottom; bool visible; bool canReceiveKeys; bool hasFocus; bool hasWallpaper; bool paused; int32_t layer; int32_t ownerPid; int32_t ownerUid; Loading Loading @@ -257,18 +253,12 @@ public: /* Notifies the system that an application is not responding. * Returns a new timeout to continue waiting, or 0 to abort dispatch. */ virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle) = 0; virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle, const sp<InputChannel>& inputChannel) = 0; /* Notifies the system that an input channel is unrecoverably broken. */ virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) = 0; /* Notifies the system that an input channel is not responding. * Returns a new timeout to continue waiting, or 0 to abort dispatch. */ virtual nsecs_t notifyInputChannelANR(const sp<InputChannel>& inputChannel) = 0; /* Notifies the system that an input channel recovered from ANR. */ virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) = 0; /* Gets the key repeat initial timeout or -1 if automatic key repeating is disabled. */ virtual nsecs_t getKeyRepeatTimeout() = 0; Loading Loading @@ -361,16 +351,6 @@ public: */ virtual void setInputDispatchMode(bool enabled, bool frozen) = 0; /* Preempts input dispatch in progress by making pending synchronous * dispatches asynchronous instead. This method is generally called during a focus * transition from one application to the next so as to enable the new application * to start receiving input as soon as possible without having to wait for the * old application to finish up. * * This method may be called on any thread (usually by the input manager). */ virtual void preemptInputDispatch() = 0; /* Registers or unregister input channels that may be used as targets for input events. * If monitor is true, the channel will receive a copy of all input events. * Loading Loading @@ -424,7 +404,6 @@ public: virtual void setInputWindows(const Vector<InputWindow>& inputWindows); virtual void setFocusedApplication(const InputApplication* inputApplication); virtual void setInputDispatchMode(bool enabled, bool frozen); virtual void preemptInputDispatch(); virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor); virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel); Loading Loading @@ -454,7 +433,7 @@ private: int32_t injectorUid; // -1 if not injected bool dispatchInProgress; // initially false, set to true while dispatching int32_t pendingSyncDispatches; // the number of synchronous dispatches in progress int32_t pendingForegroundDispatches; // the number of foreground dispatches in progress inline bool isInjected() { return injectorPid >= 0; } Loading Loading @@ -522,7 +501,6 @@ private: int32_t targetFlags; float xOffset; float yOffset; nsecs_t timeout; // True if dispatch has started. bool inProgress; Loading @@ -540,12 +518,8 @@ private: // will be set to NULL. MotionSample* tailMotionSample; inline bool isSyncTarget() const { return targetFlags & InputTarget::FLAG_SYNC; } inline void preemptSyncTarget() { targetFlags &= ~ InputTarget::FLAG_SYNC; inline bool hasForegroundTarget() const { return targetFlags & InputTarget::FLAG_FOREGROUND; } }; Loading Loading @@ -628,6 +602,8 @@ private: dequeue(first); return first; } uint32_t count() const; }; /* Allocates queue entries and performs reference counting as needed. */ Loading @@ -647,7 +623,7 @@ private: nsecs_t downTime, uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords); DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry, int32_t targetFlags, float xOffset, float yOffset, nsecs_t timeout); int32_t targetFlags, float xOffset, float yOffset); CommandEntry* obtainCommandEntry(Command command); void releaseEventEntry(EventEntry* entry); Loading Loading @@ -761,8 +737,6 @@ private: STATUS_NORMAL, // An unrecoverable communication error has occurred. STATUS_BROKEN, // The client is not responding. STATUS_NOT_RESPONDING, // The input channel has been unregistered. STATUS_ZOMBIE }; Loading @@ -772,11 +746,9 @@ private: InputPublisher inputPublisher; InputState inputState; Queue<DispatchEntry> outboundQueue; nsecs_t nextTimeoutTime; // next timeout time (LONG_LONG_MAX if none) nsecs_t lastEventTime; // the time when the event was originally captured nsecs_t lastDispatchTime; // the time when the last event was dispatched nsecs_t lastANRTime; // the time when the last ANR was recorded explicit Connection(const sp<InputChannel>& inputChannel); Loading @@ -788,18 +760,6 @@ private: // Returns NULL if not found. DispatchEntry* findQueuedDispatchEntryForEvent(const EventEntry* eventEntry) const; // Determine whether this connection has a pending synchronous dispatch target. // Since there can only ever be at most one such target at a time, if there is one, // it must be at the tail because nothing else can be enqueued after it. inline bool hasPendingSyncTarget() const { return ! outboundQueue.isEmpty() && outboundQueue.tailSentinel.prev->isSyncTarget(); } // Assuming there is a pending sync target, make it async. inline void preemptSyncTarget() { outboundQueue.tailSentinel.prev->preemptSyncTarget(); } // Gets the time since the current event was originally obtained from the input driver. inline double getEventLatencyMillis(nsecs_t currentTime) const { return (currentTime - lastEventTime) / 1000000.0; Loading @@ -810,15 +770,7 @@ private: return (currentTime - lastDispatchTime) / 1000000.0; } // Gets the time since the current event ANR was declared, if applicable. inline double getANRLatencyMillis(nsecs_t currentTime) const { return (currentTime - lastANRTime) / 1000000.0; } status_t initialize(); void setNextTimeoutTime(nsecs_t currentTime, nsecs_t timeout); void resetTimeout(nsecs_t currentTime); }; sp<InputDispatcherPolicyInterface> mPolicy; Loading Loading @@ -851,7 +803,7 @@ private: // All registered connections mapped by receive pipe file descriptor. KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd; ssize_t getConnectionIndex(const sp<InputChannel>& inputChannel); ssize_t getConnectionIndexLocked(const sp<InputChannel>& inputChannel); // Active connections are connections that have a non-empty outbound queue. // We don't use a ref-counted pointer here because we explicitly abort connections Loading @@ -859,12 +811,6 @@ private: // and the connection itself to be deactivated. Vector<Connection*> mActiveConnections; // List of connections that have timed out. Only used by dispatchOnce() // We don't use a ref-counted pointer here because it is not possible for a connection // to be unregistered while processing timed out connections since we hold the lock for // the duration. Vector<Connection*> mTimedOutConnections; // Input channels that will receive a copy of all input events. Vector<sp<InputChannel> > mMonitoringChannels; Loading @@ -877,7 +823,7 @@ private: void setInjectionResultLocked(EventEntry* entry, int32_t injectionResult); Condition mInjectionSyncFinishedCondition; void decrementPendingSyncDispatchesLocked(EventEntry* entry); void decrementPendingForegroundDispatchesLocked(EventEntry* entry); // Throttling state. struct ThrottleState { Loading Loading @@ -951,8 +897,6 @@ private: void logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry); // The input targets that were most recently identified for dispatch. // If there is a synchronous event dispatch in progress, the current input targets will // remain unchanged until the dispatch has completed or been aborted. bool mCurrentInputTargetsValid; // false while targets are being recomputed Vector<InputTarget> mCurrentInputTargets; int32_t mCurrentInputWindowType; Loading @@ -975,8 +919,9 @@ private: int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry, const InputApplication* application, const InputWindow* window, nsecs_t* nextWakeupTime); void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout); nsecs_t getTimeSpentWaitingForApplicationWhileFindingTargetsLocked(nsecs_t currentTime); void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout, const sp<InputChannel>& inputChannel); nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime); void resetANRTimeoutsLocked(); int32_t findFocusedWindowLocked(nsecs_t currentTime, const EventEntry* entry, Loading @@ -984,14 +929,16 @@ private: int32_t findTouchedWindowLocked(nsecs_t currentTime, const MotionEntry* entry, nsecs_t* nextWakeupTime, InputWindow** outWindow); void addWindowTargetLocked(const InputWindow* window, int32_t targetFlags, nsecs_t timeSpentWaitingForApplication); void addWindowTargetLocked(const InputWindow* window, int32_t targetFlags); void addMonitoringTargetsLocked(); void pokeUserActivityLocked(nsecs_t eventTime, int32_t windowType, int32_t eventType); bool checkInjectionPermission(const InputWindow* window, int32_t injectorPid, int32_t injectorUid); bool isWindowObscuredLocked(const InputWindow* window); bool isWindowFinishedWithPreviousInputLocked(const InputWindow* window); void releaseTouchedWindowLocked(); String8 getApplicationWindowLabelLocked(const InputApplication* application, const InputWindow* window); // Manage the dispatch cycle for a single connection. // These methods are deliberately not Interruptible because doing all of the work Loading @@ -1000,21 +947,14 @@ private: void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget, bool resumeWithAppendedMotionSample); void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, nsecs_t timeSpentWaitingForApplication); 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 timeoutDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection); void resumeAfterTimeoutDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, nsecs_t newTimeout); void abortDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, bool broken); void drainOutboundQueueLocked(Connection* connection, DispatchEntry* firstDispatchEntryToDrain); void drainOutboundQueueLocked(Connection* connection); static int handleReceiveCallback(int receiveFd, int events, void* data); // Preempting input dispatch. bool preemptInputDispatchInnerLocked(); // Dump state. void dumpDispatchStateLocked(String8& dump); void logDispatchStateLocked(); Loading @@ -1027,20 +967,23 @@ private: void onDispatchCycleStartedLocked( nsecs_t currentTime, const sp<Connection>& connection); void onDispatchCycleFinishedLocked( nsecs_t currentTime, const sp<Connection>& connection, bool recoveredFromANR); void onDispatchCycleANRLocked( nsecs_t currentTime, const sp<Connection>& connection); void onDispatchCycleBrokenLocked( nsecs_t currentTime, const sp<Connection>& connection); void onANRLocked( nsecs_t currentTime, const InputApplication* application, const InputWindow* window, nsecs_t eventTime, nsecs_t waitStartTime); // Outbound policy interactions. void doNotifyConfigurationChangedInterruptible(CommandEntry* commandEntry); void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry); void doNotifyInputChannelANRLockedInterruptible(CommandEntry* commandEntry); void doNotifyInputChannelRecoveredFromANRLockedInterruptible(CommandEntry* commandEntry); void doNotifyANRLockedInterruptible(CommandEntry* commandEntry); void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry); void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry); void doTargetsNotReadyTimeoutLockedInterruptible(CommandEntry* commandEntry); // Statistics gathering. void updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry, int32_t injectionResult, nsecs_t timeSpentWaitingForApplication); }; /* Enqueues and dispatches input events, endlessly. */ Loading libs/ui/InputDispatcher.cpp +269 −393 File changed.Preview size limit exceeded, changes collapsed. Show changes services/java/com/android/server/InputManager.java +2 −22 Original line number Diff line number Diff line Loading @@ -24,18 +24,13 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.os.Environment; import android.os.LocalPowerManager; import android.os.PowerManager; import android.os.SystemProperties; import android.util.Slog; import android.util.Xml; import android.view.InputChannel; import android.view.InputDevice; import android.view.InputEvent; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.Surface; import android.view.WindowManagerPolicy; import java.io.BufferedReader; import java.io.File; Loading Loading @@ -83,7 +78,6 @@ public class InputManager { private static native void nativeSetInputWindows(InputWindow[] windows); private static native void nativeSetInputDispatchMode(boolean enabled, boolean frozen); private static native void nativeSetFocusedApplication(InputApplication application); private static native void nativePreemptInputDispatch(); private static native InputDevice nativeGetInputDevice(int deviceId); private static native int[] nativeGetInputDeviceIds(); private static native String nativeDump(); Loading Loading @@ -331,10 +325,6 @@ public class InputManager { nativeSetFocusedApplication(application); } public void preemptInputDispatch() { nativePreemptInputDispatch(); } public void setInputDispatchMode(boolean enabled, boolean frozen) { nativeSetInputDispatchMode(enabled, frozen); } Loading Loading @@ -397,18 +387,8 @@ public class InputManager { } @SuppressWarnings("unused") public long notifyInputChannelANR(InputChannel inputChannel) { return mWindowManagerService.mInputMonitor.notifyInputChannelANR(inputChannel); } @SuppressWarnings("unused") public void notifyInputChannelRecoveredFromANR(InputChannel inputChannel) { mWindowManagerService.mInputMonitor.notifyInputChannelRecoveredFromANR(inputChannel); } @SuppressWarnings("unused") public long notifyANR(Object token) { return mWindowManagerService.mInputMonitor.notifyANR(token); public long notifyANR(Object token, InputChannel inputChannel) { return mWindowManagerService.mInputMonitor.notifyANR(token, inputChannel); } @SuppressWarnings("unused") Loading services/java/com/android/server/InputWindow.java +9 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,9 @@ public final class InputWindow { // The input channel associated with the window. public InputChannel inputChannel; // The window name. public String name; // Window layout params attributes. (WindowManager.LayoutParams) public int layoutParamsFlags; public int layoutParamsType; Loading Loading @@ -55,6 +58,9 @@ public final class InputWindow { // Window is visible. public boolean visible; // Window can receive keys. public boolean canReceiveKeys; // Window has focus. public boolean hasFocus; Loading @@ -64,6 +70,9 @@ public final class InputWindow { // Input event dispatching is paused. public boolean paused; // Window layer. public int layer; // Id of process and user that owns the window. public int ownerPid; public int ownerUid; Loading services/java/com/android/server/WindowManagerService.java +22 −66 Original line number Diff line number Diff line Loading @@ -5097,61 +5097,39 @@ public class WindowManagerService extends IWindowManager.Stub } } /* Notifies the window manager about an input channel that is not responding. /* Notifies the window manager about an application that is not responding. * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch. * * Called by the InputManager. */ public long notifyInputChannelANR(InputChannel inputChannel) { AppWindowToken token; public long notifyANR(Object token, InputChannel inputChannel) { AppWindowToken appWindowToken = null; if (inputChannel != null) { synchronized (mWindowMap) { WindowState windowState = getWindowStateForInputChannelLocked(inputChannel); if (windowState == null) { return 0; // window is unknown, abort dispatching } if (windowState != null) { Slog.i(TAG, "Input event dispatching timed out sending to " + windowState.mAttrs.getTitle()); token = windowState.mAppToken; appWindowToken = windowState.mAppToken; } return notifyANRInternal(token); } /* Notifies the window manager about an input channel spontaneously recovering from ANR * by successfully delivering the event that originally timed out. * * Called by the InputManager. */ public void notifyInputChannelRecoveredFromANR(InputChannel inputChannel) { // Nothing to do just now. // Just wait for the user to dismiss the ANR dialog. } /* Notifies the window manager about an application that is not responding * in general rather than with respect to a particular input channel. * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch. * * Called by the InputManager. */ public long notifyANR(Object token) { AppWindowToken appWindowToken = (AppWindowToken) token; if (appWindowToken == null && token != null) { appWindowToken = (AppWindowToken) token; Slog.i(TAG, "Input event dispatching timed out sending to application " + appWindowToken.stringName); return notifyANRInternal(appWindowToken); } private long notifyANRInternal(AppWindowToken token) { if (token != null && token.appToken != null) { if (appWindowToken != null && appWindowToken.appToken != null) { try { // Notify the activity manager about the timeout and let it decide whether // to abort dispatching or keep waiting. boolean abort = token.appToken.keyDispatchingTimedOut(); boolean abort = appWindowToken.appToken.keyDispatchingTimedOut(); if (! abort) { // The activity manager declined to abort dispatching. // Wait a bit longer and timeout again later. return token.inputDispatchingTimeoutNanos; return appWindowToken.inputDispatchingTimeoutNanos; } } catch (RemoteException ex) { } Loading Loading @@ -5204,13 +5182,16 @@ public class WindowManagerService extends IWindowManager.Stub // Add a window to our list of input windows. final InputWindow inputWindow = mTempInputWindows.add(); inputWindow.inputChannel = child.mInputChannel; inputWindow.name = child.toString(); inputWindow.layoutParamsFlags = flags; inputWindow.layoutParamsType = type; inputWindow.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos(); inputWindow.visible = isVisible; inputWindow.canReceiveKeys = child.canReceiveKeys(); inputWindow.hasFocus = hasFocus; inputWindow.hasWallpaper = hasWallpaper; inputWindow.paused = child.mAppToken != null ? child.mAppToken.paused : false; inputWindow.layer = child.mLayer; inputWindow.ownerPid = child.mSession.mPid; inputWindow.ownerUid = child.mSession.mUid; Loading Loading @@ -5303,23 +5284,6 @@ public class WindowManagerService extends IWindowManager.Stub if (newWindow != mInputFocus) { if (newWindow != null && newWindow.canReceiveKeys()) { // If the new input focus is an error window or appears above the current // input focus, preempt any pending synchronous dispatch so that we can // start delivering events to the new input focus as soon as possible. if ((newWindow.mAttrs.flags & FLAG_SYSTEM_ERROR) != 0) { if (DEBUG_INPUT) { Slog.v(TAG, "New SYSTEM_ERROR window; resetting state"); } preemptInputDispatchLw(); } else if (mInputFocus != null && newWindow.mLayer > mInputFocus.mLayer) { if (DEBUG_INPUT) { Slog.v(TAG, "Transferring focus to new window at higher layer: " + "old win layer=" + mInputFocus.mLayer + ", new win layer=" + newWindow.mLayer); } preemptInputDispatchLw(); } // Displaying a window implicitly causes dispatching to be unpaused. // This is to protect against bugs if someone pauses dispatching but // forgets to resume. Loading @@ -5331,14 +5295,6 @@ public class WindowManagerService extends IWindowManager.Stub } } /* Tells the dispatcher to stop waiting for its current synchronous event targets. * Essentially, just makes those dispatches asynchronous so a new dispatch cycle * can begin. */ private void preemptInputDispatchLw() { mInputManager.preemptInputDispatch(); } public void setFocusedAppLw(AppWindowToken newApp) { // Focused app has changed. if (newApp == null) { Loading Loading
include/ui/InputDispatcher.h +32 −89 Original line number Diff line number Diff line Loading @@ -81,9 +81,8 @@ enum { */ struct InputTarget { enum { /* This flag indicates that subsequent event delivery should be held until the * current event is delivered to this target or a timeout occurs. */ FLAG_SYNC = 0x01, /* 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 Loading @@ -109,12 +108,6 @@ struct InputTarget { // Flags for the input target. int32_t flags; // The timeout for event delivery to this target in nanoseconds, or -1 to wait indefinitely. nsecs_t timeout; // The time already spent waiting for this target in nanoseconds, or 0 if none. nsecs_t timeSpentWaitingForApplication; // The x and y offset to add to a MotionEvent as it is delivered. // (ignored for KeyEvents) float xOffset, yOffset; Loading Loading @@ -190,6 +183,7 @@ struct InputWindow { }; sp<InputChannel> inputChannel; String8 name; int32_t layoutParamsFlags; int32_t layoutParamsType; nsecs_t dispatchingTimeout; Loading @@ -206,9 +200,11 @@ struct InputWindow { int32_t touchableAreaRight; int32_t touchableAreaBottom; bool visible; bool canReceiveKeys; bool hasFocus; bool hasWallpaper; bool paused; int32_t layer; int32_t ownerPid; int32_t ownerUid; Loading Loading @@ -257,18 +253,12 @@ public: /* Notifies the system that an application is not responding. * Returns a new timeout to continue waiting, or 0 to abort dispatch. */ virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle) = 0; virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle, const sp<InputChannel>& inputChannel) = 0; /* Notifies the system that an input channel is unrecoverably broken. */ virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) = 0; /* Notifies the system that an input channel is not responding. * Returns a new timeout to continue waiting, or 0 to abort dispatch. */ virtual nsecs_t notifyInputChannelANR(const sp<InputChannel>& inputChannel) = 0; /* Notifies the system that an input channel recovered from ANR. */ virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) = 0; /* Gets the key repeat initial timeout or -1 if automatic key repeating is disabled. */ virtual nsecs_t getKeyRepeatTimeout() = 0; Loading Loading @@ -361,16 +351,6 @@ public: */ virtual void setInputDispatchMode(bool enabled, bool frozen) = 0; /* Preempts input dispatch in progress by making pending synchronous * dispatches asynchronous instead. This method is generally called during a focus * transition from one application to the next so as to enable the new application * to start receiving input as soon as possible without having to wait for the * old application to finish up. * * This method may be called on any thread (usually by the input manager). */ virtual void preemptInputDispatch() = 0; /* Registers or unregister input channels that may be used as targets for input events. * If monitor is true, the channel will receive a copy of all input events. * Loading Loading @@ -424,7 +404,6 @@ public: virtual void setInputWindows(const Vector<InputWindow>& inputWindows); virtual void setFocusedApplication(const InputApplication* inputApplication); virtual void setInputDispatchMode(bool enabled, bool frozen); virtual void preemptInputDispatch(); virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor); virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel); Loading Loading @@ -454,7 +433,7 @@ private: int32_t injectorUid; // -1 if not injected bool dispatchInProgress; // initially false, set to true while dispatching int32_t pendingSyncDispatches; // the number of synchronous dispatches in progress int32_t pendingForegroundDispatches; // the number of foreground dispatches in progress inline bool isInjected() { return injectorPid >= 0; } Loading Loading @@ -522,7 +501,6 @@ private: int32_t targetFlags; float xOffset; float yOffset; nsecs_t timeout; // True if dispatch has started. bool inProgress; Loading @@ -540,12 +518,8 @@ private: // will be set to NULL. MotionSample* tailMotionSample; inline bool isSyncTarget() const { return targetFlags & InputTarget::FLAG_SYNC; } inline void preemptSyncTarget() { targetFlags &= ~ InputTarget::FLAG_SYNC; inline bool hasForegroundTarget() const { return targetFlags & InputTarget::FLAG_FOREGROUND; } }; Loading Loading @@ -628,6 +602,8 @@ private: dequeue(first); return first; } uint32_t count() const; }; /* Allocates queue entries and performs reference counting as needed. */ Loading @@ -647,7 +623,7 @@ private: nsecs_t downTime, uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords); DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry, int32_t targetFlags, float xOffset, float yOffset, nsecs_t timeout); int32_t targetFlags, float xOffset, float yOffset); CommandEntry* obtainCommandEntry(Command command); void releaseEventEntry(EventEntry* entry); Loading Loading @@ -761,8 +737,6 @@ private: STATUS_NORMAL, // An unrecoverable communication error has occurred. STATUS_BROKEN, // The client is not responding. STATUS_NOT_RESPONDING, // The input channel has been unregistered. STATUS_ZOMBIE }; Loading @@ -772,11 +746,9 @@ private: InputPublisher inputPublisher; InputState inputState; Queue<DispatchEntry> outboundQueue; nsecs_t nextTimeoutTime; // next timeout time (LONG_LONG_MAX if none) nsecs_t lastEventTime; // the time when the event was originally captured nsecs_t lastDispatchTime; // the time when the last event was dispatched nsecs_t lastANRTime; // the time when the last ANR was recorded explicit Connection(const sp<InputChannel>& inputChannel); Loading @@ -788,18 +760,6 @@ private: // Returns NULL if not found. DispatchEntry* findQueuedDispatchEntryForEvent(const EventEntry* eventEntry) const; // Determine whether this connection has a pending synchronous dispatch target. // Since there can only ever be at most one such target at a time, if there is one, // it must be at the tail because nothing else can be enqueued after it. inline bool hasPendingSyncTarget() const { return ! outboundQueue.isEmpty() && outboundQueue.tailSentinel.prev->isSyncTarget(); } // Assuming there is a pending sync target, make it async. inline void preemptSyncTarget() { outboundQueue.tailSentinel.prev->preemptSyncTarget(); } // Gets the time since the current event was originally obtained from the input driver. inline double getEventLatencyMillis(nsecs_t currentTime) const { return (currentTime - lastEventTime) / 1000000.0; Loading @@ -810,15 +770,7 @@ private: return (currentTime - lastDispatchTime) / 1000000.0; } // Gets the time since the current event ANR was declared, if applicable. inline double getANRLatencyMillis(nsecs_t currentTime) const { return (currentTime - lastANRTime) / 1000000.0; } status_t initialize(); void setNextTimeoutTime(nsecs_t currentTime, nsecs_t timeout); void resetTimeout(nsecs_t currentTime); }; sp<InputDispatcherPolicyInterface> mPolicy; Loading Loading @@ -851,7 +803,7 @@ private: // All registered connections mapped by receive pipe file descriptor. KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd; ssize_t getConnectionIndex(const sp<InputChannel>& inputChannel); ssize_t getConnectionIndexLocked(const sp<InputChannel>& inputChannel); // Active connections are connections that have a non-empty outbound queue. // We don't use a ref-counted pointer here because we explicitly abort connections Loading @@ -859,12 +811,6 @@ private: // and the connection itself to be deactivated. Vector<Connection*> mActiveConnections; // List of connections that have timed out. Only used by dispatchOnce() // We don't use a ref-counted pointer here because it is not possible for a connection // to be unregistered while processing timed out connections since we hold the lock for // the duration. Vector<Connection*> mTimedOutConnections; // Input channels that will receive a copy of all input events. Vector<sp<InputChannel> > mMonitoringChannels; Loading @@ -877,7 +823,7 @@ private: void setInjectionResultLocked(EventEntry* entry, int32_t injectionResult); Condition mInjectionSyncFinishedCondition; void decrementPendingSyncDispatchesLocked(EventEntry* entry); void decrementPendingForegroundDispatchesLocked(EventEntry* entry); // Throttling state. struct ThrottleState { Loading Loading @@ -951,8 +897,6 @@ private: void logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry); // The input targets that were most recently identified for dispatch. // If there is a synchronous event dispatch in progress, the current input targets will // remain unchanged until the dispatch has completed or been aborted. bool mCurrentInputTargetsValid; // false while targets are being recomputed Vector<InputTarget> mCurrentInputTargets; int32_t mCurrentInputWindowType; Loading @@ -975,8 +919,9 @@ private: int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry, const InputApplication* application, const InputWindow* window, nsecs_t* nextWakeupTime); void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout); nsecs_t getTimeSpentWaitingForApplicationWhileFindingTargetsLocked(nsecs_t currentTime); void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout, const sp<InputChannel>& inputChannel); nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime); void resetANRTimeoutsLocked(); int32_t findFocusedWindowLocked(nsecs_t currentTime, const EventEntry* entry, Loading @@ -984,14 +929,16 @@ private: int32_t findTouchedWindowLocked(nsecs_t currentTime, const MotionEntry* entry, nsecs_t* nextWakeupTime, InputWindow** outWindow); void addWindowTargetLocked(const InputWindow* window, int32_t targetFlags, nsecs_t timeSpentWaitingForApplication); void addWindowTargetLocked(const InputWindow* window, int32_t targetFlags); void addMonitoringTargetsLocked(); void pokeUserActivityLocked(nsecs_t eventTime, int32_t windowType, int32_t eventType); bool checkInjectionPermission(const InputWindow* window, int32_t injectorPid, int32_t injectorUid); bool isWindowObscuredLocked(const InputWindow* window); bool isWindowFinishedWithPreviousInputLocked(const InputWindow* window); void releaseTouchedWindowLocked(); String8 getApplicationWindowLabelLocked(const InputApplication* application, const InputWindow* window); // Manage the dispatch cycle for a single connection. // These methods are deliberately not Interruptible because doing all of the work Loading @@ -1000,21 +947,14 @@ private: void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget, bool resumeWithAppendedMotionSample); void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, nsecs_t timeSpentWaitingForApplication); 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 timeoutDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection); void resumeAfterTimeoutDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, nsecs_t newTimeout); void abortDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, bool broken); void drainOutboundQueueLocked(Connection* connection, DispatchEntry* firstDispatchEntryToDrain); void drainOutboundQueueLocked(Connection* connection); static int handleReceiveCallback(int receiveFd, int events, void* data); // Preempting input dispatch. bool preemptInputDispatchInnerLocked(); // Dump state. void dumpDispatchStateLocked(String8& dump); void logDispatchStateLocked(); Loading @@ -1027,20 +967,23 @@ private: void onDispatchCycleStartedLocked( nsecs_t currentTime, const sp<Connection>& connection); void onDispatchCycleFinishedLocked( nsecs_t currentTime, const sp<Connection>& connection, bool recoveredFromANR); void onDispatchCycleANRLocked( nsecs_t currentTime, const sp<Connection>& connection); void onDispatchCycleBrokenLocked( nsecs_t currentTime, const sp<Connection>& connection); void onANRLocked( nsecs_t currentTime, const InputApplication* application, const InputWindow* window, nsecs_t eventTime, nsecs_t waitStartTime); // Outbound policy interactions. void doNotifyConfigurationChangedInterruptible(CommandEntry* commandEntry); void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry); void doNotifyInputChannelANRLockedInterruptible(CommandEntry* commandEntry); void doNotifyInputChannelRecoveredFromANRLockedInterruptible(CommandEntry* commandEntry); void doNotifyANRLockedInterruptible(CommandEntry* commandEntry); void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry); void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry); void doTargetsNotReadyTimeoutLockedInterruptible(CommandEntry* commandEntry); // Statistics gathering. void updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry, int32_t injectionResult, nsecs_t timeSpentWaitingForApplication); }; /* Enqueues and dispatches input events, endlessly. */ Loading
libs/ui/InputDispatcher.cpp +269 −393 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/java/com/android/server/InputManager.java +2 −22 Original line number Diff line number Diff line Loading @@ -24,18 +24,13 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.os.Environment; import android.os.LocalPowerManager; import android.os.PowerManager; import android.os.SystemProperties; import android.util.Slog; import android.util.Xml; import android.view.InputChannel; import android.view.InputDevice; import android.view.InputEvent; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.Surface; import android.view.WindowManagerPolicy; import java.io.BufferedReader; import java.io.File; Loading Loading @@ -83,7 +78,6 @@ public class InputManager { private static native void nativeSetInputWindows(InputWindow[] windows); private static native void nativeSetInputDispatchMode(boolean enabled, boolean frozen); private static native void nativeSetFocusedApplication(InputApplication application); private static native void nativePreemptInputDispatch(); private static native InputDevice nativeGetInputDevice(int deviceId); private static native int[] nativeGetInputDeviceIds(); private static native String nativeDump(); Loading Loading @@ -331,10 +325,6 @@ public class InputManager { nativeSetFocusedApplication(application); } public void preemptInputDispatch() { nativePreemptInputDispatch(); } public void setInputDispatchMode(boolean enabled, boolean frozen) { nativeSetInputDispatchMode(enabled, frozen); } Loading Loading @@ -397,18 +387,8 @@ public class InputManager { } @SuppressWarnings("unused") public long notifyInputChannelANR(InputChannel inputChannel) { return mWindowManagerService.mInputMonitor.notifyInputChannelANR(inputChannel); } @SuppressWarnings("unused") public void notifyInputChannelRecoveredFromANR(InputChannel inputChannel) { mWindowManagerService.mInputMonitor.notifyInputChannelRecoveredFromANR(inputChannel); } @SuppressWarnings("unused") public long notifyANR(Object token) { return mWindowManagerService.mInputMonitor.notifyANR(token); public long notifyANR(Object token, InputChannel inputChannel) { return mWindowManagerService.mInputMonitor.notifyANR(token, inputChannel); } @SuppressWarnings("unused") Loading
services/java/com/android/server/InputWindow.java +9 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,9 @@ public final class InputWindow { // The input channel associated with the window. public InputChannel inputChannel; // The window name. public String name; // Window layout params attributes. (WindowManager.LayoutParams) public int layoutParamsFlags; public int layoutParamsType; Loading Loading @@ -55,6 +58,9 @@ public final class InputWindow { // Window is visible. public boolean visible; // Window can receive keys. public boolean canReceiveKeys; // Window has focus. public boolean hasFocus; Loading @@ -64,6 +70,9 @@ public final class InputWindow { // Input event dispatching is paused. public boolean paused; // Window layer. public int layer; // Id of process and user that owns the window. public int ownerPid; public int ownerUid; Loading
services/java/com/android/server/WindowManagerService.java +22 −66 Original line number Diff line number Diff line Loading @@ -5097,61 +5097,39 @@ public class WindowManagerService extends IWindowManager.Stub } } /* Notifies the window manager about an input channel that is not responding. /* Notifies the window manager about an application that is not responding. * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch. * * Called by the InputManager. */ public long notifyInputChannelANR(InputChannel inputChannel) { AppWindowToken token; public long notifyANR(Object token, InputChannel inputChannel) { AppWindowToken appWindowToken = null; if (inputChannel != null) { synchronized (mWindowMap) { WindowState windowState = getWindowStateForInputChannelLocked(inputChannel); if (windowState == null) { return 0; // window is unknown, abort dispatching } if (windowState != null) { Slog.i(TAG, "Input event dispatching timed out sending to " + windowState.mAttrs.getTitle()); token = windowState.mAppToken; appWindowToken = windowState.mAppToken; } return notifyANRInternal(token); } /* Notifies the window manager about an input channel spontaneously recovering from ANR * by successfully delivering the event that originally timed out. * * Called by the InputManager. */ public void notifyInputChannelRecoveredFromANR(InputChannel inputChannel) { // Nothing to do just now. // Just wait for the user to dismiss the ANR dialog. } /* Notifies the window manager about an application that is not responding * in general rather than with respect to a particular input channel. * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch. * * Called by the InputManager. */ public long notifyANR(Object token) { AppWindowToken appWindowToken = (AppWindowToken) token; if (appWindowToken == null && token != null) { appWindowToken = (AppWindowToken) token; Slog.i(TAG, "Input event dispatching timed out sending to application " + appWindowToken.stringName); return notifyANRInternal(appWindowToken); } private long notifyANRInternal(AppWindowToken token) { if (token != null && token.appToken != null) { if (appWindowToken != null && appWindowToken.appToken != null) { try { // Notify the activity manager about the timeout and let it decide whether // to abort dispatching or keep waiting. boolean abort = token.appToken.keyDispatchingTimedOut(); boolean abort = appWindowToken.appToken.keyDispatchingTimedOut(); if (! abort) { // The activity manager declined to abort dispatching. // Wait a bit longer and timeout again later. return token.inputDispatchingTimeoutNanos; return appWindowToken.inputDispatchingTimeoutNanos; } } catch (RemoteException ex) { } Loading Loading @@ -5204,13 +5182,16 @@ public class WindowManagerService extends IWindowManager.Stub // Add a window to our list of input windows. final InputWindow inputWindow = mTempInputWindows.add(); inputWindow.inputChannel = child.mInputChannel; inputWindow.name = child.toString(); inputWindow.layoutParamsFlags = flags; inputWindow.layoutParamsType = type; inputWindow.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos(); inputWindow.visible = isVisible; inputWindow.canReceiveKeys = child.canReceiveKeys(); inputWindow.hasFocus = hasFocus; inputWindow.hasWallpaper = hasWallpaper; inputWindow.paused = child.mAppToken != null ? child.mAppToken.paused : false; inputWindow.layer = child.mLayer; inputWindow.ownerPid = child.mSession.mPid; inputWindow.ownerUid = child.mSession.mUid; Loading Loading @@ -5303,23 +5284,6 @@ public class WindowManagerService extends IWindowManager.Stub if (newWindow != mInputFocus) { if (newWindow != null && newWindow.canReceiveKeys()) { // If the new input focus is an error window or appears above the current // input focus, preempt any pending synchronous dispatch so that we can // start delivering events to the new input focus as soon as possible. if ((newWindow.mAttrs.flags & FLAG_SYSTEM_ERROR) != 0) { if (DEBUG_INPUT) { Slog.v(TAG, "New SYSTEM_ERROR window; resetting state"); } preemptInputDispatchLw(); } else if (mInputFocus != null && newWindow.mLayer > mInputFocus.mLayer) { if (DEBUG_INPUT) { Slog.v(TAG, "Transferring focus to new window at higher layer: " + "old win layer=" + mInputFocus.mLayer + ", new win layer=" + newWindow.mLayer); } preemptInputDispatchLw(); } // Displaying a window implicitly causes dispatching to be unpaused. // This is to protect against bugs if someone pauses dispatching but // forgets to resume. Loading @@ -5331,14 +5295,6 @@ public class WindowManagerService extends IWindowManager.Stub } } /* Tells the dispatcher to stop waiting for its current synchronous event targets. * Essentially, just makes those dispatches asynchronous so a new dispatch cycle * can begin. */ private void preemptInputDispatchLw() { mInputManager.preemptInputDispatch(); } public void setFocusedAppLw(AppWindowToken newApp) { // Focused app has changed. if (newApp == null) { Loading