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

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

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

Merge commit '92266a7894becc1cdf2298fd02380749ab036131' into gingerbread-plus-aosp

* commit '92266a7894becc1cdf2298fd02380749ab036131':
  More work in progress on native events.
parents 405a8521 c10612c7
Loading
Loading
Loading
Loading
+32 −1
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@ enum {
    POLICY_FLAG_MENU = 0x00000040,
    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
    // should wake the device.
@@ -84,6 +84,37 @@ enum {
    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.
 */

include/ui/InputDispatchPolicy.h

deleted100644 → 0
+0 −198
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_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 Diff line number Diff line
@@ -18,7 +18,6 @@
#define _UI_INPUT_DISPATCHER_H

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

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.
 * The dispatcher is expected to be mostly asynchronous. */
class InputDispatcherInterface : public virtual RefBase {
@@ -51,14 +126,10 @@ public:
    virtual void dispatchOnce() = 0;

    /* 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.
     */
    virtual void notifyConfigurationChanged(nsecs_t eventTime,
            int32_t touchScreenConfig, int32_t keyboardConfig, int32_t navigationConfig) = 0;
    virtual void notifyLidSwitchChanged(nsecs_t eventTime, bool lidOpen) = 0;
    virtual void notifyConfigurationChanged(nsecs_t eventTime) = 0;
    virtual void notifyAppSwitchComing(nsecs_t eventTime) = 0;
    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
            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;
};

/* 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 {
protected:
    virtual ~InputDispatcher();

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

    virtual void dispatchOnce();

    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 notifyConfigurationChanged(nsecs_t eventTime);
    virtual void notifyAppSwitchComing(nsecs_t eventTime);
    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
            uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
@@ -119,12 +204,11 @@ private:
        int32_t refCount;
        int32_t type;
        nsecs_t eventTime;

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

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

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

    // Tracks the progress of dispatching a particular event to a particular connection.
    struct DispatchEntry : Link<DispatchEntry> {
        EventEntry* eventEntry; // the event to dispatch
        int32_t targetFlags;
@@ -189,6 +274,36 @@ private:
        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>
    struct Queue {
        T head;
@@ -242,17 +357,17 @@ private:
        KeyEntry* obtainKeyEntry();
        MotionEntry* obtainMotionEntry();
        DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry);
        CommandEntry* obtainCommandEntry(Command command);

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

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

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

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

        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.
        // Returns NULL if not found.
@@ -323,22 +441,23 @@ private:
        status_t initialize();
    };

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

    Mutex mLock;

    Queue<EventEntry> mInboundQueue;
    Allocator mAllocator;

    sp<PollLoop> mPollLoop;

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

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

    // Active connections are connections that have a non-empty outbound queue.
    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.
    KeyEvent mReusableKeyEvent;
    MotionEvent mReusableMotionEvent;
@@ -347,6 +466,7 @@ private:
    // If there is a synchronous event dispatch in progress, the current input targets will
    // remain unchanged until the dispatch has completed or been aborted.
    Vector<InputTarget> mCurrentInputTargets;
    bool mCurrentInputTargetsValid; // false while targets are being recomputed

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

    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.
    void processConfigurationChangedLocked(nsecs_t currentTime, ConfigurationChangedEntry* entry);
    void processKeyLocked(nsecs_t currentTime, KeyEntry* entry);
    void processKeyRepeatLocked(nsecs_t currentTime);
    void processMotionLocked(nsecs_t currentTime, MotionEntry* entry);
    void processConfigurationChangedLockedInterruptible(
            nsecs_t currentTime, ConfigurationChangedEntry* entry);
    void processKeyLockedInterruptible(
            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.
    void identifyInputTargetsAndDispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry);
    void identifyInputTargetsAndDispatchMotionLocked(nsecs_t currentTime, MotionEntry* entry);
    void dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime, EventEntry* entry,
            bool resumeWithAppendedMotionSample);
    void identifyInputTargetsAndDispatchKeyLockedInterruptible(
            nsecs_t currentTime, KeyEntry* entry);
    void identifyInputTargetsAndDispatchMotionLockedInterruptible(
            nsecs_t currentTime, MotionEntry* entry);
    void dispatchEventToCurrentInputTargetsLocked(
            nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample);

    // Manage the dispatch cycle for a single connection.
    void prepareDispatchCycleLocked(nsecs_t currentTime, Connection* connection,
@@ -384,12 +514,22 @@ private:
    void activateConnectionLocked(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.
    void onDispatchCycleStartedLocked(nsecs_t currentTime, Connection* connection);
    void onDispatchCycleFinishedLocked(nsecs_t currentTime, Connection* connection,
            bool recoveredFromANR);
    void onDispatchCycleANRLocked(nsecs_t currentTime, Connection* connection);
    void onDispatchCycleBrokenLocked(nsecs_t currentTime, Connection* connection);
    void onDispatchCycleStartedLocked(
            nsecs_t currentTime, Connection* connection);
    void onDispatchCycleFinishedLocked(
            nsecs_t currentTime, Connection* connection, bool recoveredFromANR);
    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. */
+26 −18

File changed.

Preview size limit exceeded, changes collapsed.

+176 −27

File changed.

Preview size limit exceeded, changes collapsed.

Loading