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


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


    /* Unregisters an input channel. */
    /* Gets the input dispatcher. */
    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
    virtual sp<InputDispatcherInterface> getDispatcher() = 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;
};
};


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


    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel);
    virtual sp<InputReaderInterface> getReader();
    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
    virtual sp<InputDispatcherInterface> getDispatcher();

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


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


        // The input dispatcher should dispatch the input to the application.
        // The input dispatcher should dispatch the input to the application.
        ACTION_DISPATCH = 0x00000001,
        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.
    /* Gets information about the display with the specified id.
@@ -168,6 +164,11 @@ protected:
    virtual ~InputReaderInterface() { }
    virtual ~InputReaderInterface() { }


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


    virtual void dump(String8& dump);

    virtual void loopOnce();
    virtual void loopOnce();


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

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




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


    virtual void configureParameters();
    virtual void configureParameters();
    virtual void logParameters();
    virtual void configureRawAxes();
    virtual void configureRawAxes();
    virtual void logRawAxes();
    virtual void logRawAxes();
    virtual bool configureSurfaceLocked();
    virtual bool configureSurfaceLocked();
    virtual void logMotionRangesLocked();
    virtual void configureVirtualKeysLocked();
    virtual void configureVirtualKeysLocked();
    virtual void parseCalibration();
    virtual void parseCalibration();
    virtual void resolveCalibration();
    virtual void resolveCalibration();
+37 −0
Original line number Original line 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 Original line Diff line number Diff line
@@ -172,22 +172,36 @@ private:
        void* data;
        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;
    Mutex mLock;
    bool mPolling;
    bool mPolling;      // guarded by mLock
    uint32_t mWaiters;
    uint32_t mWaiters;  // guarded by mLock
    Condition mAwake;
    Condition mAwake;   // guarded by mLock
    Condition mResume;
    Condition mResume;  // guarded by mLock


    int mWakeReadPipeFd;
    // The next two vectors are only mutated when mPolling is false since they must
    int mWakeWritePipeFd;
    // 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<struct pollfd> mRequestedFds;
    Vector<RequestedCallback> mRequestedCallbacks;
    Vector<RequestedCallback> mRequestedCallbacks;


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