Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fa8186c7 authored by Jeff Brown's avatar Jeff Brown Committed by Android Git Automerger
Browse files

am 7642c82c: am f4d788c9: Merge "Make input dispatcher only ANR for foreground...

am 7642c82c: am f4d788c9: Merge "Make input dispatcher only ANR for foreground windows." into gingerbread

Merge commit '7642c82c'

* commit '7642c82c':
  Make input dispatcher only ANR for foreground windows.
parents fcec46b3 7642c82c
Loading
Loading
Loading
Loading
+32 −89
Original line number Diff line number Diff line
@@ -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
@@ -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;
@@ -190,6 +183,7 @@ struct InputWindow {
    };

    sp<InputChannel> inputChannel;
    String8 name;
    int32_t layoutParamsFlags;
    int32_t layoutParamsType;
    nsecs_t dispatchingTimeout;
@@ -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;

@@ -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;

@@ -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.
     *
@@ -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);
@@ -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; }

@@ -522,7 +501,6 @@ private:
        int32_t targetFlags;
        float xOffset;
        float yOffset;
        nsecs_t timeout;

        // True if dispatch has started.
        bool inProgress;
@@ -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;
        }
    };

@@ -628,6 +602,8 @@ private:
            dequeue(first);
            return first;
        }

        uint32_t count() const;
    };

    /* Allocates queue entries and performs reference counting as needed. */
@@ -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);
@@ -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
        };
@@ -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);

@@ -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;
@@ -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;
@@ -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
@@ -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;

@@ -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 {
@@ -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;
@@ -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,
@@ -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
@@ -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();
@@ -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. */
+269 −393

File changed.

Preview size limit exceeded, changes collapsed.

+2 −22
Original line number Diff line number Diff line
@@ -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;
@@ -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();
@@ -331,10 +325,6 @@ public class InputManager {
        nativeSetFocusedApplication(application);
    }
    
    public void preemptInputDispatch() {
        nativePreemptInputDispatch();
    }
    
    public void setInputDispatchMode(boolean enabled, boolean frozen) {
        nativeSetInputDispatchMode(enabled, frozen);
    }
@@ -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")
+9 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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;
    
@@ -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;
+22 −66
Original line number Diff line number Diff line
@@ -5088,61 +5088,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) {
                }
@@ -5195,13 +5173,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;
                
@@ -5294,23 +5275,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.
@@ -5322,14 +5286,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