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

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

am 2dfd2aa4: am 92266a78: Merge "More work in progress on native events." into gingerbread

Merge commit '2dfd2aa4'

* commit '2dfd2aa4':
  More work in progress on native events.
parents ce718947 2dfd2aa4
Loading
Loading
Loading
Loading
+14 −3
Original line number Original line Diff line number Diff line
@@ -21,6 +21,9 @@
// Log debug messages about the dispatch cycle.
// Log debug messages about the dispatch cycle.
#define DEBUG_DISPATCH_CYCLE 1
#define DEBUG_DISPATCH_CYCLE 1


// Log debug messages about registrations.
#define DEBUG_REGISTRATION 1



#include "JNIHelp.h"
#include "JNIHelp.h"


@@ -51,7 +54,7 @@ static struct {
class NativeInputQueue {
class NativeInputQueue {
public:
public:
    NativeInputQueue();
    NativeInputQueue();
    virtual ~NativeInputQueue();
    ~NativeInputQueue();


    status_t registerInputChannel(JNIEnv* env, jobject inputChannelObj,
    status_t registerInputChannel(JNIEnv* env, jobject inputChannelObj,
            jobject inputHandlerObj, jobject messageQueueObj);
            jobject inputHandlerObj, jobject messageQueueObj);
@@ -75,7 +78,7 @@ private:


        Connection(const sp<InputChannel>& inputChannel, const sp<PollLoop>& pollLoop);
        Connection(const sp<InputChannel>& inputChannel, const sp<PollLoop>& pollLoop);


        inline const char* getInputChannelName() { return inputChannel->getName().string(); }
        inline const char* getInputChannelName() const { return inputChannel->getName().string(); }


        Status status;
        Status status;


@@ -125,6 +128,10 @@ status_t NativeInputQueue::registerInputChannel(JNIEnv* env, jobject inputChanne
        return BAD_VALUE;
        return BAD_VALUE;
    }
    }


#if DEBUG_REGISTRATION
    LOGD("channel '%s' - Registered", inputChannel->getName().string());
#endif

    sp<PollLoop> pollLoop = android_os_MessageQueue_getPollLoop(env, messageQueueObj);
    sp<PollLoop> pollLoop = android_os_MessageQueue_getPollLoop(env, messageQueueObj);


    int receiveFd;
    int receiveFd;
@@ -154,7 +161,7 @@ status_t NativeInputQueue::registerInputChannel(JNIEnv* env, jobject inputChanne
    android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
    android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
            handleInputChannelDisposed, this);
            handleInputChannelDisposed, this);


    pollLoop->setCallback(receiveFd, POLLIN, handleReceiveCallback, NULL);
    pollLoop->setCallback(receiveFd, POLLIN, handleReceiveCallback, this);
    return OK;
    return OK;
}
}


@@ -166,6 +173,10 @@ status_t NativeInputQueue::unregisterInputChannel(JNIEnv* env, jobject inputChan
        return BAD_VALUE;
        return BAD_VALUE;
    }
    }


#if DEBUG_REGISTRATION
    LOGD("channel '%s' - Unregistered", inputChannel->getName().string());
