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

Commit a665ca80 authored by Jeff Brown's avatar Jeff Brown
Browse files

Input dispatcher ANR handling enhancements.

This change is essentially a rewrite of the main input dispatcher loop
with the target identification folded in.  Since the input dispatcher now
has all of the window state, it can make better decisions about
when to ANR.

Added a .5 second deadline for processing app switch keys.  This behavior
predates Gingerbread but had not previously been ported.

Fixed some timing inaccuracies in the ANR accounting that could cause
applications to ANR sooner than they should have.

Added a mechanism for tracking key and motion events that have been
dispatched to a window so that appropriate cancelation events can be
synthesized when recovering from ANR.  This change helps to keep
applications in sync so they don't end up with stuck buttons upon
recovery from ANRs.

Added more comments to describe the tricky parts of PollLoop.

Change-Id: I13dffca27acb436fc383980db536abc4d8b9e6f1
parent f76fc380
Loading
Loading
Loading
Loading
+431 −76

File changed.

Preview size limit exceeded, changes collapsed.

+7 −64
Original line number Diff line number Diff line
@@ -72,51 +72,11 @@ public:
    /* Stops the input manager threads and waits for them to exit. */
    virtual status_t stop() = 0;

    /* Registers an input channel prior to using it as the target of an event. */
    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel) = 0;
    /* Gets the input reader. */
    virtual sp<InputReaderInterface> getReader() = 0;

    /* Unregisters an input channel. */
    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;

    /* Injects an input event and optionally waits for sync.
     * The synchronization mode determines whether the method blocks while waiting for
     * input injection to proceed.
     * Returns one of the INPUT_EVENT_INJECTION_XXX constants.
     */
    virtual int32_t injectInputEvent(const InputEvent* event,
            int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) = 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.
     */
    virtual void preemptInputDispatch() = 0;

    /* Gets input device configuration. */
    virtual void getInputConfiguration(InputConfiguration* outConfiguration) = 0;

    /* Gets information about the specified input device.
     * Returns OK if the device information was obtained or NAME_NOT_FOUND if there
     * was no such device.
     */
    virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) = 0;

    /* Gets the list of all registered device ids. */
    virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds) = 0;

    /* Queries current input state. */
    virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
            int32_t scanCode) = 0;
    virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
            int32_t keyCode) = 0;
    virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
            int32_t sw) = 0;

    /* Determines whether physical keys exist for the given framework-domain key codes. */
    virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
            size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
    /* Gets the input dispatcher. */
    virtual sp<InputDispatcherInterface> getDispatcher() = 0;
};

class InputManager : public InputManagerInterface {
@@ -137,25 +97,8 @@ public:
    virtual status_t start();
    virtual status_t stop();

    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel);
    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);

    virtual int32_t injectInputEvent(const InputEvent* event,
            int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis);

    virtual void preemptInputDispatch();

    virtual void getInputConfiguration(InputConfiguration* outConfiguration);
    virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo);
    virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds);
    virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
            int32_t scanCode);
    virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
            int32_t keyCode);
    virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
            int32_t sw);
    virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
            size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
    virtual sp<InputReaderInterface> getReader();
    virtual sp<InputDispatcherInterface> getDispatcher();

private:
    sp<InputReaderInterface> mReader;
