am b88102f5: Input dispatcher ANR handling enhancements.

Merge commit 'b88102f5b7e51552a3576cf197b4c8cf96f193d1' into gingerbread-plus-aosp

* commit 'b88102f5b7e51552a3576cf197b4c8cf96f193d1':
  Input dispatcher ANR handling enhancements.
This commit is contained in:
Jeff Brown
2010-09-12 17:05:38 -07:00
committed by Android Git Automerger
15 changed files with 2589 additions and 1978 deletions

View File

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

View File

@ -30,6 +30,7 @@
#include <stddef.h>
#include <unistd.h>
#include <limits.h>
namespace android {
@ -108,15 +109,134 @@ struct InputTarget {
// Flags for the input target.
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;
// 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.
// (ignored for KeyEvents)
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.
*
@ -135,14 +255,16 @@ public:
/* Notifies the system that a configuration change has occurred. */
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. */
virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) = 0;
/* Notifies the system that an input channel is not responding.
* Returns true and a new timeout value if the dispatcher should keep waiting.
* Otherwise returns false. */
virtual bool notifyInputChannelANR(const sp<InputChannel>& inputChannel,
nsecs_t& outNewTimeout) = 0;
* Returns a new timeout to continue waiting, or 0 to abort dispatch. */
virtual nsecs_t notifyInputChannelANR(const sp<InputChannel>& inputChannel) = 0;
/* Notifies the system that an input channel recovered from ANR. */
virtual void notifyInputChannelRecoveredFromANR(const sp<InputChannel>& inputChannel) = 0;
@ -153,29 +275,27 @@ public:
/* Gets the key repeat inter-key delay. */
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.
* This value is used to throttle motion event movement actions on a per-device
* basis. It is not intended to be a hard limit.
*/
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() { }
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.
* 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.
*/
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,
uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;
@ -219,6 +343,24 @@ public:
virtual int32_t injectInputEvent(const InputEvent* event,
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
* 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
@ -230,10 +372,11 @@ public:
virtual void preemptInputDispatch() = 0;
/* 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).
*/
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;
};
@ -261,10 +404,11 @@ protected:
public:
explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy);
virtual void dump(String8& dump);
virtual void dispatchOnce();
virtual void notifyConfigurationChanged(nsecs_t eventTime);
virtual void notifyAppSwitchComing(nsecs_t eventTime);
virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
int32_t scanCode, int32_t metaState, nsecs_t downTime);
@ -277,9 +421,12 @@ public:
virtual int32_t injectInputEvent(const InputEvent* event,
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 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);
private:
@ -310,6 +457,8 @@ private:
int32_t pendingSyncDispatches; // the number of synchronous dispatches in progress
inline bool isInjected() { return injectorPid >= 0; }
void recycle();
};
struct ConfigurationChangedEntry : EventEntry {
@ -326,6 +475,17 @@ private:
int32_t metaState;
int32_t repeatCount;
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 {
@ -380,9 +540,13 @@ private:
// will be set to NULL.
MotionSample* tailMotionSample;
inline bool isSyncTarget() {
inline bool isSyncTarget() const {
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
@ -413,37 +577,43 @@ private:
// parameters for the command (usage varies by command)
sp<Connection> connection;
nsecs_t eventTime;
KeyEntry* keyEntry;
sp<InputChannel> inputChannel;
sp<InputApplicationHandle> inputApplicationHandle;
int32_t windowType;
int32_t userActivityEventType;
};
// Generic queue implementation.
template <typename T>
struct Queue {
T head;
T tail;
T headSentinel;
T tailSentinel;
inline Queue() {
head.prev = NULL;
head.next = & tail;
tail.prev = & head;
tail.next = NULL;
headSentinel.prev = NULL;
headSentinel.next = & tailSentinel;
tailSentinel.prev = & headSentinel;
tailSentinel.next = NULL;
}
inline bool isEmpty() {
return head.next == & tail;
inline bool isEmpty() const {
return headSentinel.next == & tailSentinel;
}
inline void enqueueAtTail(T* entry) {
T* last = tail.prev;
T* last = tailSentinel.prev;
last->next = entry;
entry->prev = last;
entry->next = & tail;
tail.prev = entry;
entry->next = & tailSentinel;
tailSentinel.prev = entry;
}
inline void enqueueAtHead(T* entry) {
T* first = head.next;
head.next = entry;
entry->prev = & head;
T* first = headSentinel.next;
headSentinel.next = entry;
entry->prev = & headSentinel;
entry->next = first;
first->prev = entry;
}
@ -454,7 +624,7 @@ private:
}
inline T* dequeueAtHead() {
T* first = head.next;
T* first = headSentinel.next;
dequeue(first);
return first;
}
@ -476,7 +646,8 @@ private:
float xPrecision, float yPrecision,
nsecs_t downTime, uint32_t pointerCount,
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);
void releaseEventEntry(EventEntry* entry);
@ -500,6 +671,85 @@ private:
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. */
class Connection : public RefBase {
protected:
@ -520,6 +770,7 @@ private:
Status status;
sp<InputChannel> inputChannel;
InputPublisher inputPublisher;
InputState inputState;
Queue<DispatchEntry> outboundQueue;
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.
// 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.
inline bool hasPendingSyncTarget() {
return ! outboundQueue.isEmpty() && outboundQueue.tail.prev->isSyncTarget();
inline bool hasPendingSyncTarget() const {
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.
inline double getEventLatencyMillis(nsecs_t currentTime) {
inline double getEventLatencyMillis(nsecs_t currentTime) const {
return (currentTime - lastEventTime) / 1000000.0;
}
// 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;
}
// 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;
}
status_t initialize();
void setNextTimeoutTime(nsecs_t currentTime, nsecs_t timeout);
void resetTimeout(nsecs_t currentTime);
};
sp<InputDispatcherPolicyInterface> mPolicy;
@ -571,9 +828,26 @@ private:
Allocator mAllocator;
sp<PollLoop> mPollLoop;
EventEntry* mPendingEvent;
Queue<EventEntry> mInboundQueue;
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.
KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd;
@ -591,20 +865,15 @@ private:
// the duration.
Vector<Connection*> mTimedOutConnections;
// Preallocated key and motion event objects used only to ask the input dispatcher policy
// for the targets of an event that is to be dispatched.
KeyEvent mReusableKeyEvent;
MotionEvent mReusableMotionEvent;
// Input channels that will receive a copy of all input events.
Vector<sp<InputChannel> > mMonitoringChannels;
// 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.
Vector<InputTarget> mCurrentInputTargets;
bool mCurrentInputTargetsValid; // false while targets are being recomputed
// Preallocated key event object used for policy inquiries.
KeyEvent mReusableKeyEvent;
// Event injection and synchronization.
Condition mInjectionResultAvailableCondition;
EventEntry* createEntryFromInputEventLocked(const InputEvent* event);
EventEntry* createEntryFromInjectedInputEventLocked(const InputEvent* event);
void setInjectionResultLocked(EventEntry* entry, int32_t injectionResult);
Condition mInjectionSyncFinishedCondition;
@ -622,36 +891,108 @@ private:
} mThrottleState;
// Key repeat tracking.
// XXX Move this up to the input reader instead.
struct KeyRepeatState {
KeyEntry* lastKeyEntry; // or null if no repeat
nsecs_t nextRepeatTime;
} mKeyRepeatState;
void resetKeyRepeatLocked();
KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime, nsecs_t keyRepeatTimeout);
// Deferred command processing.
bool runCommandsLockedInterruptible();
CommandEntry* postCommandLocked(Command command);
// Process events that have just been dequeued from the head of the input queue.
void processConfigurationChangedLockedInterruptible(
nsecs_t currentTime, ConfigurationChangedEntry* entry);
void processKeyLockedInterruptible(
nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout);
void processKeyRepeatLockedInterruptible(
nsecs_t currentTime, nsecs_t keyRepeatTimeout);
void processMotionLockedInterruptible(
nsecs_t currentTime, MotionEntry* entry);
// Inbound event processing.
void drainInboundQueueLocked();
void releasePendingEventLocked(bool wasDropped);
void releaseInboundEventLocked(EventEntry* entry, bool wasDropped);
bool isEventFromReliableSourceLocked(EventEntry* entry);
// Identify input targets for an event and dispatch to them.
void identifyInputTargetsAndDispatchKeyLockedInterruptible(
nsecs_t currentTime, KeyEntry* entry);
void identifyInputTargetsAndDispatchMotionLockedInterruptible(
nsecs_t currentTime, MotionEntry* entry);
// Dispatch state.
bool mDispatchEnabled;
bool mDispatchFrozen;
Vector<InputWindow> mWindows;
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(
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.
// 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.
@ -659,15 +1000,25 @@ private:
void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
EventEntry* eventEntry, const InputTarget* inputTarget,
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 startNextDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
void timeoutDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
void resumeAfterTimeoutDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection, nsecs_t newTimeout);
void abortDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
bool broken);
void drainOutboundQueueLocked(Connection* connection, DispatchEntry* firstDispatchEntryToDrain);
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.
void activateConnectionLocked(Connection* connection);
void deactivateConnectionLocked(Connection* connection);
@ -683,9 +1034,13 @@ private:
nsecs_t currentTime, const sp<Connection>& connection);
// Outbound policy interactions.
void doNotifyConfigurationChangedInterruptible(CommandEntry* commandEntry);
void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry);
void doNotifyInputChannelANRLockedInterruptible(CommandEntry* commandEntry);
void doNotifyInputChannelRecoveredFromANRLockedInterruptible(CommandEntry* commandEntry);
void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry);
void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry);
void doTargetsNotReadyTimeoutLockedInterruptible(CommandEntry* commandEntry);
};
/* Enqueues and dispatches input events, endlessly. */
@ -702,4 +1057,4 @@ private:
} // 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. */
virtual status_t stop() = 0;
/* Registers an input channel prior to using it as the target of an event. */
virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel) = 0;
/* Gets the input reader. */
virtual sp<InputReaderInterface> getReader() = 0;
/* Unregisters an input channel. */
virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 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;
/* Gets the input dispatcher. */
virtual sp<InputDispatcherInterface> getDispatcher() = 0;
};
class InputManager : public InputManagerInterface {
@ -137,25 +97,8 @@ public:
virtual status_t start();
virtual status_t stop();
virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel);
virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
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);
virtual sp<InputReaderInterface> getReader();
virtual sp<InputDispatcherInterface> getDispatcher();
private:
sp<InputReaderInterface> mReader;