#endif

    int32_t receiveFd;
    int32_t receiveFd;
    sp<Connection> connection;
    sp<Connection> connection;
    { // acquire lock
    { // acquire lock
+1 −1
Original line number Original line Diff line number Diff line
@@ -19,7 +19,7 @@
#include "JNIHelp.h"
#include "JNIHelp.h"


#include <utils/Log.h>
#include <utils/Log.h>
#include <ui/InputDispatchPolicy.h>
#include <ui/InputDispatcher.h>
#include <ui/InputTransport.h>
#include <ui/InputTransport.h>
#include "android_view_InputTarget.h"
#include "android_view_InputTarget.h"
#include "android_view_InputChannel.h"
#include "android_view_InputChannel.h"
+32 −1
Original line number Original line Diff line number Diff line
@@ -73,7 +73,7 @@ enum {
    POLICY_FLAG_MENU = 0x00000040,
    POLICY_FLAG_MENU = 0x00000040,
    POLICY_FLAG_LAUNCHER = 0x00000080,
    POLICY_FLAG_LAUNCHER = 0x00000080,


    /* These flags are set by the input dispatch policy as it intercepts each event. */
    /* These flags are set by the input reader policy as it intercepts each event. */


    // Indicates that the screen was off when the event was received and the event
    // Indicates that the screen was off when the event was received and the event
    // should wake the device.
    // should wake the device.
@@ -84,6 +84,37 @@ enum {
    POLICY_FLAG_BRIGHT_HERE = 0x20000000,
    POLICY_FLAG_BRIGHT_HERE = 0x20000000,
};
};


/*
 * Describes the basic configuration of input devices that are present.
 */
struct InputConfiguration {
    enum {
        TOUCHSCREEN_UNDEFINED = 0,
        TOUCHSCREEN_NOTOUCH = 1,
        TOUCHSCREEN_STYLUS = 2,
        TOUCHSCREEN_FINGER = 3
    };

    enum {
        KEYBOARD_UNDEFINED = 0,
        KEYBOARD_NOKEYS = 1,
        KEYBOARD_QWERTY = 2,
        KEYBOARD_12KEY = 3
    };

    enum {
        NAVIGATION_UNDEFINED = 0,
        NAVIGATION_NONAV = 1,
        NAVIGATION_DPAD = 2,
        NAVIGATION_TRACKBALL = 3,
        NAVIGATION_WHEEL = 4
    };

    int32_t touchScreen;
    int32_t keyboard;
    int32_t navigation;
};

/*
/*
 * Pointer coordinate data.
 * Pointer coordinate data.
 */
 */

include/ui/InputDispatchPolicy.h

deleted100644 → 0
+0 −198
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_INPUT_DISPATCH_POLICY_H
#define _UI_INPUT_DISPATCH_POLICY_H

/**
 * Native input dispatch policy.
 */

#include <ui/Input.h>
#include <utils/Errors.h>
#include <utils/Vector.h>
#include <utils/Timers.h>
#include <utils/RefBase.h>
#include <utils/String8.h>

namespace android {

class InputChannel;

/*
 * An input target specifies how an input event is to be dispatched to a particular window
 * including the window's input channel, control flags, a timeout, and an X / Y offset to
 * be added to input event coordinates to compensate for the absolute position of the
 * window area.
 */
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 a MotionEvent with ACTION_DOWN falls outside of the area of
         * this target and so should instead be delivered as an ACTION_OUTSIDE to this target. */
        FLAG_OUTSIDE = 0x02,

        /* This flag indicates that a KeyEvent or MotionEvent is being canceled.
         * In the case of a key event, it should be delivered with KeyEvent.FLAG_CANCELED set.
         * In the case of a motion event, it should be delivered as MotionEvent.ACTION_CANCEL. */
        FLAG_CANCEL = 0x04
    };

    // The input channel to be targeted.
    sp<InputChannel> inputChannel;

    // Flags for the input target.
    int32_t flags;

    // The timeout for event delivery to this target in nanoseconds.  Or -1 if none.
    nsecs_t timeout;

    // The x and y offset to add to a MotionEvent as it is delivered.
    // (ignored for KeyEvents)
    float xOffset, yOffset;
};

/*
 * Input dispatch policy interface.
 *
 * The input dispatch policy is used by the input dispatcher to interact with the
 * Window Manager and other system components.  This separation of concerns keeps
 * the input dispatcher relatively free of special case logic such as is required
 * to determine the target of iput events, when to wake the device, how to interact
 * with key guard, and when to transition to the home screen.
 *
 * The actual implementation is partially supported by callbacks into the DVM
 * via JNI.  This class is also mocked in the input dispatcher unit tests since
 * it is an ideal test seam.
 */
class InputDispatchPolicyInterface : public virtual RefBase {
protected:
    InputDispatchPolicyInterface() { }
    virtual ~InputDispatchPolicyInterface() { }

public:
    enum {
        ROTATION_0 = 0,
        ROTATION_90 = 1,
        ROTATION_180 = 2,
        ROTATION_270 = 3
    };

    enum {
        // The input dispatcher should do nothing and discard the input unless other
        // flags are set.
        ACTION_NONE = 0,

        // 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,

        // The input dispatcher should add POLICY_FLAG_WOKE_HERE to the policy flags it
        // passes through the dispatch pipeline.
        ACTION_WOKE_HERE = 0x00000004,

        // The input dispatcher should add POLICY_FLAG_BRIGHT_HERE to the policy flags it
        // passes through the dispatch pipeline.
        ACTION_BRIGHT_HERE = 0x00000008
    };

    enum {
        TOUCHSCREEN_UNDEFINED = 0,
        TOUCHSCREEN_NOTOUCH = 1,
        TOUCHSCREEN_STYLUS = 2,
        TOUCHSCREEN_FINGER = 3
    };

    enum {
        KEYBOARD_UNDEFINED = 0,
        KEYBOARD_NOKEYS = 1,
        KEYBOARD_QWERTY = 2,
        KEYBOARD_12KEY = 3
    };

    enum {
        NAVIGATION_UNDEFINED = 0,
        NAVIGATION_NONAV = 1,
        NAVIGATION_DPAD = 2,
        NAVIGATION_TRACKBALL = 3,
        NAVIGATION_WHEEL = 4
    };

    struct VirtualKeyDefinition {
        int32_t scanCode;

        // configured position data, specified in display coords
        int32_t centerX;
        int32_t centerY;
        int32_t width;
        int32_t height;
    };

    /* Gets information about the display with the specified id.
     * Returns true if the display info is available, false otherwise.
     */
    virtual bool getDisplayInfo(int32_t displayId,
            int32_t* width, int32_t* height, int32_t* orientation) = 0;

    virtual void notifyConfigurationChanged(nsecs_t when,
            int32_t touchScreenConfig, int32_t keyboardConfig, int32_t navigationConfig) = 0;

    virtual void notifyLidSwitchChanged(nsecs_t when, bool lidOpen) = 0;

    virtual void virtualKeyFeedback(nsecs_t when, int32_t deviceId,
            int32_t action, int32_t flags, int32_t keyCode,
            int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;

    virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
            bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) = 0;

    virtual int32_t interceptTrackball(nsecs_t when, bool buttonChanged, bool buttonDown,
            bool rolled) = 0;

    virtual int32_t interceptTouch(nsecs_t when) = 0;

    virtual bool allowKeyRepeat() = 0;
    virtual nsecs_t getKeyRepeatTimeout() = 0;

    virtual void getKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
            Vector<InputTarget>& outTargets) = 0;
    virtual void getMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
            Vector<InputTarget>& outTargets) = 0;

    /* Determine whether to turn on some hacks we have to improve the touch interaction with a
     * certain device whose screen currently is not all that good.
     */
    virtual bool filterTouchEvents() = 0;

    /* Determine whether to turn on some hacks to improve touch interaction with another device
     * where touch coordinate data can get corrupted.
     */
    virtual bool filterJumpyTouchEvents() = 0;

    virtual void getVirtualKeyDefinitions(const String8& deviceName,
            Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) = 0;
    virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) = 0;
};

} // namespace android

