diff options
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"); |