View File

@ -95,10 +95,6 @@ public:
// 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,
};
/* Gets information about the display with the specified id.
@ -168,6 +164,11 @@ protected:
virtual ~InputReaderInterface() { }
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.
* Nominally reads and processes one incoming message from the EventHub.
*
@ -240,6 +241,8 @@ public:
const sp<InputDispatcherInterface>& dispatcher);
virtual ~InputReader();
virtual void dump(String8& dump);
virtual void loopOnce();
virtual void getInputConfiguration(InputConfiguration* outConfiguration);
@ -305,6 +308,9 @@ private:
GetStateFunc getStateFunc);
bool markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
const int32_t* keyCodes, uint8_t* outFlags);
// dump state
void dumpDeviceInfo(String8& dump);
};
@ -759,9 +765,11 @@ protected:
} mLocked;
virtual void configureParameters();
virtual void logParameters();
virtual void configureRawAxes();
virtual void logRawAxes();
virtual bool configureSurfaceLocked();
virtual void logMotionRangesLocked();
virtual void configureVirtualKeysLocked();
virtual void parseCalibration();
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;
};
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;
bool mPolling;
uint32_t mWaiters;
Condition mAwake;
Condition mResume;
int mWakeReadPipeFd;
int mWakeWritePipeFd;
bool mPolling; // guarded by mLock
uint32_t mWaiters; // guarded by mLock
Condition mAwake; // guarded by mLock
Condition mResume; // guarded by mLock
// 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<RequestedCallback> mRequestedCallbacks;
Vector<PendingCallback> mPendingCallbacks; // used privately by pollOnce
Vector<PendingCallback> mPendingFds; // used privately by pollOnce
// This state is only used privately by pollOnce and does not require a lock since
// it runs on a single thread.
Vector<PendingCallback> mPendingCallbacks;
Vector<PendingCallback> mPendingFds;
size_t mPendingFdsPos;
void openWakePipe();

File diff suppressed because it is too large Load Diff

View File

@ -72,52 +72,12 @@ status_t InputManager::stop() {
return OK;
}
status_t InputManager::registerInputChannel(const sp<InputChannel>& inputChannel) {
return mDispatcher->registerInputChannel(inputChannel);
sp<InputReaderInterface> InputManager::getReader() {
return mReader;
}
status_t InputManager::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
return mDispatcher->unregisterInputChannel(inputChannel);
}
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);
sp<InputDispatcherInterface> InputManager::getDispatcher() {
return mDispatcher;
}
} // namespace android

View File

@ -573,6 +573,60 @@ bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, s
} // 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 ---
@ -740,10 +794,6 @@ int32_t InputMapper::getMetaState() {
}
bool InputMapper::applyStandardPolicyActions(nsecs_t when, int32_t policyActions) {
if (policyActions & InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING) {
getDispatcher()->notifyAppSwitchComing(when);
}
return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
}
@ -1249,20 +1299,12 @@ void TouchInputMapper::initializeLocked() {
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() {
InputMapper::configure();
// Configure basic parameters.
configureParameters();
logParameters();
// Configure absolute axis information.
configureRawAxes();
@ -1287,6 +1329,18 @@ void TouchInputMapper::configureParameters() {
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() {
mRawAxes.x.clear();
mRawAxes.y.clear();
@ -1298,6 +1352,15 @@ void TouchInputMapper::configureRawAxes() {
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() {
logAxisInfo(mRawAxes.x, "x");
logAxisInfo(mRawAxes.y, "y");
@ -1331,8 +1394,10 @@ bool TouchInputMapper::configureSurfaceLocked() {
bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
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());
LOGI(INDENT "Width: %dpx", width);
LOGI(INDENT "Height: %dpx", height);
mLocked.surfaceWidth = width;
mLocked.surfaceHeight = height;
@ -1500,9 +1565,41 @@ bool TouchInputMapper::configureSurfaceLocked() {
mLocked.orientedRanges.y.fuzz = orientedYScale;
}
if (sizeChanged) {
logMotionRangesLocked();
}
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() {
assert(mRawAxes.x.valid && mRawAxes.y.valid);
@ -1768,16 +1865,18 @@ void TouchInputMapper::resolveCalibration() {
}
void TouchInputMapper::logCalibration() {
LOGI(INDENT "Calibration:");
// Touch Area
switch (mCalibration.touchAreaCalibration) {
case Calibration::TOUCH_AREA_CALIBRATION_NONE:
LOGI(INDENT " touch.touchArea.calibration: none");
LOGI(INDENT INDENT "touch.touchArea.calibration: none");
break;
case Calibration::TOUCH_AREA_CALIBRATION_GEOMETRIC:
LOGI(INDENT " touch.touchArea.calibration: geometric");
LOGI(INDENT INDENT "touch.touchArea.calibration: geometric");
break;
case Calibration::TOUCH_AREA_CALIBRATION_PRESSURE:
LOGI(INDENT " touch.touchArea.calibration: pressure");
LOGI(INDENT INDENT "touch.touchArea.calibration: pressure");
break;
default:
assert(false);
@ -1786,40 +1885,40 @@ void TouchInputMapper::logCalibration() {
// Tool Area
switch (mCalibration.toolAreaCalibration) {
case Calibration::TOOL_AREA_CALIBRATION_NONE:
LOGI(INDENT " touch.toolArea.calibration: none");
LOGI(INDENT INDENT "touch.toolArea.calibration: none");
break;
case Calibration::TOOL_AREA_CALIBRATION_GEOMETRIC:
LOGI(INDENT " touch.toolArea.calibration: geometric");
LOGI(INDENT INDENT "touch.toolArea.calibration: geometric");
break;
case Calibration::TOOL_AREA_CALIBRATION_LINEAR:
LOGI(INDENT " touch.toolArea.calibration: linear");
LOGI(INDENT INDENT "touch.toolArea.calibration: linear");
break;
default:
assert(false);
}
if (mCalibration.haveToolAreaLinearScale) {
LOGI(INDENT " touch.toolArea.linearScale: %f", mCalibration.toolAreaLinearScale);
LOGI(INDENT INDENT "touch.toolArea.linearScale: %f", mCalibration.toolAreaLinearScale);
}
if (mCalibration.haveToolAreaLinearBias) {
LOGI(INDENT " touch.toolArea.linearBias: %f", mCalibration.toolAreaLinearBias);
LOGI(INDENT INDENT "touch.toolArea.linearBias: %f", mCalibration.toolAreaLinearBias);
}
if (mCalibration.haveToolAreaIsSummed) {
LOGI(INDENT " touch.toolArea.isSummed: %d", mCalibration.toolAreaIsSummed);
LOGI(INDENT INDENT "touch.toolArea.isSummed: %d", mCalibration.toolAreaIsSummed);
}
// Pressure
switch (mCalibration.pressureCalibration) {
case Calibration::PRESSURE_CALIBRATION_NONE:
LOGI(INDENT " touch.pressure.calibration: none");
LOGI(INDENT INDENT "touch.pressure.calibration: none");
break;
case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
LOGI(INDENT " touch.pressure.calibration: physical");
LOGI(INDENT INDENT "touch.pressure.calibration: physical");
break;
case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
LOGI(INDENT " touch.pressure.calibration: amplitude");
LOGI(INDENT INDENT "touch.pressure.calibration: amplitude");
break;
default:
assert(false);
@ -1827,10 +1926,10 @@ void TouchInputMapper::logCalibration() {
switch (mCalibration.pressureSource) {
case Calibration::PRESSURE_SOURCE_PRESSURE:
LOGI(INDENT " touch.pressure.source: pressure");
LOGI(INDENT INDENT "touch.pressure.source: pressure");
break;
case Calibration::PRESSURE_SOURCE_TOUCH:
LOGI(INDENT " touch.pressure.source: touch");
LOGI(INDENT INDENT "touch.pressure.source: touch");
break;
case Calibration::PRESSURE_SOURCE_DEFAULT:
break;
@ -1839,16 +1938,16 @@ void TouchInputMapper::logCalibration() {
}
if (mCalibration.havePressureScale) {
LOGI(INDENT " touch.pressure.scale: %f", mCalibration.pressureScale);
LOGI(INDENT INDENT "touch.pressure.scale: %f", mCalibration.pressureScale);
}
// Size
switch (mCalibration.sizeCalibration) {
case Calibration::SIZE_CALIBRATION_NONE:
LOGI(INDENT " touch.size.calibration: none");
LOGI(INDENT INDENT "touch.size.calibration: none");
break;
case Calibration::SIZE_CALIBRATION_NORMALIZED:
LOGI(INDENT " touch.size.calibration: normalized");
LOGI(INDENT INDENT "touch.size.calibration: normalized");
break;
default:
assert(false);
@ -1857,10 +1956,10 @@ void TouchInputMapper::logCalibration() {
// Orientation
switch (mCalibration.orientationCalibration) {
case Calibration::ORIENTATION_CALIBRATION_NONE:
LOGI(INDENT " touch.orientation.calibration: none");
LOGI(INDENT INDENT "touch.orientation.calibration: none");
break;
case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
LOGI(INDENT " touch.orientation.calibration: interpolated");
LOGI(INDENT INDENT "touch.orientation.calibration: interpolated");
break;
default:
assert(false);

View File

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

View File

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

View File

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

View File

@ -5098,8 +5098,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
/* 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
* return a new timeout in nanoseconds.
* Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch.
*
* Called by the InputManager.
*/
@ -5108,7 +5107,7 @@ public class WindowManagerService extends IWindowManager.Stub
synchronized (mWindowMap) {
WindowState windowState = getWindowStateForInputChannelLocked(inputChannel);
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 "
@ -5131,8 +5130,7 @@ public class WindowManagerService extends IWindowManager.Stub
/* Notifies the window manager about an application that is not responding
* in general rather than with respect to a particular input channel.
* The method can either cause dispatching to be aborted by returning -2 or
* return a new timeout in nanoseconds.
* Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch.
*
* Called by the InputManager.
*/
@ -5158,7 +5156,7 @@ public class WindowManagerService extends IWindowManager.Stub
} catch (RemoteException ex) {
}
}
return -2; // abort dispatching
return 0; // abort dispatching
}
private WindowState getWindowStateForInputChannel(InputChannel inputChannel) {
@ -5272,15 +5270,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. */
public void notifyLidSwitchChanged(long whenNanos, boolean 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 "jni.h"
#include <ui/PowerManager.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.
};
extern bool android_server_PowerManagerService_isScreenOn();
extern bool android_server_PowerManagerService_isScreenBright();
extern void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType);