Input dispatcher ANR handling enhancements.

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

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

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

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

Added more comments to describe the tricky parts of PollLoop.

Change-Id: I13dffca27acb436fc383980db536abc4d8b9e6f1
This commit is contained in:
Jeff Brown
2010-09-08 11:49:43 -07:00
parent 11fe181e16
commit b88102f5b7
15 changed files with 2589 additions and 1978 deletions

View File

@@ -224,8 +224,8 @@ public class MessageQueue {
msg.next = prev.next; msg.next = prev.next;
prev.next = msg; prev.next = msg;
} }
nativeWake();
} }
nativeWake();
return true; return true;
} }

View File

@@ -30,6 +30,7 @@
#include <stddef.h> #include <stddef.h>
#include <unistd.h> #include <unistd.h>
#include <limits.h>
namespace android { namespace android {
@@ -108,15 +109,134 @@ struct InputTarget {
// Flags for the input target. // Flags for the input target.
int32_t flags; int32_t flags;
// The timeout for event delivery to this target in nanoseconds. Or -1 if none. // The timeout for event delivery to this target in nanoseconds, or -1 to wait indefinitely.
nsecs_t timeout; nsecs_t timeout;
// The time already spent waiting for this target in nanoseconds, or 0 if none.
nsecs_t timeSpentWaitingForApplication;
// The x and y offset to add to a MotionEvent as it is delivered. // The x and y offset to add to a MotionEvent as it is delivered.
// (ignored for KeyEvents) // (ignored for KeyEvents)
float xOffset, yOffset; float xOffset, yOffset;
}; };
/*
* An input window describes the bounds of a window that can receive input.
*/
struct InputWindow {
// Window flags from WindowManager.LayoutParams
enum {
FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
FLAG_DIM_BEHIND = 0x00000002,
FLAG_BLUR_BEHIND = 0x00000004,
FLAG_NOT_FOCUSABLE = 0x00000008,
FLAG_NOT_TOUCHABLE = 0x00000010,
FLAG_NOT_TOUCH_MODAL = 0x00000020,
FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
FLAG_KEEP_SCREEN_ON = 0x00000080,
FLAG_LAYOUT_IN_SCREEN = 0x00000100,
FLAG_LAYOUT_NO_LIMITS = 0x00000200,
FLAG_FULLSCREEN = 0x00000400,
FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
FLAG_DITHER = 0x00001000,
FLAG_SECURE = 0x00002000,
FLAG_SCALED = 0x00004000,
FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
FLAG_LAYOUT_INSET_DECOR = 0x00010000,
FLAG_ALT_FOCUSABLE_IM = 0x00020000,
FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
FLAG_SHOW_WHEN_LOCKED = 0x00080000,
FLAG_SHOW_WALLPAPER = 0x00100000,
FLAG_TURN_SCREEN_ON = 0x00200000,
FLAG_DISMISS_KEYGUARD = 0x00400000,
FLAG_IMMERSIVE = 0x00800000,
FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
FLAG_COMPATIBLE_WINDOW = 0x20000000,
FLAG_SYSTEM_ERROR = 0x40000000,
};
// Window types from WindowManager.LayoutParams
enum {
FIRST_APPLICATION_WINDOW = 1,
TYPE_BASE_APPLICATION = 1,
TYPE_APPLICATION = 2,
TYPE_APPLICATION_STARTING = 3,
LAST_APPLICATION_WINDOW = 99,
FIRST_SUB_WINDOW = 1000,
TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW,
TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1,
TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4,
LAST_SUB_WINDOW = 1999,
FIRST_SYSTEM_WINDOW = 2000,
TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW,
TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1,
TYPE_PHONE = FIRST_SYSTEM_WINDOW+2,
TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3,
TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4,
TYPE_TOAST = FIRST_SYSTEM_WINDOW+5,
TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6,
TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7,
TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8,
TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9,
TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10,
TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11,
TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13,
TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14,
LAST_SYSTEM_WINDOW = 2999,
};
sp<InputChannel> inputChannel;
int32_t layoutParamsFlags;
int32_t layoutParamsType;
nsecs_t dispatchingTimeout;
int32_t frameLeft;
int32_t frameTop;
int32_t frameRight;
int32_t frameBottom;
int32_t visibleFrameLeft;
int32_t visibleFrameTop;
int32_t visibleFrameRight;
int32_t visibleFrameBottom;
int32_t touchableAreaLeft;
int32_t touchableAreaTop;
int32_t touchableAreaRight;
int32_t touchableAreaBottom;
bool visible;
bool hasFocus;
bool hasWallpaper;
bool paused;
int32_t ownerPid;
int32_t ownerUid;
bool visibleFrameIntersects(const InputWindow* other) const;
bool touchableAreaContainsPoint(int32_t x, int32_t y) const;
};
/*
* A private handle type used by the input manager to track the window.
*/
class InputApplicationHandle : public RefBase {
protected:
InputApplicationHandle() { }
virtual ~InputApplicationHandle() { }
};
/*
* An input application describes properties of an application that can receive input.
*/
struct InputApplication {
String8 name;
nsecs_t dispatchingTimeout;
sp<InputApplicationHandle> handle;
};
/* /*
* Input dispatcher policy interface. * Input dispatcher policy interface.
* *
@@ -135,14 +255,16 @@ public:
/* Notifies the system that a configuration change has occurred. */ /* Notifies the system that a configuration change has occurred. */
virtual void notifyConfigurationChanged(nsecs_t when) = 0; virtual void notifyConfigurationChanged(nsecs_t when) = 0;
/* Notifies the system that an application is not responding.
* Returns a new timeout to continue waiting, or 0 to abort dispatch. */
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle) = 0;
/* Notifies the system that an input channel is unrecoverably broken. */ /* Notifies the system that an input channel is unrecoverably broken. */
virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) = 0; virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) = 0;
/* Notifies the system that an input channel is not responding. /* Notifies the system that an input channel is not responding.
* Returns true and a new timeout value if the dispatcher should keep waiting. * Returns a new timeout to continue waiting, or 0 to abort dispatch. */
* Otherwise returns false. */ virtual nsecs_t notifyInputChannelANR(const sp<InputChannel>& inputChannel) = 0;
virtual bool notifyInputChannelANR(const sp<InputChannel>& inputChannel,
nsecs_t& outNewTimeout) = 0;
/* Notifies the system that an input channel recovered from ANR. */ /* Notifies the system that an input channel recovered from ANR. */
virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) = 0; virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) = 0;
@@ -153,29 +275,27 @@ public:
/* Gets the key repeat inter-key delay. */ /* Gets the key repeat inter-key delay. */
virtual nsecs_t getKeyRepeatDelay() = 0; virtual nsecs_t getKeyRepeatDelay() = 0;
/* Waits for key event input targets to become available.
* If the event is being injected, injectorPid and injectorUid should specify the
* process id and used id of the injecting application, otherwise they should both
* be -1.
* Returns one of the INPUT_EVENT_INJECTION_XXX constants. */
virtual int32_t waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
int32_t injectorPid, int32_t injectorUid,
Vector<InputTarget>& outTargets) = 0;
/* Waits for motion event targets to become available.
* If the event is being injected, injectorPid and injectorUid should specify the
* process id and used id of the injecting application, otherwise they should both
* be -1.
* Returns one of the INPUT_EVENT_INJECTION_XXX constants. */
virtual int32_t waitForMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
int32_t injectorPid, int32_t injectorUid,
Vector<InputTarget>& outTargets) = 0;
/* Gets the maximum suggested event delivery rate per second. /* Gets the maximum suggested event delivery rate per second.
* This value is used to throttle motion event movement actions on a per-device * This value is used to throttle motion event movement actions on a per-device
* basis. It is not intended to be a hard limit. * basis. It is not intended to be a hard limit.
*/ */
virtual int32_t getMaxEventsPerSecond() = 0; virtual int32_t getMaxEventsPerSecond() = 0;
/* Allows the policy a chance to intercept a key before dispatching. */
virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
/* Poke user activity for an event dispatched to a window. */
virtual void pokeUserActivity(nsecs_t eventTime, int32_t windowType, int32_t eventType) = 0;
/* Checks whether a given application pid/uid has permission to inject input events
* into other applications.
*
* This method is special in that its implementation promises to be non-reentrant and
* is safe to call while holding other locks. (Most other methods make no such guarantees!)
*/
virtual bool checkInjectEventsPermissionNonReentrant(
int32_t injectorPid, int32_t injectorUid) = 0;
}; };
@@ -187,6 +307,11 @@ protected:
virtual ~InputDispatcherInterface() { } virtual ~InputDispatcherInterface() { }
public: public:
/* Dumps the state of the input dispatcher.
*
* This method may be called on any thread (usually by the input manager). */
virtual void dump(String8& dump) = 0;
/* Runs a single iteration of the dispatch loop. /* Runs a single iteration of the dispatch loop.
* Nominally processes one queued event, a timeout, or a response from an input consumer. * Nominally processes one queued event, a timeout, or a response from an input consumer.
* *
@@ -199,7 +324,6 @@ public:
* 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) = 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 source, virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode, uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0; int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;
@@ -219,6 +343,24 @@ public:
virtual int32_t injectInputEvent(const InputEvent* event, virtual int32_t injectInputEvent(const InputEvent* event,
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) = 0; int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) = 0;
/* Sets the list of input windows.
*
* This method may be called on any thread (usually by the input manager).
*/
virtual void setInputWindows(const Vector<InputWindow>& inputWindows) = 0;
/* Sets the focused application.
*
* This method may be called on any thread (usually by the input manager).
*/
virtual void setFocusedApplication(const InputApplication* inputApplication) = 0;
/* Sets the input dispatching mode.
*
* This method may be called on any thread (usually by the input manager).
*/
virtual void setInputDispatchMode(bool enabled, bool frozen) = 0;
/* Preempts input dispatch in progress by making pending synchronous /* Preempts input dispatch in progress by making pending synchronous
* dispatches asynchronous instead. This method is generally called during a focus * dispatches asynchronous instead. This method is generally called during a focus
* transition from one application to the next so as to enable the new application * transition from one application to the next so as to enable the new application
@@ -230,10 +372,11 @@ public:
virtual void preemptInputDispatch() = 0; virtual void preemptInputDispatch() = 0;
/* Registers or unregister input channels that may be used as targets for input events. /* Registers or unregister input channels that may be used as targets for input events.
* If monitor is true, the channel will receive a copy of all input events.
* *
* These methods may be called on any thread (usually by the input manager). * These methods may be called on any thread (usually by the input manager).
*/ */
virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel) = 0; virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) = 0;
virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0; virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
}; };
@@ -261,10 +404,11 @@ protected:
public: public:
explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy); explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy);
virtual void dump(String8& dump);
virtual void dispatchOnce(); virtual void dispatchOnce();
virtual void notifyConfigurationChanged(nsecs_t eventTime); virtual void notifyConfigurationChanged(nsecs_t eventTime);
virtual void notifyAppSwitchComing(nsecs_t eventTime);
virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source, virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode, uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
int32_t scanCode, int32_t metaState, nsecs_t downTime); int32_t scanCode, int32_t metaState, nsecs_t downTime);
@@ -277,9 +421,12 @@ public:
virtual int32_t injectInputEvent(const InputEvent* event, virtual int32_t injectInputEvent(const InputEvent* event,
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis); int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis);
virtual void setInputWindows(const Vector<InputWindow>& inputWindows);
virtual void setFocusedApplication(const InputApplication* inputApplication);
virtual void setInputDispatchMode(bool enabled, bool frozen);
virtual void preemptInputDispatch(); virtual void preemptInputDispatch();
virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel); virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor);
virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel); virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
private: private:
@@ -310,6 +457,8 @@ private:
int32_t pendingSyncDispatches; // the number of synchronous dispatches in progress int32_t pendingSyncDispatches; // the number of synchronous dispatches in progress
inline bool isInjected() { return injectorPid >= 0; } inline bool isInjected() { return injectorPid >= 0; }
void recycle();
}; };
struct ConfigurationChangedEntry : EventEntry { struct ConfigurationChangedEntry : EventEntry {
@@ -326,6 +475,17 @@ private:
int32_t metaState; int32_t metaState;
int32_t repeatCount; int32_t repeatCount;
nsecs_t downTime; nsecs_t downTime;
bool syntheticRepeat; // set to true for synthetic key repeats
enum InterceptKeyResult {
INTERCEPT_KEY_RESULT_UNKNOWN,
INTERCEPT_KEY_RESULT_SKIP,
INTERCEPT_KEY_RESULT_CONTINUE,
};
InterceptKeyResult interceptKeyResult; // set based on the interception result
void recycle();
}; };
struct MotionSample { struct MotionSample {
@@ -380,9 +540,13 @@ private:
// will be set to NULL. // will be set to NULL.
MotionSample* tailMotionSample; MotionSample* tailMotionSample;
inline bool isSyncTarget() { inline bool isSyncTarget() const {
return targetFlags & InputTarget::FLAG_SYNC; return targetFlags & InputTarget::FLAG_SYNC;
} }
inline void preemptSyncTarget() {
targetFlags &= ~ InputTarget::FLAG_SYNC;
}
}; };
// A command entry captures state and behavior for an action to be performed in the // A command entry captures state and behavior for an action to be performed in the
@@ -413,37 +577,43 @@ private:
// parameters for the command (usage varies by command) // parameters for the command (usage varies by command)
sp<Connection> connection; sp<Connection> connection;
nsecs_t eventTime;
KeyEntry* keyEntry;
sp<InputChannel> inputChannel;
sp<InputApplicationHandle> inputApplicationHandle;
int32_t windowType;
int32_t userActivityEventType;
}; };
// Generic queue implementation. // Generic queue implementation.
template <typename T> template <typename T>
struct Queue { struct Queue {
T head; T headSentinel;
T tail; T tailSentinel;
inline Queue() { inline Queue() {
head.prev = NULL; headSentinel.prev = NULL;
head.next = & tail; headSentinel.next = & tailSentinel;
tail.prev = & head; tailSentinel.prev = & headSentinel;
tail.next = NULL; tailSentinel.next = NULL;
} }
inline bool isEmpty() { inline bool isEmpty() const {
return head.next == & tail; return headSentinel.next == & tailSentinel;
} }
inline void enqueueAtTail(T* entry) { inline void enqueueAtTail(T* entry) {
T* last = tail.prev; T* last = tailSentinel.prev;
last->next = entry; last->next = entry;
entry->prev = last; entry->prev = last;
entry->next = & tail; entry->next = & tailSentinel;
tail.prev = entry; tailSentinel.prev = entry;
} }
inline void enqueueAtHead(T* entry) { inline void enqueueAtHead(T* entry) {
T* first = head.next; T* first = headSentinel.next;
head.next = entry; headSentinel.next = entry;
entry->prev = & head; entry->prev = & headSentinel;
entry->next = first; entry->next = first;
first->prev = entry; first->prev = entry;
} }
@@ -454,7 +624,7 @@ private:
} }
inline T* dequeueAtHead() { inline T* dequeueAtHead() {
T* first = head.next; T* first = headSentinel.next;
dequeue(first); dequeue(first);
return first; return first;
} }
@@ -476,7 +646,8 @@ private:
float xPrecision, float yPrecision, float xPrecision, float yPrecision,
nsecs_t downTime, uint32_t pointerCount, nsecs_t downTime, uint32_t pointerCount,
const int32_t* pointerIds, const PointerCoords* pointerCoords); const int32_t* pointerIds, const PointerCoords* pointerCoords);
DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry); DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry,
int32_t targetFlags, float xOffset, float yOffset, nsecs_t timeout);
CommandEntry* obtainCommandEntry(Command command); CommandEntry* obtainCommandEntry(Command command);
void releaseEventEntry(EventEntry* entry); void releaseEventEntry(EventEntry* entry);
@@ -500,6 +671,85 @@ private:
void initializeEventEntry(EventEntry* entry, int32_t type, nsecs_t eventTime); void initializeEventEntry(EventEntry* entry, int32_t type, nsecs_t eventTime);
}; };
/* Tracks dispatched key and motion event state so that cancelation events can be
* synthesized when events are dropped. */
class InputState {
public:
// Specifies whether a given event will violate input state consistency.
enum Consistency {
// The event is consistent with the current input state.
CONSISTENT,
// The event is inconsistent with the current input state but applications
// will tolerate it. eg. Down followed by another down.
TOLERABLE,
// The event is inconsistent with the current input state and will probably
// cause applications to crash. eg. Up without prior down, move with
// unexpected number of pointers.
BROKEN
};
InputState();
~InputState();
// Returns true if there is no state to be canceled.
bool isNeutral() const;
// Returns true if the input state believes it is out of sync.
bool isOutOfSync() const;
// Sets the input state to be out of sync if it is not neutral.
void setOutOfSync();
// Resets the input state out of sync flag.
void resetOutOfSync();
// Records tracking information for an event that has just been published.
// Returns whether the event is consistent with the current input state.
Consistency trackEvent(const EventEntry* entry);
// Records tracking information for a key event that has just been published.
// Returns whether the event is consistent with the current input state.
Consistency trackKey(const KeyEntry* entry);
// Records tracking information for a motion event that has just been published.
// Returns whether the event is consistent with the current input state.
Consistency trackMotion(const MotionEntry* entry);
// Synthesizes cancelation events for the current state.
void synthesizeCancelationEvents(Allocator* allocator,
Vector<EventEntry*>& outEvents) const;
// Clears the current state.
void clear();
private:
bool mIsOutOfSync;
struct KeyMemento {
int32_t deviceId;
int32_t source;
int32_t keyCode;
int32_t scanCode;
nsecs_t downTime;
};
struct MotionMemento {
int32_t deviceId;
int32_t source;
float xPrecision;
float yPrecision;
nsecs_t downTime;
uint32_t pointerCount;
int32_t pointerIds[MAX_POINTERS];
PointerCoords pointerCoords[MAX_POINTERS];
void setPointers(const MotionEntry* entry);
};
Vector<KeyMemento> mKeyMementos;
Vector<MotionMemento> mMotionMementos;
};
/* Manages the dispatch state associated with a single input channel. */ /* Manages the dispatch state associated with a single input channel. */
class Connection : public RefBase { class Connection : public RefBase {
protected: protected:
@@ -520,6 +770,7 @@ private:
Status status; Status status;
sp<InputChannel> inputChannel; sp<InputChannel> inputChannel;
InputPublisher inputPublisher; InputPublisher inputPublisher;
InputState inputState;
Queue<DispatchEntry> outboundQueue; Queue<DispatchEntry> outboundQueue;
nsecs_t nextTimeoutTime; // next timeout time (LONG_LONG_MAX if none) nsecs_t nextTimeoutTime; // next timeout time (LONG_LONG_MAX if none)
@@ -540,28 +791,34 @@ private:
// Determine whether this connection has a pending synchronous dispatch target. // Determine whether this connection has a pending synchronous dispatch target.
// Since there can only ever be at most one such target at a time, if there is one, // Since there can only ever be at most one such target at a time, if there is one,
// it must be at the tail because nothing else can be enqueued after it. // it must be at the tail because nothing else can be enqueued after it.
inline bool hasPendingSyncTarget() { inline bool hasPendingSyncTarget() const {
return ! outboundQueue.isEmpty() && outboundQueue.tail.prev->isSyncTarget(); return ! outboundQueue.isEmpty() && outboundQueue.tailSentinel.prev->isSyncTarget();
}
// Assuming there is a pending sync target, make it async.
inline void preemptSyncTarget() {
outboundQueue.tailSentinel.prev->preemptSyncTarget();
} }
// Gets the time since the current event was originally obtained from the input driver. // Gets the time since the current event was originally obtained from the input driver.
inline double getEventLatencyMillis(nsecs_t currentTime) { inline double getEventLatencyMillis(nsecs_t currentTime) const {
return (currentTime - lastEventTime) / 1000000.0; return (currentTime - lastEventTime) / 1000000.0;
} }
// Gets the time since the current event entered the outbound dispatch queue. // Gets the time since the current event entered the outbound dispatch queue.
inline double getDispatchLatencyMillis(nsecs_t currentTime) { inline double getDispatchLatencyMillis(nsecs_t currentTime) const {
return (currentTime - lastDispatchTime) / 1000000.0; return (currentTime - lastDispatchTime) / 1000000.0;
} }
// Gets the time since the current event ANR was declared, if applicable. // Gets the time since the current event ANR was declared, if applicable.
inline double getANRLatencyMillis(nsecs_t currentTime) { inline double getANRLatencyMillis(nsecs_t currentTime) const {
return (currentTime - lastANRTime) / 1000000.0; return (currentTime - lastANRTime) / 1000000.0;
} }
status_t initialize(); status_t initialize();
void setNextTimeoutTime(nsecs_t currentTime, nsecs_t timeout); void setNextTimeoutTime(nsecs_t currentTime, nsecs_t timeout);
void resetTimeout(nsecs_t currentTime);
}; };
sp<InputDispatcherPolicyInterface> mPolicy; sp<InputDispatcherPolicyInterface> mPolicy;
@@ -571,9 +828,26 @@ private:
Allocator mAllocator; Allocator mAllocator;
sp<PollLoop> mPollLoop; sp<PollLoop> mPollLoop;
EventEntry* mPendingEvent;
Queue<EventEntry> mInboundQueue; Queue<EventEntry> mInboundQueue;
Queue<CommandEntry> mCommandQueue; Queue<CommandEntry> mCommandQueue;
Vector<EventEntry*> mTempCancelationEvents;
void dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout, nsecs_t keyRepeatDelay,
nsecs_t* nextWakeupTime);
// Enqueues an inbound event. Returns true if mPollLoop->wake() should be called.
bool enqueueInboundEventLocked(EventEntry* entry);
// App switch latency optimization.
nsecs_t mAppSwitchDueTime;
static bool isAppSwitchKey(int32_t keyCode);
bool isAppSwitchPendingLocked();
bool detectPendingAppSwitchLocked(KeyEntry* inboundKeyEntry);
void resetPendingAppSwitchLocked(bool handled);
// 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;
@@ -591,20 +865,15 @@ private:
// the duration. // the duration.
Vector<Connection*> mTimedOutConnections; Vector<Connection*> mTimedOutConnections;
// Preallocated key and motion event objects used only to ask the input dispatcher policy // Input channels that will receive a copy of all input events.
// for the targets of an event that is to be dispatched. Vector<sp<InputChannel> > mMonitoringChannels;
KeyEvent mReusableKeyEvent;
MotionEvent mReusableMotionEvent;
// The input targets that were most recently identified for dispatch. // Preallocated key event object used for policy inquiries.
// If there is a synchronous event dispatch in progress, the current input targets will KeyEvent mReusableKeyEvent;
// remain unchanged until the dispatch has completed or been aborted.
Vector<InputTarget> mCurrentInputTargets;
bool mCurrentInputTargetsValid; // false while targets are being recomputed
// Event injection and synchronization. // Event injection and synchronization.
Condition mInjectionResultAvailableCondition; Condition mInjectionResultAvailableCondition;
EventEntry* createEntryFromInputEventLocked(const InputEvent* event); EventEntry* createEntryFromInjectedInputEventLocked(const InputEvent* event);
void setInjectionResultLocked(EventEntry* entry, int32_t injectionResult); void setInjectionResultLocked(EventEntry* entry, int32_t injectionResult);
Condition mInjectionSyncFinishedCondition; Condition mInjectionSyncFinishedCondition;
@@ -622,36 +891,108 @@ private:
} mThrottleState; } mThrottleState;
// Key repeat tracking. // Key repeat tracking.
// XXX Move this up to the input reader instead.
struct KeyRepeatState { struct KeyRepeatState {
KeyEntry* lastKeyEntry; // or null if no repeat KeyEntry* lastKeyEntry; // or null if no repeat
nsecs_t nextRepeatTime; nsecs_t nextRepeatTime;
} mKeyRepeatState; } mKeyRepeatState;
void resetKeyRepeatLocked(); void resetKeyRepeatLocked();
KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime, nsecs_t keyRepeatTimeout);
// Deferred command processing. // Deferred command processing.
bool runCommandsLockedInterruptible(); bool runCommandsLockedInterruptible();
CommandEntry* postCommandLocked(Command command); CommandEntry* postCommandLocked(Command command);
// Process events that have just been dequeued from the head of the input queue. // Inbound event processing.
void processConfigurationChangedLockedInterruptible( void drainInboundQueueLocked();
nsecs_t currentTime, ConfigurationChangedEntry* entry); void releasePendingEventLocked(bool wasDropped);
void processKeyLockedInterruptible( void releaseInboundEventLocked(EventEntry* entry, bool wasDropped);
nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout); bool isEventFromReliableSourceLocked(EventEntry* entry);
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. // Dispatch state.
void identifyInputTargetsAndDispatchKeyLockedInterruptible( bool mDispatchEnabled;
nsecs_t currentTime, KeyEntry* entry); bool mDispatchFrozen;
void identifyInputTargetsAndDispatchMotionLockedInterruptible( Vector<InputWindow> mWindows;
nsecs_t currentTime, MotionEntry* entry); Vector<InputWindow*> mWallpaperWindows;
// Focus tracking for keys, trackball, etc.
InputWindow* mFocusedWindow;
// Focus tracking for touch.
bool mTouchDown;
InputWindow* mTouchedWindow; // primary target for current down
bool mTouchedWindowIsObscured; // true if other windows may obscure the target
Vector<InputWindow*> mTouchedWallpaperWindows; // wallpaper targets
struct OutsideTarget {
InputWindow* window;
bool obscured;
};
Vector<OutsideTarget> mTempTouchedOutsideTargets; // temporary outside touch targets
Vector<sp<InputChannel> > mTempTouchedWallpaperChannels; // temporary wallpaper targets
// Focused application.
InputApplication* mFocusedApplication;
InputApplication mFocusedApplicationStorage; // preallocated storage for mFocusedApplication
void releaseFocusedApplicationLocked();
// Dispatch inbound events.
bool dispatchConfigurationChangedLocked(
nsecs_t currentTime, ConfigurationChangedEntry* entry);
bool dispatchKeyLocked(
nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
nsecs_t* nextWakeupTime);
bool dispatchMotionLocked(
nsecs_t currentTime, MotionEntry* entry,
nsecs_t* nextWakeupTime);
void dispatchEventToCurrentInputTargetsLocked( void dispatchEventToCurrentInputTargetsLocked(
nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample); nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample);
void logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry);
void logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry);
// The input targets that were most recently identified for dispatch.
// If there is a synchronous event dispatch in progress, the current input targets will
// remain unchanged until the dispatch has completed or been aborted.
bool mCurrentInputTargetsValid; // false while targets are being recomputed
Vector<InputTarget> mCurrentInputTargets;
int32_t mCurrentInputWindowType;
sp<InputChannel> mCurrentInputChannel;
enum InputTargetWaitCause {
INPUT_TARGET_WAIT_CAUSE_NONE,
INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY,
INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY,
};
InputTargetWaitCause mInputTargetWaitCause;
nsecs_t mInputTargetWaitStartTime;
nsecs_t mInputTargetWaitTimeoutTime;
bool mInputTargetWaitTimeoutExpired;
// Finding targets for input events.
void startFindingTargetsLocked();
void finishFindingTargetsLocked(const InputWindow* window);
int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry,
const InputApplication* application, const InputWindow* window,
nsecs_t* nextWakeupTime);
void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout);
nsecs_t getTimeSpentWaitingForApplicationWhileFindingTargetsLocked(nsecs_t currentTime);
void resetANRTimeoutsLocked();
int32_t findFocusedWindowLocked(nsecs_t currentTime, const EventEntry* entry,
nsecs_t* nextWakeupTime, InputWindow** outWindow);
int32_t findTouchedWindowLocked(nsecs_t currentTime, const MotionEntry* entry,
nsecs_t* nextWakeupTime, InputWindow** outWindow);
void addWindowTargetLocked(const InputWindow* window, int32_t targetFlags,
nsecs_t timeSpentWaitingForApplication);
void addMonitoringTargetsLocked();
void pokeUserActivityLocked(nsecs_t eventTime, int32_t windowType, int32_t eventType);
bool checkInjectionPermission(const InputWindow* window,
int32_t injectorPid, int32_t injectorUid);
bool isWindowObscuredLocked(const InputWindow* window);
void releaseTouchedWindowLocked();
// Manage the dispatch cycle for a single connection. // Manage the dispatch cycle for a single connection.
// These methods are deliberately not Interruptible because doing all of the work // These methods are deliberately not Interruptible because doing all of the work
// with the mutex held makes it easier to ensure that connection invariants are maintained. // with the mutex held makes it easier to ensure that connection invariants are maintained.
@@ -659,15 +1000,25 @@ private:
void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
EventEntry* eventEntry, const InputTarget* inputTarget, EventEntry* eventEntry, const InputTarget* inputTarget,
bool resumeWithAppendedMotionSample); bool resumeWithAppendedMotionSample);
void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection); void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
nsecs_t timeSpentWaitingForApplication);
void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection); void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
void startNextDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
void timeoutDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection); void timeoutDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
void resumeAfterTimeoutDispatchCycleLocked(nsecs_t currentTime, void resumeAfterTimeoutDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection, nsecs_t newTimeout); const sp<Connection>& connection, nsecs_t newTimeout);
void abortDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, void abortDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
bool broken); bool broken);
void drainOutboundQueueLocked(Connection* connection, DispatchEntry* firstDispatchEntryToDrain);
static bool handleReceiveCallback(int receiveFd, int events, void* data); static bool handleReceiveCallback(int receiveFd, int events, void* data);
// Preempting input dispatch.
bool preemptInputDispatchInnerLocked();
// Dump state.
void dumpDispatchStateLocked(String8& dump);
void logDispatchStateLocked();
// Add or remove a connection to the mActiveConnections vector. // Add or remove a connection to the mActiveConnections vector.
void activateConnectionLocked(Connection* connection); void activateConnectionLocked(Connection* connection);
void deactivateConnectionLocked(Connection* connection); void deactivateConnectionLocked(Connection* connection);
@@ -683,9 +1034,13 @@ private:
nsecs_t currentTime, const sp<Connection>& connection); nsecs_t currentTime, const sp<Connection>& connection);
// Outbound policy interactions. // Outbound policy interactions.
void doNotifyConfigurationChangedInterruptible(CommandEntry* commandEntry);
void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry); void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry);
void doNotifyInputChannelANRLockedInterruptible(CommandEntry* commandEntry); void doNotifyInputChannelANRLockedInterruptible(CommandEntry* commandEntry);
void doNotifyInputChannelRecoveredFromANRLockedInterruptible(CommandEntry* commandEntry); void doNotifyInputChannelRecoveredFromANRLockedInterruptible(CommandEntry* commandEntry);
void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry);
void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry);
void doTargetsNotReadyTimeoutLockedInterruptible(CommandEntry* commandEntry);
}; };
/* Enqueues and dispatches input events, endlessly. */ /* Enqueues and dispatches input events, endlessly. */
@@ -702,4 +1057,4 @@ private:
} // namespace android } // namespace android
#endif // _UI_INPUT_DISPATCHER_PRIV_H #endif // _UI_INPUT_DISPATCHER_H

