summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/MotionEvent.java15
-rw-r--r--core/java/android/view/WindowManagerPolicy.java16
-rw-r--r--core/jni/android_view_MotionEvent.cpp9
-rw-r--r--include/ui/Input.h5
-rw-r--r--libs/ui/Input.cpp17
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardViewBase.java3
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardViewManager.java3
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java22
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java19
-rw-r--r--services/input/EventHub.cpp16
-rw-r--r--services/input/EventHub.h5
-rw-r--r--services/input/InputDispatcher.cpp9
-rw-r--r--services/input/InputDispatcher.h4
-rw-r--r--services/input/InputReader.cpp52
-rw-r--r--services/input/InputReader.h4
-rw-r--r--services/input/tests/InputDispatcher_test.cpp2
-rw-r--r--services/input/tests/InputReader_test.cpp6
-rw-r--r--services/java/com/android/server/wm/InputManager.java8
-rw-r--r--services/java/com/android/server/wm/InputMonitor.java9
-rw-r--r--services/jni/com_android_server_InputManager.cpp69
20 files changed, 244 insertions, 49 deletions
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index a26dd04..076f712 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -937,6 +937,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
private static native int nativeSetSource(int nativePtr, int source);
private static native int nativeGetAction(int nativePtr);
private static native void nativeSetAction(int nativePtr, int action);
+ private static native boolean nativeIsTouchEvent(int nativePtr);
private static native int nativeGetFlags(int nativePtr);
private static native int nativeGetEdgeFlags(int nativePtr);
private static native void nativeSetEdgeFlags(int nativePtr, int action);
@@ -1275,19 +1276,7 @@ public final class MotionEvent extends InputEvent implements Parcelable {
* @hide
*/
public final boolean isTouchEvent() {
- if ((getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
- switch (getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- case MotionEvent.ACTION_MOVE:
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_POINTER_DOWN:
- case MotionEvent.ACTION_POINTER_UP:
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_OUTSIDE:
- return true;
- }
- }
- return false;
+ return nativeIsTouchEvent(mNativePtr);
}
/**
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index be68cb9..334c68e 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -573,7 +573,21 @@ public interface WindowManagerPolicy {
* {@link #ACTION_POKE_USER_ACTIVITY} and {@link #ACTION_GO_TO_SLEEP} flags.
*/
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn);
-
+
+ /**
+ * Called from the input reader thread before a motion is enqueued when the screen is off.
+ *
+ * <p>There are some actions that need to be handled here because they
+ * affect the power state of the device, for example, waking on motions.
+ * Generally, it's best to keep as little as possible in the queue thread
+ * because it's the most fragile.
+ * @param policyFlags The policy flags associated with the motion.
+ *
+ * @return The bitwise or of the {@link #ACTION_PASS_TO_USER},
+ * {@link #ACTION_POKE_USER_ACTIVITY} and {@link #ACTION_GO_TO_SLEEP} flags.
+ */
+ public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags);
+
/**
* Called from the input dispatcher thread before a key is dispatched to a window.
*
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index b014006..97cba23 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -429,6 +429,12 @@ static void android_view_MotionEvent_nativeSetAction(JNIEnv* env, jclass clazz,
event->setAction(action);
}
+static jboolean android_view_MotionEvent_nativeIsTouchEvent(JNIEnv* env, jclass clazz,
+ jint nativePtr) {
+ MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
+ return event->isTouchEvent();
+}
+
static jint android_view_MotionEvent_nativeGetFlags(JNIEnv* env, jclass clazz,
jint nativePtr) {
MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
@@ -661,6 +667,9 @@ static JNINativeMethod gMotionEventMethods[] = {
{ "nativeSetAction",
"(II)V",
(void*)android_view_MotionEvent_nativeSetAction },
+ { "nativeIsTouchEvent",
+ "(I)Z",
+ (void*)android_view_MotionEvent_nativeIsTouchEvent },
{ "nativeGetFlags",
"(I)I",
(void*)android_view_MotionEvent_nativeGetFlags },
diff --git a/include/ui/Input.h b/include/ui/Input.h
index 082f11c..e92d7f5 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -476,6 +476,11 @@ public:
status_t writeToParcel(Parcel* parcel) const;
#endif
+ static bool isTouchEvent(int32_t source, int32_t action);
+ inline bool isTouchEvent() const {
+ return isTouchEvent(mSource, mAction);
+ }
+
// Low-level accessors.
inline const int32_t* getPointerIds() const { return mPointerIds.array(); }
inline const nsecs_t* getSampleEventTimes() const { return mSampleEventTimes.array(); }
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index a80320e..0ed0866 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -616,6 +616,23 @@ status_t MotionEvent::writeToParcel(Parcel* parcel) const {
}
#endif
+bool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
+ if (source & AINPUT_SOURCE_CLASS_POINTER) {
+ // Specifically excludes HOVER_MOVE and SCROLL.
+ switch (action & AMOTION_EVENT_ACTION_MASK) {
+ case AMOTION_EVENT_ACTION_DOWN:
+ case AMOTION_EVENT_ACTION_MOVE:
+ case AMOTION_EVENT_ACTION_UP:
+ case AMOTION_EVENT_ACTION_POINTER_DOWN:
+ case AMOTION_EVENT_ACTION_POINTER_UP:
+ case AMOTION_EVENT_ACTION_CANCEL:
+ case AMOTION_EVENT_ACTION_OUTSIDE:
+ return true;
+ }
+ }
+ return false;
+}
+
// --- InputDeviceInfo ---
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
index 36afd75..74dde9c 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
@@ -108,7 +108,8 @@ public abstract class KeyguardViewBase extends FrameLayout {
* action should be posted to a handler.
*
* @param keyCode The wake key, which may be relevant for configuring the
- * keyguard.
+ * keyguard. May be {@link KeyEvent#KEYCODE_UNKNOWN} if waking for a reason
+ * other than a key press.
*/
abstract public void wakeWhenReadyTq(int keyCode);
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
index edab690..8d70a7b 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
@@ -201,7 +201,8 @@ public class KeyguardViewManager implements KeyguardWindowController {
* Be sure not to take any action that takes a long time; any significant
* action should be posted to a handler.
*
- * @param keyCode The wake key.
+ * @param keyCode The wake key. May be {@link KeyEvent#KEYCODE_UNKNOWN} if waking
+ * for a reason other than a key press.
*/
public boolean wakeWhenReadyTq(int keyCode) {
if (DEBUG) Log.d(TAG, "wakeWhenReady(" + keyCode + ")");
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index b32a729..e7a9eb1 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -810,6 +810,28 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
}
/**
+ * When a wake motion such as an external mouse movement is received when the screen
+ * is off and the keyguard is showing, we need to decide whether to actually turn
+ * on the screen, and if so, tell the keyguard to prepare itself and poke the wake
+ * lock when it is ready.
+ *
+ * The 'Tq' suffix is per the documentation in {@link WindowManagerPolicy}.
+ * Be sure not to take any action that takes a long time; any significant
+ * action should be posted to a handler.
+ *
+ * @return Whether we poked the wake lock (and turned the screen on)
+ */
+ public boolean onWakeMotionWhenKeyguardShowingTq() {
+ if (DEBUG) Log.d(TAG, "onWakeMotionWhenKeyguardShowing()");
+
+ // give the keyguard view manager a chance to adjust the state of the
+ // keyguard based on the key that woke the device before poking
+ // the wake lock
+ wakeWhenReadyLocked(KeyEvent.KEYCODE_UNKNOWN);
+ return true;
+ }
+
+ /**
* Callbacks from {@link KeyguardViewManager}.
*/
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 75ef762..8e18f2a 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2364,6 +2364,25 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return result;
}
+ /** {@inheritDoc} */
+ @Override
+ public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
+ int result = 0;
+
+ final boolean isWakeMotion = (policyFlags
+ & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
+ if (isWakeMotion) {
+ if (mKeyguardMediator.isShowing()) {
+ // If the keyguard is showing, let it decide what to do with the wake motion.
+ mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq();
+ } else {
+ // Otherwise, wake the device ourselves.
+ result |= ACTION_POKE_USER_ACTIVITY;
+ }
+ }
+ return result;
+ }
+
class PassHeadsetKey implements Runnable {
KeyEvent mKeyEvent;
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index 25db25e..2fe5980 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -933,6 +933,11 @@ int EventHub::openDevice(const char *devicePath) {
return -1;
}
+ // Determine whether the device is external or internal.
+ if (isExternalDevice(device)) {
+ device->classes |= INPUT_DEVICE_CLASS_EXTERNAL;
+ }
+
LOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
"configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s",
deviceId, fd, devicePath, device->identifier.name.string(),
@@ -997,6 +1002,17 @@ void EventHub::clearKeyboardProperties(Device* device, bool builtInKeyboard) {
android::clearKeyboardProperties(id);
}
+bool EventHub::isExternalDevice(Device* device) {
+ if (device->configuration) {
+ bool value;
+ if (device->configuration->tryGetProperty(String8("device.internal"), value)
+ && value) {
+ return false;
+ }
+ }
+ return device->identifier.bus == BUS_USB || device->identifier.bus == BUS_BLUETOOTH;
+}
+
bool EventHub::hasKeycodeLocked(Device* device, int keycode) const {
if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) {
return false;
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
index f7936d2..445c04b 100644
--- a/services/input/EventHub.h
+++ b/services/input/EventHub.h
@@ -126,6 +126,9 @@ enum {
/* The input device is a joystick (implies gamepad, has joystick absolute axes). */
INPUT_DEVICE_CLASS_JOYSTICK = 0x00000100,
+
+ /* The input device is external (not built-in). */
+ INPUT_DEVICE_CLASS_EXTERNAL = 0x80000000,
};
/*
@@ -304,6 +307,8 @@ private:
void setKeyboardProperties(Device* device, bool builtInKeyboard);
void clearKeyboardProperties(Device* device, bool builtInKeyboard);
+ bool isExternalDevice(Device* device);
+
// Protect all internal state.
mutable Mutex mLock;
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index c064a9c..655b672 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -1572,7 +1572,7 @@ String8 InputDispatcher::getApplicationWindowLabelLocked(const InputApplication*
}
void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
- int32_t eventType = POWER_MANAGER_BUTTON_EVENT;
+ int32_t eventType = POWER_MANAGER_OTHER_EVENT;
switch (eventEntry->type) {
case EventEntry::TYPE_MOTION: {
const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
@@ -1580,7 +1580,7 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
return;
}
- if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
+ if (MotionEvent::isTouchEvent(motionEntry->source, motionEntry->action)) {
eventType = POWER_MANAGER_TOUCH_EVENT;
}
break;
@@ -1590,6 +1590,7 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
return;
}
+ eventType = POWER_MANAGER_BUTTON_EVENT;
break;
}
}
@@ -2304,7 +2305,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, uint32_t
}
policyFlags |= POLICY_FLAG_TRUSTED;
- mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
+ mPolicy->interceptMotionBeforeQueueing(eventTime, /*byref*/ policyFlags);
bool needWake;
{ // acquire lock
@@ -2498,7 +2499,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
}
nsecs_t eventTime = motionEvent->getEventTime();
- mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
+ mPolicy->interceptMotionBeforeQueueing(eventTime, /*byref*/ policyFlags);
mLock.lock();
const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index 304b1bb..1e118c4 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -165,14 +165,14 @@ public:
*/
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) = 0;
- /* Intercepts a generic touch, trackball or other event before queueing it.
+ /* Intercepts a touch, trackball or other motion event before queueing it.
* The policy can use this method as an opportunity to perform power management functions
* and early event preprocessing such as updating policy flags.
*
* This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
* should be dispatched to applications.
*/
- virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
+ virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
/* Allows the policy a chance to intercept a key before dispatching. */
virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index c3c143c..b92c3b5 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -233,6 +233,11 @@ void InputReader::removeDevice(int32_t deviceId) {
InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
InputDevice* device = new InputDevice(this, deviceId, name);
+ // External devices.
+ if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
+ device->setExternal(true);
+ }
+
// Switch-like devices.
if (classes & INPUT_DEVICE_CLASS_SWITCH) {
device->addMapper(new SwitchInputMapper(device));
@@ -565,7 +570,7 @@ bool InputReaderThread::threadLoop() {
// --- InputDevice ---
InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
- mContext(context), mId(id), mName(name), mSources(0) {
+ mContext(context), mId(id), mName(name), mSources(0), mIsExternal(false) {
}
InputDevice::~InputDevice() {
@@ -582,6 +587,7 @@ void InputDevice::dump(String8& dump) {
dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
deviceInfo.getName().string());
+ dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
@@ -985,6 +991,16 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
downTime = mLocked.downTime;
} // release lock
+ // Key down on external an keyboard should wake the device.
+ // We don't do this for internal keyboards to prevent them from waking up in your pocket.
+ // For internal keyboards, the key layout file should specify the policy flags for
+ // each wake key individually.
+ // TODO: Use the input device configuration to control this behavior more finely.
+ if (down && getDevice()->isExternal()
+ && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {
+ policyFlags |= POLICY_FLAG_WAKE_DROPPED;
+ }
+
if (metaStateChanged) {
getContext()->updateGlobalMetaState();
}
@@ -1379,9 +1395,18 @@ void CursorInputMapper::sync(nsecs_t when) {
}
} // release lock
+ // Moving an external trackball or mouse should wake the device.
+ // We don't do this for internal cursor devices to prevent them from waking up
+ // the device in your pocket.
+ // TODO: Use the input device configuration to control this behavior more finely.
+ uint32_t policyFlags = 0;
+ if (getDevice()->isExternal()) {
+ policyFlags |= POLICY_FLAG_WAKE_DROPPED;
+ }
+
int32_t metaState = mContext->getGlobalMetaState();
int32_t pointerId = 0;
- getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0,
+ getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
@@ -1391,7 +1416,7 @@ void CursorInputMapper::sync(nsecs_t when) {
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
- getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0,
+ getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
AMOTION_EVENT_ACTION_SCROLL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
}
@@ -2308,8 +2333,6 @@ void TouchInputMapper::reset() {
}
void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
- uint32_t policyFlags = 0;
-
// Preprocess pointer data.
if (mParameters.useBadTouchFilter) {
if (applyBadTouchFilter()) {
@@ -2338,9 +2361,18 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
savedTouch = & mCurrentTouch;
}
- // Hide the pointer on an initial down.
+ uint32_t policyFlags = 0;
if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
+ // Hide the pointer on an initial down.
getContext()->fadePointer();
+
+ // Initial downs on external touch devices should wake the device.
+ // We don't do this for internal touch screens to prevent them from waking
+ // up in your pocket.
+ // TODO: Use the input device configuration to control this behavior more finely.
+ if (getDevice()->isExternal()) {
+ policyFlags |= POLICY_FLAG_WAKE_DROPPED;
+ }
}
// Process touches and virtual keys.
@@ -4017,8 +4049,14 @@ void JoystickInputMapper::sync(nsecs_t when, bool force) {
axis.oldValue = axis.newValue;
}
+ // Moving a joystick axis should not wake the devide because joysticks can
+ // be fairly noisy even when not in use. On the other hand, pushing a gamepad
+ // button will likely wake the device.
+ // TODO: Use the input device configuration to control this behavior more finely.
+ uint32_t policyFlags = 0;
+
int32_t pointerId = 0;
- getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, 0,
+ getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1, &pointerId, &pointerCoords, 0, 0, 0);
}
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index b344ffe..655f0f0 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -286,6 +286,9 @@ public:
inline const String8& getName() { return mName; }
inline uint32_t getSources() { return mSources; }
+ inline bool isExternal() { return mIsExternal; }
+ inline void setExternal(bool external) { mIsExternal = external; }
+
inline bool isIgnored() { return mMappers.isEmpty(); }
void dump(String8& dump);
@@ -317,6 +320,7 @@ private:
String8 mName;
uint32_t mSources;
+ bool mIsExternal;
typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc);
diff --git a/services/input/tests/InputDispatcher_test.cpp b/services/input/tests/InputDispatcher_test.cpp
index 5ba1867..bb3449b 100644
--- a/services/input/tests/InputDispatcher_test.cpp
+++ b/services/input/tests/InputDispatcher_test.cpp
@@ -58,7 +58,7 @@ private:
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
}
- virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
+ virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
}
virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 864241e..8404b3a 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -188,6 +188,8 @@ private:
class FakeInputDispatcher : public InputDispatcherInterface {
public:
struct NotifyConfigurationChangedArgs {
+ NotifyConfigurationChangedArgs() : eventTime(0) { }
+
nsecs_t eventTime;
};
@@ -687,6 +689,10 @@ private:
}
}
+ virtual bool isExternal(int32_t deviceId) const {
+ return false;
+ }
+
virtual void dump(String8& dump) {
}
};
diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/wm/InputManager.java
index 326eca7..77cec5d 100644
--- a/services/java/com/android/server/wm/InputManager.java
+++ b/services/java/com/android/server/wm/InputManager.java
@@ -448,7 +448,13 @@ public class InputManager {
return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing(
event, policyFlags, isScreenOn);
}
-
+
+ @SuppressWarnings("unused")
+ public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
+ return mWindowManagerService.mInputMonitor.interceptMotionBeforeQueueingWhenScreenOff(
+ policyFlags);
+ }
+
@SuppressWarnings("unused")
public boolean interceptKeyBeforeDispatching(InputWindowHandle focus,
KeyEvent event, int policyFlags) {
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index b1833c4..45a78af 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -258,7 +258,14 @@ final class InputMonitor {
KeyEvent event, int policyFlags, boolean isScreenOn) {
return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags, isScreenOn);
}
-
+
+ /* Provides an opportunity for the window manager policy to intercept early
+ * motion event processing when the screen is off since these events are normally
+ * dropped. */
+ public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
+ return mService.mPolicy.interceptMotionBeforeQueueingWhenScreenOff(policyFlags);
+ }
+
/* Provides an opportunity for the window manager policy to process a key before
* ordinary dispatch. */
public boolean interceptKeyBeforeDispatching(
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 5ef234a..00d0af1 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -59,6 +59,7 @@ static struct {
jmethodID notifyInputChannelBroken;
jmethodID notifyANR;
jmethodID interceptKeyBeforeQueueing;
+ jmethodID interceptMotionBeforeQueueingWhenScreenOff;
jmethodID interceptKeyBeforeDispatching;
jmethodID dispatchUnhandledKey;
jmethodID checkInjectEventsPermission;
@@ -178,7 +179,7 @@ public:
virtual nsecs_t getKeyRepeatDelay();
virtual int32_t getMaxEventsPerSecond();
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
- virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
+ virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags);
virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
@@ -215,6 +216,7 @@ private:
} mLocked;
void updateInactivityFadeDelayLocked(const sp<PointerController>& controller);
+ void handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags);
// Power manager interactions.
bool isScreenOn();
@@ -620,10 +622,6 @@ void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
// - Ask the window manager what to do with normal events and trusted injected events.
// - For normal events wake and brighten the screen if currently off or dim.
if ((policyFlags & POLICY_FLAG_TRUSTED)) {
- const int32_t WM_ACTION_PASS_TO_USER = 1;
- const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2;
- const int32_t WM_ACTION_GO_TO_SLEEP = 4;
-
nsecs_t when = keyEvent->getEventTime();
bool isScreenOn = this->isScreenOn();
bool isScreenBright = this->isScreenBright();
@@ -655,23 +653,13 @@ void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
}
}
- if (wmActions & WM_ACTION_GO_TO_SLEEP) {
- android_server_PowerManagerService_goToSleep(when);
- }
-
- if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
- android_server_PowerManagerService_userActivity(when, POWER_MANAGER_BUTTON_EVENT);
- }
-
- if (wmActions & WM_ACTION_PASS_TO_USER) {
- policyFlags |= POLICY_FLAG_PASS_TO_USER;
- }
+ handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
} else {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
}
}
-void NativeInputManager::interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
+void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
// Policy:
// - Ignore untrusted events and pass them along.
// - No special filtering for injected events required at this time.
@@ -684,12 +672,55 @@ void NativeInputManager::interceptGenericBeforeQueueing(nsecs_t when, uint32_t&
if (!isScreenBright()) {
policyFlags |= POLICY_FLAG_BRIGHT_HERE;
}
+ } else {
+ JNIEnv* env = jniEnv();
+ jint wmActions = env->CallIntMethod(mCallbacksObj,
+ gCallbacksClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
+ policyFlags);
+ if (checkAndClearExceptionFromCallback(env,
+ "interceptMotionBeforeQueueingWhenScreenOff")) {
+ wmActions = 0;
+ }
+
+ policyFlags |= POLICY_FLAG_WOKE_HERE | POLICY_FLAG_BRIGHT_HERE;
+ handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
}
} else {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
}
}
+void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,
+ uint32_t& policyFlags) {
+ enum {
+ WM_ACTION_PASS_TO_USER = 1,
+ WM_ACTION_POKE_USER_ACTIVITY = 2,
+ WM_ACTION_GO_TO_SLEEP = 4,
+ };
+
+ if (wmActions & WM_ACTION_GO_TO_SLEEP) {
+#ifdef DEBUG_INPUT_DISPATCHER_POLICY
+ LOGD("handleInterceptActions: Going to sleep.");
+#endif
+ android_server_PowerManagerService_goToSleep(when);
+ }
+
+ if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
+#ifdef DEBUG_INPUT_DISPATCHER_POLICY
+ LOGD("handleInterceptActions: Poking user activity.");
+#endif
+ android_server_PowerManagerService_userActivity(when, POWER_MANAGER_BUTTON_EVENT);
+ }
+
+ if (wmActions & WM_ACTION_PASS_TO_USER) {
+ policyFlags |= POLICY_FLAG_PASS_TO_USER;
+ } else {
+#ifdef DEBUG_INPUT_DISPATCHER_POLICY
+ LOGD("handleInterceptActions: Not passing key to user.");
+#endif
+ }
+}
+
bool NativeInputManager::interceptKeyBeforeDispatching(
const sp<InputWindowHandle>& inputWindowHandle,
const KeyEvent* keyEvent, uint32_t policyFlags) {
@@ -1204,6 +1235,10 @@ int register_android_server_InputManager(JNIEnv* env) {
GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
"interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;IZ)I");
+ GET_METHOD_ID(gCallbacksClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
+ gCallbacksClassInfo.clazz,
+ "interceptMotionBeforeQueueingWhenScreenOff", "(I)I");
+
GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
"interceptKeyBeforeDispatching",
"(Lcom/android/server/wm/InputWindowHandle;Landroid/view/KeyEvent;I)Z");