#endif // _UI_INPUT_DISPATCH_POLICY_H
+174 −34
Original line number Original line Diff line number Diff line
@@ -18,7 +18,6 @@
#define _UI_INPUT_DISPATCHER_H
#define _UI_INPUT_DISPATCHER_H


#include <ui/Input.h>
#include <ui/Input.h>
#include <ui/InputDispatchPolicy.h>
#include <ui/InputTransport.h>
#include <ui/InputTransport.h>
#include <utils/KeyedVector.h>
#include <utils/KeyedVector.h>
#include <utils/Vector.h>
#include <utils/Vector.h>
@@ -35,6 +34,82 @@


namespace android {
namespace android {


/*
 * An input target specifies how an input event is to be dispatched to a particular window
 * including the window's input channel, control flags, a timeout, and an X / Y offset to
 * be added to input event coordinates to compensate for the absolute position of the
 * window area.
 */
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 a MotionEvent with ACTION_DOWN falls outside of the area of
         * this target and so should instead be delivered as an ACTION_OUTSIDE to this target. */
        FLAG_OUTSIDE = 0x02,

        /* This flag indicates that a KeyEvent or MotionEvent is being canceled.
         * In the case of a key event, it should be delivered with KeyEvent.FLAG_CANCELED set.
         * In the case of a motion event, it should be delivered as MotionEvent.ACTION_CANCEL. */
        FLAG_CANCEL = 0x04
    };