View File

@@ -72,51 +72,11 @@ public:
/* Stops the input manager threads and waits for them to exit. */ /* Stops the input manager threads and waits for them to exit. */
virtual status_t stop() = 0; virtual status_t stop() = 0;
/* Registers an input channel prior to using it as the target of an event. */ /* Gets the input reader. */
virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel) = 0; virtual sp<InputReaderInterface> getReader() = 0;
/* Unregisters an input channel. */ /* Gets the input dispatcher. */
virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0; virtual sp<InputDispatcherInterface> getDispatcher() = 0;
/* Injects an input event and optionally waits for sync.
* The synchronization mode determines whether the method blocks while waiting for
* input injection to proceed.
* Returns one of the INPUT_EVENT_INJECTION_XXX constants.
*/
virtual int32_t injectInputEvent(const InputEvent* event,
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) = 0;
/* Preempts input dispatch in progress by making pending synchronous
* dispatches asynchronous instead. This method is generally called during a focus
* transition from one application to the next so as to enable the new application
* to start receiving input as soon as possible without having to wait for the
* old application to finish up.
*/
virtual void preemptInputDispatch() = 0;
/* Gets input device configuration. */
virtual void getInputConfiguration(InputConfiguration* outConfiguration) = 0;
/* Gets information about the specified input device.
* Returns OK if the device information was obtained or NAME_NOT_FOUND if there
* was no such device.
*/
virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) = 0;
/* Gets the list of all registered device ids. */
virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds) = 0;
/* Queries current input state. */
virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
int32_t scanCode) = 0;
virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
int32_t keyCode) = 0;
virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
int32_t sw) = 0;
/* Determines whether physical keys exist for the given framework-domain key codes. */
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
}; };
class InputManager : public InputManagerInterface { class InputManager : public InputManagerInterface {
@@ -137,25 +97,8 @@ public:
virtual status_t start(); virtual status_t start();
virtual status_t stop(); virtual status_t stop();
virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel); virtual sp<InputReaderInterface> getReader();
virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel); virtual sp<InputDispatcherInterface> getDispatcher();
virtual int32_t injectInputEvent(const InputEvent* event,
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis);
virtual void preemptInputDispatch();
virtual void getInputConfiguration(InputConfiguration* outConfiguration);
virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo);
virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds);
virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
int32_t scanCode);
virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
int32_t keyCode);
virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
int32_t sw);
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
private: private:
sp<InputReaderInterface> mReader; sp<InputReaderInterface> mReader;