+12 −4
Original line number Diff line number Diff line
@@ -95,10 +95,6 @@ public:

        // The input dispatcher should dispatch the input to the application.
        ACTION_DISPATCH = 0x00000001,

        // The input dispatcher should perform special filtering in preparation for
        // a pending app switch.
        ACTION_APP_SWITCH_COMING = 0x00000002,
    };

    /* Gets information about the display with the specified id.
@@ -168,6 +164,11 @@ protected:
    virtual ~InputReaderInterface() { }

public:
    /* Dumps the state of the input reader.
     *
     * This method may be called on any thread (usually by the input manager). */
    virtual void dump(String8& dump) = 0;

    /* Runs a single iteration of the processing loop.
     * Nominally reads and processes one incoming message from the EventHub.
     *
@@ -240,6 +241,8 @@ public:
            const sp<InputDispatcherInterface>& dispatcher);
    virtual ~InputReader();

    virtual void dump(String8& dump);

    virtual void loopOnce();

    virtual void getInputConfiguration(InputConfiguration* outConfiguration);
@@ -305,6 +308,9 @@ private:
            GetStateFunc getStateFunc);
    bool markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
            const int32_t* keyCodes, uint8_t* outFlags);

    // dump state
    void dumpDeviceInfo(String8& dump);
};


@@ -759,9 +765,11 @@ protected:
    } mLocked;

    virtual void configureParameters();
    virtual void logParameters();
    virtual void configureRawAxes();
    virtual void logRawAxes();
    virtual bool configureSurfaceLocked();
    virtual void logMotionRangesLocked();
    virtual void configureVirtualKeysLocked();
    virtual void parseCalibration();
    virtual void resolveCalibration();
+37 −0
Original line number Diff line number Diff line
/*
 * 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_POWER_MANAGER_H
#define _UI_POWER_MANAGER_H


namespace android {

enum {
    POWER_MANAGER_OTHER_EVENT = 0,
    POWER_MANAGER_CHEEK_EVENT = 1,
    POWER_MANAGER_TOUCH_EVENT = 2, // touch events are TOUCH for 300ms, and then either
                                   // up events or LONG_TOUCH events.
    POWER_MANAGER_LONG_TOUCH_EVENT = 3,
    POWER_MANAGER_TOUCH_UP_EVENT = 4,
    POWER_MANAGER_BUTTON_EVENT = 5, // Button and trackball events.

    POWER_MANAGER_LAST_EVENT = POWER_MANAGER_BUTTON_EVENT, // Last valid event code.
};

} // namespace android

#endif // _UI_POWER_MANAGER_H
+26 −12
Original line number Diff line number Diff line
@@ -172,22 +172,36 @@ private:
        void* data;
    };
    
    const bool mAllowNonCallbacks;
    
    const bool mAllowNonCallbacks; // immutable

    int mWakeReadPipeFd;  // immutable
    int mWakeWritePipeFd; // immutable

    // The lock guards state used to track whether there is a poll() in progress and whether
    // there are any other threads waiting in wakeAndLock().  The condition variables
    // are used to transfer control among these threads such that all waiters are
    // serviced before a new poll can begin.
    // The wakeAndLock() method increments mWaiters, wakes the poll, blocks on mAwake
    // until mPolling becomes false, then decrements mWaiters again.
    // The poll() method blocks on mResume until mWaiters becomes 0, then sets
    // mPolling to true, blocks until the poll completes, then resets mPolling to false
    // and signals mResume if there are waiters.
    Mutex mLock;
    bool mPolling;
    uint32_t mWaiters;
    Condition mAwake;
    Condition mResume;

    int mWakeReadPipeFd;
    int mWakeWritePipeFd;

    bool mPolling;      // guarded by mLock
    uint32_t mWaiters;  // guarded by mLock
    Condition mAwake;   // guarded by mLock
    Condition mResume;  // guarded by mLock

    // The next two vectors are only mutated when mPolling is false since they must
    // not be changed while the poll() system call is in progress.  To mutate these
    // vectors, the poll() must first be awoken then the lock acquired.
    Vector<struct pollfd> mRequestedFds;
    Vector<RequestedCallback> mRequestedCallbacks;

    Vector<PendingCallback> mPendingCallbacks; // used privately by pollOnce
    Vector<PendingCallback> mPendingFds;       // used privately by pollOnce
    // This state is only used privately by pollOnce and does not require a lock since
    // it runs on a single thread.
    Vector<PendingCallback> mPendingCallbacks;
    Vector<PendingCallback> mPendingFds;
    size_t mPendingFdsPos;
    
    void openWakePipe();
Loading