    // The input channel to be targeted.
    sp<InputChannel> inputChannel;

    // Flags for the input target.
    int32_t flags;

    // The timeout for event delivery to this target in nanoseconds.  Or -1 if none.
    nsecs_t timeout;

    // The x and y offset to add to a MotionEvent as it is delivered.
    // (ignored for KeyEvents)
    float xOffset, yOffset;
};

/*
 * Input dispatcher policy interface.
 *
 * The input reader policy is used by the input reader to interact with the Window Manager
 * and other system components.
 *
 * The actual implementation is partially supported by callbacks into the DVM
 * via JNI.  This interface is also mocked in the unit tests.
 */
class InputDispatcherPolicyInterface : public virtual RefBase {
protected:
    InputDispatcherPolicyInterface() { }
    virtual ~InputDispatcherPolicyInterface() { }

public:
    /* Notifies the system that a configuration change has occurred. */
    virtual void notifyConfigurationChanged(nsecs_t when) = 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. */
    virtual void 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 timeout or -1 if automatic key repeating is disabled. */
    virtual nsecs_t getKeyRepeatTimeout() = 0;

    /* Gets the input targets for a key event. */
    virtual void getKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
            Vector<InputTarget>& outTargets) = 0;

    /* Gets the input targets for a motion event. */
    virtual void getMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
            Vector<InputTarget>& outTargets) = 0;
};


/* Notifies the system about input events generated by the input reader.
/* Notifies the system about input events generated by the input reader.
 * The dispatcher is expected to be mostly asynchronous. */
 * The dispatcher is expected to be mostly asynchronous. */
class InputDispatcherInterface : public virtual RefBase {
class InputDispatcherInterface : public virtual RefBase {
@@ -51,14 +126,10 @@ public:
    virtual void dispatchOnce() = 0;
    virtual void dispatchOnce() = 0;


    /* Notifies the dispatcher about new events.
    /* Notifies the dispatcher about new events.
     * The dispatcher will process most of these events asynchronously although some
     * policy processing may occur synchronously.
     *
     *
     * These methods should only be called on the input reader thread.
     * These methods should only be called on the input reader thread.
     */
     */
    virtual void notifyConfigurationChanged(nsecs_t eventTime,
    virtual void notifyConfigurationChanged(nsecs_t eventTime) = 0;
            int32_t touchScreenConfig, int32_t keyboardConfig, int32_t navigationConfig) = 0;
    virtual void notifyLidSwitchChanged(nsecs_t eventTime, bool lidOpen) = 0;
    virtual void notifyAppSwitchComing(nsecs_t eventTime) = 0;
    virtual void notifyAppSwitchComing(nsecs_t eventTime) = 0;
    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
            uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
            uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
@@ -76,19 +147,33 @@ public:
    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
};
};