View File

@@ -95,10 +95,6 @@ public:
// The input dispatcher should dispatch the input to the application. // The input dispatcher should dispatch the input to the application.
ACTION_DISPATCH = 0x00000001, ACTION_DISPATCH = 0x00000001,
// The input dispatcher should perform special filtering in preparation for
// a pending app switch.
ACTION_APP_SWITCH_COMING = 0x00000002,
}; };
/* Gets information about the display with the specified id. /* Gets information about the display with the specified id.
@@ -168,6 +164,11 @@ protected:
virtual ~InputReaderInterface() { } virtual ~InputReaderInterface() { }
public: public:
/* Dumps the state of the input reader.
*
* This method may be called on any thread (usually by the input manager). */
virtual void dump(String8& dump) = 0;
/* Runs a single iteration of the processing loop. /* Runs a single iteration of the processing loop.
* Nominally reads and processes one incoming message from the EventHub. * Nominally reads and processes one incoming message from the EventHub.
* *
@@ -240,6 +241,8 @@ public:
const sp<InputDispatcherInterface>& dispatcher); const sp<InputDispatcherInterface>& dispatcher);
virtual ~InputReader(); virtual ~InputReader();
virtual void dump(String8& dump);
virtual void loopOnce(); virtual void loopOnce();
virtual void getInputConfiguration(InputConfiguration* outConfiguration); virtual void getInputConfiguration(InputConfiguration* outConfiguration);
@@ -305,6 +308,9 @@ private:
GetStateFunc getStateFunc); GetStateFunc getStateFunc);
bool markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes, bool markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
const int32_t* keyCodes, uint8_t* outFlags); const int32_t* keyCodes, uint8_t* outFlags);
// dump state
void dumpDeviceInfo(String8& dump);
}; };
@@ -759,9 +765,11 @@ protected:
} mLocked; } mLocked;
virtual void configureParameters(); virtual void configureParameters();
virtual void logParameters();
virtual void configureRawAxes(); virtual void configureRawAxes();
virtual void logRawAxes(); virtual void logRawAxes();
virtual bool configureSurfaceLocked(); virtual bool configureSurfaceLocked();
virtual void logMotionRangesLocked();
virtual void configureVirtualKeysLocked(); virtual void configureVirtualKeysLocked();
virtual void parseCalibration(); virtual void parseCalibration();
virtual void resolveCalibration(); virtual void resolveCalibration();

37
include/ui/PowerManager.h Normal file
View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _UI_POWER_MANAGER_H
#define _UI_POWER_MANAGER_H
namespace android {
enum {
POWER_MANAGER_OTHER_EVENT = 0,
POWER_MANAGER_CHEEK_EVENT = 1,
POWER_MANAGER_TOUCH_EVENT = 2, // touch events are TOUCH for 300ms, and then either
// up events or LONG_TOUCH events.
POWER_MANAGER_LONG_TOUCH_EVENT = 3,
POWER_MANAGER_TOUCH_UP_EVENT = 4,
POWER_MANAGER_BUTTON_EVENT = 5, // Button and trackball events.
POWER_MANAGER_LAST_EVENT = POWER_MANAGER_BUTTON_EVENT, // Last valid event code.
};
} // namespace android
#endif // _UI_POWER_MANAGER_H

View File

@@ -172,22 +172,36 @@ private:
void* data; void* data;
}; };
const bool mAllowNonCallbacks; const bool mAllowNonCallbacks; // immutable
int mWakeReadPipeFd; // immutable
int mWakeWritePipeFd; // immutable
// The lock guards state used to track whether there is a poll() in progress and whether
// there are any other threads waiting in wakeAndLock(). The condition variables
// are used to transfer control among these threads such that all waiters are
// serviced before a new poll can begin.
// The wakeAndLock() method increments mWaiters, wakes the poll, blocks on mAwake
// until mPolling becomes false, then decrements mWaiters again.
// The poll() method blocks on mResume until mWaiters becomes 0, then sets
// mPolling to true, blocks until the poll completes, then resets mPolling to false
// and signals mResume if there are waiters.
Mutex mLock; Mutex mLock;
bool mPolling; bool mPolling; // guarded by mLock
uint32_t mWaiters; uint32_t mWaiters; // guarded by mLock
Condition mAwake; Condition mAwake; // guarded by mLock
Condition mResume; Condition mResume; // guarded by mLock
int mWakeReadPipeFd;
int mWakeWritePipeFd;
// The next two vectors are only mutated when mPolling is false since they must
// not be changed while the poll() system call is in progress. To mutate these
// vectors, the poll() must first be awoken then the lock acquired.
Vector<struct pollfd> mRequestedFds; Vector<struct pollfd> mRequestedFds;
Vector<RequestedCallback> mRequestedCallbacks; Vector<RequestedCallback> mRequestedCallbacks;
Vector<PendingCallback> mPendingCallbacks; // used privately by pollOnce // This state is only used privately by pollOnce and does not require a lock since
Vector<PendingCallback> mPendingFds; // used privately by pollOnce // it runs on a single thread.
Vector<PendingCallback> mPendingCallbacks;
Vector<PendingCallback> mPendingFds;
size_t mPendingFdsPos; size_t mPendingFdsPos;
void openWakePipe(); void openWakePipe();

File diff suppressed because it is too large Load Diff

View File

@@ -72,52 +72,12 @@ status_t InputManager::stop() {
return OK; return OK;
} }
status_t InputManager::registerInputChannel(const sp<InputChannel>& inputChannel) { sp<InputReaderInterface> InputManager::getReader() {
return mDispatcher->registerInputChannel(inputChannel); return mReader;
} }
status_t InputManager::unregisterInputChannel(const sp<InputChannel>& inputChannel) { sp<InputDispatcherInterface> InputManager::getDispatcher() {
return mDispatcher->unregisterInputChannel(inputChannel); return mDispatcher;
}
int32_t InputManager::injectInputEvent(const InputEvent* event,
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
return mDispatcher->injectInputEvent(event, injectorPid, injectorUid, syncMode, timeoutMillis);
}
void InputManager::preemptInputDispatch() {
mDispatcher->preemptInputDispatch();
}
void InputManager::getInputConfiguration(InputConfiguration* outConfiguration) {
mReader->getInputConfiguration(outConfiguration);
}
status_t InputManager::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
return mReader->getInputDeviceInfo(deviceId, outDeviceInfo);
}
void InputManager::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
mReader->getInputDeviceIds(outDeviceIds);
}
int32_t InputManager::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
int32_t scanCode) {
return mReader->getScanCodeState(deviceId, sourceMask, scanCode);
}
int32_t InputManager::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
int32_t keyCode) {
return mReader->getKeyCodeState(deviceId, sourceMask, keyCode);
}
int32_t InputManager::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t sw) {
return mReader->getSwitchState(deviceId, sourceMask, sw);
}
bool InputManager::hasKeys(int32_t deviceId, uint32_t sourceMask,
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
return mReader->hasKeys(deviceId, sourceMask, numCodes, keyCodes, outFlags);
} }
} // namespace android } // namespace android

View File

@@ -573,6 +573,60 @@ bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, s
} // release device registy reader lock } // release device registy reader lock
} }
void InputReader::dump(String8& dump) {
dumpDeviceInfo(dump);
}
static void dumpMotionRange(String8& dump,
const char* name, const InputDeviceInfo::MotionRange* range) {
if (range) {
dump.appendFormat(" %s = { min: %0.3f, max: %0.3f, flat: %0.3f, fuzz: %0.3f }\n",
name, range->min, range->max, range->flat, range->fuzz);
}
}
#define DUMP_MOTION_RANGE(range) \
dumpMotionRange(dump, #range, deviceInfo.getMotionRange(AINPUT_MOTION_RANGE_##range));
void InputReader::dumpDeviceInfo(String8& dump) {
Vector<int32_t> deviceIds;
getInputDeviceIds(deviceIds);
InputDeviceInfo deviceInfo;
for (size_t i = 0; i < deviceIds.size(); i++) {
int32_t deviceId = deviceIds[i];
status_t result = getInputDeviceInfo(deviceId, & deviceInfo);
if (result == NAME_NOT_FOUND) {
continue;
} else if (result != OK) {
dump.appendFormat(" ** Unexpected error %d getting information about input devices.\n",
result);
continue;
}
dump.appendFormat(" Device %d: '%s'\n",
deviceInfo.getId(), deviceInfo.getName().string());
dump.appendFormat(" sources = 0x%08x\n",
deviceInfo.getSources());
dump.appendFormat(" keyboardType = %d\n",
deviceInfo.getKeyboardType());
dump.append(" motion ranges:\n");
DUMP_MOTION_RANGE(X);
DUMP_MOTION_RANGE(Y);
DUMP_MOTION_RANGE(PRESSURE);
DUMP_MOTION_RANGE(SIZE);
DUMP_MOTION_RANGE(TOUCH_MAJOR);
DUMP_MOTION_RANGE(TOUCH_MINOR);
DUMP_MOTION_RANGE(TOOL_MAJOR);
DUMP_MOTION_RANGE(TOOL_MINOR);
DUMP_MOTION_RANGE(ORIENTATION);
}
}
#undef DUMP_MOTION_RANGE
// --- InputReaderThread --- // --- InputReaderThread ---
@@ -740,10 +794,6 @@ int32_t InputMapper::getMetaState() {
} }
bool InputMapper::applyStandardPolicyActions(nsecs_t when, int32_t policyActions) { bool InputMapper::applyStandardPolicyActions(nsecs_t when, int32_t policyActions) {
if (policyActions & InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING) {
getDispatcher()->notifyAppSwitchComing(when);
}
return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH; return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
} }
@@ -1249,20 +1299,12 @@ void TouchInputMapper::initializeLocked() {
mLocked.orientedRanges.haveOrientation = false; mLocked.orientedRanges.haveOrientation = false;
} }
static void logAxisInfo(RawAbsoluteAxisInfo axis, const char* name) {
if (axis.valid) {
LOGI(INDENT "Raw %s axis: min=%d, max=%d, flat=%d, fuzz=%d",
name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
} else {
LOGI(INDENT "Raw %s axis: unknown range", name);
}
}
void TouchInputMapper::configure() { void TouchInputMapper::configure() {
InputMapper::configure(); InputMapper::configure();
// Configure basic parameters. // Configure basic parameters.
configureParameters(); configureParameters();
logParameters();
// Configure absolute axis information. // Configure absolute axis information.
configureRawAxes(); configureRawAxes();
@@ -1287,6 +1329,18 @@ void TouchInputMapper::configureParameters() {
mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents(); mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
} }
void TouchInputMapper::logParameters() {
if (mParameters.useBadTouchFilter) {
LOGI(INDENT "Bad touch filter enabled.");
}
if (mParameters.useAveragingTouchFilter) {
LOGI(INDENT "Averaging touch filter enabled.");
}
if (mParameters.useJumpyTouchFilter) {
LOGI(INDENT "Jumpy touch filter enabled.");
}
}
void TouchInputMapper::configureRawAxes() { void TouchInputMapper::configureRawAxes() {
mRawAxes.x.clear(); mRawAxes.x.clear();
mRawAxes.y.clear(); mRawAxes.y.clear();
@@ -1298,6 +1352,15 @@ void TouchInputMapper::configureRawAxes() {
mRawAxes.orientation.clear(); mRawAxes.orientation.clear();
} }
static void logAxisInfo(RawAbsoluteAxisInfo axis, const char* name) {
if (axis.valid) {
LOGI(INDENT "Raw %s axis: min=%d, max=%d, flat=%d, fuzz=%d",
name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
} else {
LOGI(INDENT "Raw %s axis: unknown range", name);
}
}
void TouchInputMapper::logRawAxes() { void TouchInputMapper::logRawAxes() {
logAxisInfo(mRawAxes.x, "x"); logAxisInfo(mRawAxes.x, "x");
logAxisInfo(mRawAxes.y, "y"); logAxisInfo(mRawAxes.y, "y");
@@ -1331,8 +1394,10 @@ bool TouchInputMapper::configureSurfaceLocked() {
bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height; bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
if (sizeChanged) { if (sizeChanged) {
LOGI("Device configured: id=0x%x, name=%s (display size was changed)", LOGI("Device reconfigured (display size changed): id=0x%x, name=%s",
getDeviceId(), getDeviceName().string()); getDeviceId(), getDeviceName().string());
LOGI(INDENT "Width: %dpx", width);
LOGI(INDENT "Height: %dpx", height);
mLocked.surfaceWidth = width; mLocked.surfaceWidth = width;
mLocked.surfaceHeight = height; mLocked.surfaceHeight = height;
@@ -1500,9 +1565,41 @@ bool TouchInputMapper::configureSurfaceLocked() {
mLocked.orientedRanges.y.fuzz = orientedYScale; mLocked.orientedRanges.y.fuzz = orientedYScale;
} }
if (sizeChanged) {
logMotionRangesLocked();
}
return true; return true;
} }
static void logMotionRangeInfo(InputDeviceInfo::MotionRange* range, const char* name) {
if (range) {
LOGI(INDENT "Output %s range: min=%f, max=%f, flat=%f, fuzz=%f",
name, range->min, range->max, range->flat, range->fuzz);
} else {
LOGI(INDENT "Output %s range: unsupported", name);
}
}
void TouchInputMapper::logMotionRangesLocked() {
logMotionRangeInfo(& mLocked.orientedRanges.x, "x");
logMotionRangeInfo(& mLocked.orientedRanges.y, "y");
logMotionRangeInfo(mLocked.orientedRanges.havePressure
? & mLocked.orientedRanges.pressure : NULL, "pressure");
logMotionRangeInfo(mLocked.orientedRanges.haveSize
? & mLocked.orientedRanges.size : NULL, "size");
logMotionRangeInfo(mLocked.orientedRanges.haveTouchArea
? & mLocked.orientedRanges.touchMajor : NULL, "touchMajor");
logMotionRangeInfo(mLocked.orientedRanges.haveTouchArea
? & mLocked.orientedRanges.touchMinor : NULL, "touchMinor");
logMotionRangeInfo(mLocked.orientedRanges.haveToolArea
? & mLocked.orientedRanges.toolMajor : NULL, "toolMajor");
logMotionRangeInfo(mLocked.orientedRanges.haveToolArea
? & mLocked.orientedRanges.toolMinor : NULL, "toolMinor");
logMotionRangeInfo(mLocked.orientedRanges.haveOrientation
? & mLocked.orientedRanges.orientation : NULL, "orientation");
}
void TouchInputMapper::configureVirtualKeysLocked() { void TouchInputMapper::configureVirtualKeysLocked() {
assert(mRawAxes.x.valid && mRawAxes.y.valid); assert(mRawAxes.x.valid && mRawAxes.y.valid);
@@ -1768,16 +1865,18 @@ void TouchInputMapper::resolveCalibration() {
} }
void TouchInputMapper::logCalibration() { void TouchInputMapper::logCalibration() {
LOGI(INDENT "Calibration:");
// Touch Area // Touch Area
switch (mCalibration.touchAreaCalibration) { switch (mCalibration.touchAreaCalibration) {
case Calibration::TOUCH_AREA_CALIBRATION_NONE: case Calibration::TOUCH_AREA_CALIBRATION_NONE:
LOGI(INDENT " touch.touchArea.calibration: none"); LOGI(INDENT INDENT "touch.touchArea.calibration: none");
break; break;
case Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC: case Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC:
LOGI(INDENT " touch.touchArea.calibration: geometric"); LOGI(INDENT INDENT "touch.touchArea.calibration: geometric");
break; break;
case Calibration::TOUCH_AREA_CALIBRATION_PRESSURE: case Calibration::TOUCH_AREA_CALIBRATION_PRESSURE:
LOGI(INDENT " touch.touchArea.calibration: pressure"); LOGI(INDENT INDENT "touch.touchArea.calibration: pressure");
break; break;
default: default:
assert(false); assert(false);
@@ -1786,40 +1885,40 @@ void TouchInputMapper::logCalibration() {
// Tool Area // Tool Area
switch (mCalibration.toolAreaCalibration) { switch (mCalibration.toolAreaCalibration) {
case Calibration::TOOL_AREA_CALIBRATION_NONE: case Calibration::TOOL_AREA_CALIBRATION_NONE:
LOGI(INDENT " touch.toolArea.calibration: none"); LOGI(INDENT INDENT "touch.toolArea.calibration: none");
break; break;
case Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC: case Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC:
LOGI(INDENT " touch.toolArea.calibration: geometric"); LOGI(INDENT INDENT "touch.toolArea.calibration: geometric");
break; break;
case Calibration::TOOL_AREA_CALIBRATION_LINEAR: case Calibration::TOOL_AREA_CALIBRATION_LINEAR:
LOGI(INDENT " touch.toolArea.calibration: linear"); LOGI(INDENT INDENT "touch.toolArea.calibration: linear");
break; break;
default: default:
assert(false); assert(false);
} }
if (mCalibration.haveToolAreaLinearScale) { if (mCalibration.haveToolAreaLinearScale) {
LOGI(INDENT " touch.toolArea.linearScale: %f", mCalibration.toolAreaLinearScale); LOGI(INDENT INDENT "touch.toolArea.linearScale: %f", mCalibration.toolAreaLinearScale);
} }
if (mCalibration.haveToolAreaLinearBias) { if (mCalibration.haveToolAreaLinearBias) {
LOGI(INDENT " touch.toolArea.linearBias: %f", mCalibration.toolAreaLinearBias); LOGI(INDENT INDENT "touch.toolArea.linearBias: %f", mCalibration.toolAreaLinearBias);
} }
if (mCalibration.haveToolAreaIsSummed) { if (mCalibration.haveToolAreaIsSummed) {
LOGI(INDENT " touch.toolArea.isSummed: %d", mCalibration.toolAreaIsSummed); LOGI(INDENT INDENT "touch.toolArea.isSummed: %d", mCalibration.toolAreaIsSummed);
} }
// Pressure // Pressure
switch (mCalibration.pressureCalibration) { switch (mCalibration.pressureCalibration) {
case Calibration::PRESSURE_CALIBRATION_NONE: case Calibration::PRESSURE_CALIBRATION_NONE:
LOGI(INDENT " touch.pressure.calibration: none"); LOGI(INDENT INDENT "touch.pressure.calibration: none");
break; break;
case Calibration::PRESSURE_CALIBRATION_PHYSICAL: case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
LOGI(INDENT " touch.pressure.calibration: physical"); LOGI(INDENT INDENT "touch.pressure.calibration: physical");
break; break;
case Calibration::PRESSURE_CALIBRATION_AMPLITUDE: case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
LOGI(INDENT " touch.pressure.calibration: amplitude"); LOGI(INDENT INDENT "touch.pressure.calibration: amplitude");
break; break;
default: default:
assert(false); assert(false);
@@ -1827,10 +1926,10 @@ void TouchInputMapper::logCalibration() {
switch (mCalibration.pressureSource) { switch (mCalibration.pressureSource) {
case Calibration::PRESSURE_SOURCE_PRESSURE: case Calibration::PRESSURE_SOURCE_PRESSURE:
LOGI(INDENT " touch.pressure.source: pressure"); LOGI(INDENT INDENT "touch.pressure.source: pressure");
break; break;
case Calibration::PRESSURE_SOURCE_TOUCH: case Calibration::PRESSURE_SOURCE_TOUCH:
LOGI(INDENT " touch.pressure.source: touch"); LOGI(INDENT INDENT "touch.pressure.source: touch");
break; break;
case Calibration::PRESSURE_SOURCE_DEFAULT: case Calibration::PRESSURE_SOURCE_DEFAULT:
break; break;
@@ -1839,16 +1938,16 @@ void TouchInputMapper::logCalibration() {
} }
if (mCalibration.havePressureScale) { if (mCalibration.havePressureScale) {
LOGI(INDENT " touch.pressure.scale: %f", mCalibration.pressureScale); LOGI(INDENT INDENT "touch.pressure.scale: %f", mCalibration.pressureScale);
} }
// Size // Size
switch (mCalibration.sizeCalibration) { switch (mCalibration.sizeCalibration) {
case Calibration::SIZE_CALIBRATION_NONE: case Calibration::SIZE_CALIBRATION_NONE:
LOGI(INDENT " touch.size.calibration: none"); LOGI(INDENT INDENT "touch.size.calibration: none");
break; break;
case Calibration::SIZE_CALIBRATION_NORMALIZED: case Calibration::SIZE_CALIBRATION_NORMALIZED:
LOGI(INDENT " touch.size.calibration: normalized"); LOGI(INDENT INDENT "touch.size.calibration: normalized");
break; break;
default: default:
assert(false); assert(false);
@@ -1857,10 +1956,10 @@ void TouchInputMapper::logCalibration() {
// Orientation // Orientation
switch (mCalibration.orientationCalibration) { switch (mCalibration.orientationCalibration) {
case Calibration::ORIENTATION_CALIBRATION_NONE: case Calibration::ORIENTATION_CALIBRATION_NONE:
LOGI(INDENT " touch.orientation.calibration: none"); LOGI(INDENT INDENT "touch.orientation.calibration: none");
break; break;
case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED: case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
LOGI(INDENT " touch.orientation.calibration: interpolated"); LOGI(INDENT INDENT "touch.orientation.calibration: interpolated");
break; break;
default: default:
assert(false); assert(false);

View File

@@ -119,7 +119,8 @@ int32_t PollLoop::pollOnce(int timeoutMillis, int* outEvents, void** outData) {
if (outData != NULL) *outData = pending.data; if (outData != NULL) *outData = pending.data;
return pending.ident; return pending.ident;
} }
// Wait for wakeAndLock() waiters to run then set mPolling to true.
mLock.lock(); mLock.lock();
while (mWaiters != 0) { while (mWaiters != 0) {
mResume.wait(mLock); mResume.wait(mLock);
@@ -127,6 +128,7 @@ int32_t PollLoop::pollOnce(int timeoutMillis, int* outEvents, void** outData) {
mPolling = true; mPolling = true;
mLock.unlock(); mLock.unlock();
// Poll.
int32_t result; int32_t result;
size_t requestedCount = mRequestedFds.size(); size_t requestedCount = mRequestedFds.size();
@@ -168,6 +170,7 @@ int32_t PollLoop::pollOnce(int timeoutMillis, int* outEvents, void** outData) {
} }
#endif #endif
// Process the poll results.
mPendingCallbacks.clear(); mPendingCallbacks.clear();
mPendingFds.clear(); mPendingFds.clear();
mPendingFdsPos = 0; mPendingFdsPos = 0;
@@ -218,6 +221,7 @@ int32_t PollLoop::pollOnce(int timeoutMillis, int* outEvents, void** outData) {
} }
Done: Done:
// Set mPolling to false and wake up the wakeAndLock() waiters.
mLock.lock(); mLock.lock();
mPolling = false; mPolling = false;
if (mWaiters != 0) { if (mWaiters != 0) {
@@ -357,11 +361,13 @@ ssize_t PollLoop::getRequestIndexLocked(int fd) {
void PollLoop::wakeAndLock() { void PollLoop::wakeAndLock() {
mLock.lock(); mLock.lock();
mWaiters += 1; mWaiters += 1;
while (mPolling) { while (mPolling) {
wake(); wake();
mAwake.wait(mLock); mAwake.wait(mLock);
} }
mWaiters -= 1; mWaiters -= 1;
if (mWaiters == 0) { if (mWaiters == 0) {
mResume.signal(); mResume.signal();

View File

@@ -432,11 +432,6 @@ public class InputManager {
== PackageManager.PERMISSION_GRANTED; == PackageManager.PERMISSION_GRANTED;
} }
@SuppressWarnings("unused")
public void notifyAppSwitchComing() {
mWindowManagerService.mInputMonitor.notifyAppSwitchComing();
}
@SuppressWarnings("unused") @SuppressWarnings("unused")
public boolean filterTouchEvents() { public boolean filterTouchEvents() {
return mContext.getResources().getBoolean( return mContext.getResources().getBoolean(

View File

@@ -1751,24 +1751,28 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
p.println(" mSystemReady=" + mSystemReady + " mScreenOn=" + mScreenOn); p.println(" mSystemReady=" + mSystemReady + " mScreenOn=" + mScreenOn);
} }
p.println(" ");
if (client != null) { if (client != null) {
p.println(" ");
pw.flush(); pw.flush();
try { try {
client.client.asBinder().dump(fd, args); client.client.asBinder().dump(fd, args);
} catch (RemoteException e) { } catch (RemoteException e) {
p.println("Input method client dead: " + e); p.println("Input method client dead: " + e);
} }
} else {
p.println("No input method client.");
} }
p.println(" ");
if (method != null) { if (method != null) {
p.println(" ");
pw.flush(); pw.flush();
try { try {
method.asBinder().dump(fd, args); method.asBinder().dump(fd, args);
} catch (RemoteException e) { } catch (RemoteException e) {
p.println("Input method service dead: " + e); p.println("Input method service dead: " + e);
} }
} else {
p.println("No input method service.");
} }
} }
} }

View File

@@ -5097,8 +5097,7 @@ public class WindowManagerService extends IWindowManager.Stub
} }
/* Notifies the window manager about an input channel that is not responding. /* Notifies the window manager about an input channel that is not responding.
* The method can either cause dispatching to be aborted by returning -2 or * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch.
* return a new timeout in nanoseconds.
* *
* Called by the InputManager. * Called by the InputManager.
*/ */
@@ -5107,7 +5106,7 @@ public class WindowManagerService extends IWindowManager.Stub
synchronized (mWindowMap) { synchronized (mWindowMap) {
WindowState windowState = getWindowStateForInputChannelLocked(inputChannel); WindowState windowState = getWindowStateForInputChannelLocked(inputChannel);
if (windowState == null) { if (windowState == null) {
return -2; // irrelevant, abort dispatching (-2) return 0; // window is unknown, abort dispatching
} }
Slog.i(TAG, "Input event dispatching timed out sending to " Slog.i(TAG, "Input event dispatching timed out sending to "
@@ -5130,8 +5129,7 @@ public class WindowManagerService extends IWindowManager.Stub
/* Notifies the window manager about an application that is not responding /* Notifies the window manager about an application that is not responding
* in general rather than with respect to a particular input channel. * in general rather than with respect to a particular input channel.
* The method can either cause dispatching to be aborted by returning -2 or * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch.
* return a new timeout in nanoseconds.
* *
* Called by the InputManager. * Called by the InputManager.
*/ */
@@ -5157,7 +5155,7 @@ public class WindowManagerService extends IWindowManager.Stub
} catch (RemoteException ex) { } catch (RemoteException ex) {
} }
} }
return -2; // abort dispatching return 0; // abort dispatching
} }
private WindowState getWindowStateForInputChannel(InputChannel inputChannel) { private WindowState getWindowStateForInputChannel(InputChannel inputChannel) {
@@ -5271,15 +5269,6 @@ public class WindowManagerService extends IWindowManager.Stub
} }
} }
/* Notifies that an app switch key (BACK / HOME) has just been pressed.
* This essentially starts a .5 second timeout for the application to process
* subsequent input events while waiting for the app switch to occur. If it takes longer
* than this, the pending events will be dropped.
*/
public void notifyAppSwitchComing() {
// TODO Not implemented yet. Should go in the native side.
}
/* Notifies that the lid switch changed state. */ /* Notifies that the lid switch changed state. */
public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen); mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);

File diff suppressed because it is too large Load Diff

View File

@@ -20,20 +20,10 @@
#include "JNIHelp.h" #include "JNIHelp.h"
#include "jni.h" #include "jni.h"
#include <ui/PowerManager.h>
namespace android { namespace android {
enum {
POWER_MANAGER_OTHER_EVENT = 0,
POWER_MANAGER_CHEEK_EVENT = 1,
POWER_MANAGER_TOUCH_EVENT = 2, // touch events are TOUCH for 300ms, and then either
// up events or LONG_TOUCH events.
POWER_MANAGER_LONG_TOUCH_EVENT = 3,
POWER_MANAGER_TOUCH_UP_EVENT = 4,
POWER_MANAGER_BUTTON_EVENT = 5, // Button and trackball events.
POWER_MANAGER_LAST_EVENT = POWER_MANAGER_BUTTON_EVENT, // Last valid event code.
};
extern bool android_server_PowerManagerService_isScreenOn(); extern bool android_server_PowerManagerService_isScreenOn();
extern bool android_server_PowerManagerService_isScreenBright(); extern bool android_server_PowerManagerService_isScreenBright();
extern void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType); extern void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType);