Loading core/jni/android_view_InputQueue.cpp +14 −3 Original line number Original line Diff line number Diff line Loading @@ -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" Loading Loading @@ -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); Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; } } Loading @@ -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 Loading core/jni/android_view_InputTarget.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -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" Loading include/ui/Input.h +32 −1 Original line number Original line Diff line number Diff line Loading @@ -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. Loading @@ -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. */ */ Loading include/ui/InputDispatchPolicy.hdeleted 100644 → 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 include/ui/InputDispatcher.h +174 −34 Original line number Original line Diff line number Diff line Loading @@ -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> Loading @@ -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 { Loading @@ -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, Loading @@ -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, Loading Loading @@ -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 { Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading @@ -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. */ Loading Loading @@ -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. Loading Loading @@ -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; Loading @@ -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. Loading @@ -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, Loading @@ -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 Loading
core/jni/android_view_InputQueue.cpp +14 −3 Original line number Original line Diff line number Diff line Loading @@ -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" Loading Loading @@ -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); Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; } } Loading @@ -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 Loading
core/jni/android_view_InputTarget.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -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" Loading
include/ui/Input.h +32 −1 Original line number Original line Diff line number Diff line Loading @@ -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. Loading @@ -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. */ */ Loading
include/ui/InputDispatchPolicy.hdeleted 100644 → 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
include/ui/InputDispatcher.h +174 −34 Original line number Original line Diff line number Diff line Loading @@ -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> Loading @@ -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 { Loading @@ -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, Loading @@ -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, Loading Loading @@ -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 { Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading @@ -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. */ Loading Loading @@ -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. Loading Loading @@ -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; Loading @@ -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. Loading @@ -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, Loading @@ -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