/* Dispatches events. */
/* 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 InputDispatcherInterface {
class InputDispatcher : public InputDispatcherInterface {
protected:
protected:
    virtual ~InputDispatcher();
    virtual ~InputDispatcher();


public:
public:
    explicit InputDispatcher(const sp<InputDispatchPolicyInterface>& policy);
    explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy);


    virtual void dispatchOnce();
    virtual void dispatchOnce();


    virtual void notifyConfigurationChanged(nsecs_t eventTime,
    virtual void notifyConfigurationChanged(nsecs_t eventTime);
            int32_t touchScreenConfig, int32_t keyboardConfig, int32_t navigationConfig);
    virtual void notifyLidSwitchChanged(nsecs_t eventTime, bool lidOpen);
    virtual void notifyAppSwitchComing(nsecs_t eventTime);
    virtual void notifyAppSwitchComing(nsecs_t eventTime);
    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
            uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
            uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
@@ -119,12 +204,11 @@ private:
        int32_t refCount;
        int32_t refCount;
        int32_t type;
        int32_t type;
        nsecs_t eventTime;
        nsecs_t eventTime;

        bool dispatchInProgress; // initially false, set to true while dispatching
    };
    };


    struct ConfigurationChangedEntry : EventEntry {
    struct ConfigurationChangedEntry : EventEntry {
        int32_t touchScreenConfig;
        int32_t keyboardConfig;
        int32_t navigationConfig;
    };
    };


    struct KeyEntry : EventEntry {
    struct KeyEntry : EventEntry {
@@ -165,6 +249,7 @@ private:
        MotionSample* lastSample;
        MotionSample* lastSample;
    };
    };


    // Tracks the progress of dispatching a particular event to a particular connection.
    struct DispatchEntry : Link<DispatchEntry> {
    struct DispatchEntry : Link<DispatchEntry> {
        EventEntry* eventEntry; // the event to dispatch
        EventEntry* eventEntry; // the event to dispatch
        int32_t targetFlags;
        int32_t targetFlags;
@@ -189,6 +274,36 @@ private:
        MotionSample* tailMotionSample;
        MotionSample* tailMotionSample;
    };
    };


    // A command entry captures state and behavior for an action to be performed in the
    // dispatch loop after the initial processing has taken place.  It is essentially
    // a kind of continuation used to postpone sensitive policy interactions to a point
    // in the dispatch loop where it is safe to release the lock (generally after finishing
    // the critical parts of the dispatch cycle).
    //
    // The special thing about commands is that they can voluntarily release and reacquire
    // the dispatcher lock at will.  Initially when the command starts running, the
    // dispatcher lock is held.  However, if the command needs to call into the policy to
    // do some work, it can release the lock, do the work, then reacquire the lock again
    // before returning.
    //
    // This mechanism is a bit clunky but it helps to preserve the invariant that the dispatch
    // never calls into the policy while holding its lock.
    //
    // Commands are implicitly 'LockedInterruptible'.
    struct CommandEntry;
    typedef void (InputDispatcher::*Command)(CommandEntry* commandEntry);

    struct CommandEntry : Link<CommandEntry> {
        CommandEntry();
        ~CommandEntry();

        Command command;

        // parameters for the command (usage varies by command)
        sp<InputChannel> inputChannel;
    };

    // Generic queue implementation.
    template <typename T>
    template <typename T>
    struct Queue {
    struct Queue {
        T head;
        T head;
@@ -242,17 +357,17 @@ private:
        KeyEntry* obtainKeyEntry();
        KeyEntry* obtainKeyEntry();
        MotionEntry* obtainMotionEntry();
        MotionEntry* obtainMotionEntry();
        DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry);
        DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry);
        CommandEntry* obtainCommandEntry(Command command);


        void releaseEventEntry(EventEntry* entry);
        void releaseEventEntry(EventEntry* entry);
        void releaseConfigurationChangedEntry(ConfigurationChangedEntry* entry);
        void releaseConfigurationChangedEntry(ConfigurationChangedEntry* entry);
        void releaseKeyEntry(KeyEntry* entry);
        void releaseKeyEntry(KeyEntry* entry);
        void releaseMotionEntry(MotionEntry* entry);
        void releaseMotionEntry(MotionEntry* entry);
        void releaseDispatchEntry(DispatchEntry* entry);
        void releaseDispatchEntry(DispatchEntry* entry);
        void releaseCommandEntry(CommandEntry* entry);


        void appendMotionSample(MotionEntry* motionEntry,
        void appendMotionSample(MotionEntry* motionEntry,
                nsecs_t eventTime, int32_t pointerCount, const PointerCoords* pointerCoords);
                nsecs_t eventTime, int32_t pointerCount, const PointerCoords* pointerCoords);
        void freeMotionSample(MotionSample* sample);
        void freeMotionSampleList(MotionSample* head);


    private:
    private:
        Pool<ConfigurationChangedEntry> mConfigurationChangeEntryPool;
        Pool<ConfigurationChangedEntry> mConfigurationChangeEntryPool;
@@ -260,6 +375,7 @@ private:
        Pool<MotionEntry> mMotionEntryPool;
        Pool<MotionEntry> mMotionEntryPool;
        Pool<MotionSample> mMotionSamplePool;
        Pool<MotionSample> mMotionSamplePool;
        Pool<DispatchEntry> mDispatchEntryPool;
        Pool<DispatchEntry> mDispatchEntryPool;
        Pool<CommandEntry> mCommandEntryPool;
    };
    };


    /* Manages the dispatch state associated with a single input channel. */
    /* Manages the dispatch state associated with a single input channel. */
@@ -291,7 +407,9 @@ private:


        explicit Connection(const sp<InputChannel>& inputChannel);
        explicit Connection(const sp<InputChannel>& inputChannel);


        inline const char* getInputChannelName() { return inputChannel->getName().string(); }
        inline const char* getInputChannelName() const { return inputChannel->getName().string(); }

        const char* getStatusLabel() const;


        // Finds a DispatchEntry in the outbound queue associated with the specified event.
        // Finds a DispatchEntry in the outbound queue associated with the specified event.
        // Returns NULL if not found.
        // Returns NULL if not found.
@@ -323,22 +441,23 @@ private:
        status_t initialize();
        status_t initialize();
    };
    };


    sp<InputDispatchPolicyInterface> mPolicy;
    sp<InputDispatcherPolicyInterface> mPolicy;


    Mutex mLock;
    Mutex mLock;


    Queue<EventEntry> mInboundQueue;
    Allocator mAllocator;
    Allocator mAllocator;

    sp<PollLoop> mPollLoop;
    sp<PollLoop> mPollLoop;


    Queue<EventEntry> mInboundQueue;
    Queue<CommandEntry> mCommandQueue;

    // All registered connections mapped by receive pipe file descriptor.
    // All registered connections mapped by receive pipe file descriptor.
    KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd;
    KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd;


    // Active connections are connections that have a non-empty outbound queue.
    // Active connections are connections that have a non-empty outbound queue.
    Vector<Connection*> mActiveConnections;
    Vector<Connection*> mActiveConnections;


    // Pool of key and motion event objects used only to ask the input dispatch policy
    // Preallocated key and motion event objects used only to ask the input dispatcher policy
    // for the targets of an event that is to be dispatched.
    // for the targets of an event that is to be dispatched.
    KeyEvent mReusableKeyEvent;
    KeyEvent mReusableKeyEvent;
    MotionEvent mReusableMotionEvent;
    MotionEvent mReusableMotionEvent;
@@ -347,6 +466,7 @@ private:
    // If there is a synchronous event dispatch in progress, the current input targets will
    // If there is a synchronous event dispatch in progress, the current input targets will
    // remain unchanged until the dispatch has completed or been aborted.
    // remain unchanged until the dispatch has completed or been aborted.
    Vector<InputTarget> mCurrentInputTargets;
    Vector<InputTarget> mCurrentInputTargets;
    bool mCurrentInputTargetsValid; // false while targets are being recomputed


    // Key repeat tracking.
    // Key repeat tracking.
    // XXX Move this up to the input reader instead.
    // XXX Move this up to the input reader instead.
@@ -357,17 +477,27 @@ private:


    void resetKeyRepeatLocked();
    void resetKeyRepeatLocked();


    // Deferred command processing.
    bool runCommandsLockedInterruptible();
    CommandEntry* postCommandLocked(Command command);

    // Process events that have just been dequeued from the head of the input queue.
    // Process events that have just been dequeued from the head of the input queue.
    void processConfigurationChangedLocked(nsecs_t currentTime, ConfigurationChangedEntry* entry);
    void processConfigurationChangedLockedInterruptible(
    void processKeyLocked(nsecs_t currentTime, KeyEntry* entry);
            nsecs_t currentTime, ConfigurationChangedEntry* entry);
    void processKeyRepeatLocked(nsecs_t currentTime);
    void processKeyLockedInterruptible(
    void processMotionLocked(nsecs_t currentTime, MotionEntry* entry);
            nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout);
    void processKeyRepeatLockedInterruptible(
            nsecs_t currentTime, nsecs_t keyRepeatTimeout);
    void processMotionLockedInterruptible(
            nsecs_t currentTime, MotionEntry* entry);


    // Identify input targets for an event and dispatch to them.
    // Identify input targets for an event and dispatch to them.
    void identifyInputTargetsAndDispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry);
    void identifyInputTargetsAndDispatchKeyLockedInterruptible(
    void identifyInputTargetsAndDispatchMotionLocked(nsecs_t currentTime, MotionEntry* entry);
            nsecs_t currentTime, KeyEntry* entry);
    void dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime, EventEntry* entry,
    void identifyInputTargetsAndDispatchMotionLockedInterruptible(
            bool resumeWithAppendedMotionSample);
            nsecs_t currentTime, MotionEntry* entry);
    void dispatchEventToCurrentInputTargetsLocked(
            nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample);


    // Manage the dispatch cycle for a single connection.
    // Manage the dispatch cycle for a single connection.
    void prepareDispatchCycleLocked(nsecs_t currentTime, Connection* connection,
    void prepareDispatchCycleLocked(nsecs_t currentTime, Connection* connection,
@@ -384,12 +514,22 @@ private:
    void activateConnectionLocked(Connection* connection);
    void activateConnectionLocked(Connection* connection);
    void deactivateConnectionLocked(Connection* connection);
    void deactivateConnectionLocked(Connection* connection);


    // Outbound policy interactions.
    void doNotifyConfigurationChangedLockedInterruptible(CommandEntry* commandEntry);

    // Interesting events that we might like to log or tell the framework about.
    // Interesting events that we might like to log or tell the framework about.
    void onDispatchCycleStartedLocked(nsecs_t currentTime, Connection* connection);
    void onDispatchCycleStartedLocked(
    void onDispatchCycleFinishedLocked(nsecs_t currentTime, Connection* connection,
            nsecs_t currentTime, Connection* connection);
            bool recoveredFromANR);
    void onDispatchCycleFinishedLocked(
    void onDispatchCycleANRLocked(nsecs_t currentTime, Connection* connection);
            nsecs_t currentTime, Connection* connection, bool recoveredFromANR);
    void onDispatchCycleBrokenLocked(nsecs_t currentTime, Connection* connection);
    void onDispatchCycleANRLocked(
            nsecs_t currentTime, Connection* connection);
    void onDispatchCycleBrokenLocked(
            nsecs_t currentTime, Connection* connection);

    void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry);
    void doNotifyInputChannelANRLockedInterruptible(CommandEntry* commandEntry);
    void doNotifyInputChannelRecoveredFromANRLockedInterruptible(CommandEntry* commandEntry);
};
};


/* Enqueues and dispatches input events, endlessly. */
/* Enqueues and dispatches input events, endlessly. */
Loading