diff options
author | Jeff Brown <jeffbrown@google.com> | 2010-10-11 17:26:51 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2010-10-11 17:26:51 -0700 |
commit | f2e0681ada3ffe1de994a51dcebd6ef045d27434 (patch) | |
tree | c6f8e837d2091a890fb3d9d2882b3a534b190625 | |
parent | d965724fdcc63a070657518542559a8b1a35a70d (diff) | |
parent | 1da8d4d1697cec871dea8c30dad67e90db10bde6 (diff) | |
download | frameworks_base-f2e0681ada3ffe1de994a51dcebd6ef045d27434.zip frameworks_base-f2e0681ada3ffe1de994a51dcebd6ef045d27434.tar.gz frameworks_base-f2e0681ada3ffe1de994a51dcebd6ef045d27434.tar.bz2 |
am 1da8d4d1: Merge "Fix an event injection bug when the policy is bypassed." into gingerbread
Merge commit '1da8d4d1697cec871dea8c30dad67e90db10bde6' into gingerbread-plus-aosp
* commit '1da8d4d1697cec871dea8c30dad67e90db10bde6':
Fix an event injection bug when the policy is bypassed.
-rw-r--r-- | core/java/android/view/WindowManagerPolicy.java | 1 | ||||
-rw-r--r-- | include/ui/Input.h | 4 | ||||
-rw-r--r-- | include/ui/InputDispatcher.h | 5 | ||||
-rw-r--r-- | libs/ui/InputDispatcher.cpp | 63 | ||||
-rwxr-xr-x | policy/src/com/android/internal/policy/impl/PhoneWindowManager.java | 15 | ||||
-rw-r--r-- | services/java/com/android/server/InputManager.java | 5 | ||||
-rw-r--r-- | services/java/com/android/server/WindowManagerService.java | 7 | ||||
-rw-r--r-- | services/jni/com_android_server_InputManager.cpp | 250 |
8 files changed, 149 insertions, 201 deletions
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index ef7716e..1fd31a3 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -77,6 +77,7 @@ public interface WindowManagerPolicy { public final static int FLAG_VIRTUAL = 0x00000100; public final static int FLAG_INJECTED = 0x01000000; + public final static int FLAG_TRUSTED = 0x02000000; public final static int FLAG_WOKE_HERE = 0x10000000; public final static int FLAG_BRIGHT_HERE = 0x20000000; diff --git a/include/ui/Input.h b/include/ui/Input.h index 66061fd..8c6018b 100644 --- a/include/ui/Input.h +++ b/include/ui/Input.h @@ -95,6 +95,10 @@ enum { // Indicates that the input event was injected. POLICY_FLAG_INJECTED = 0x01000000, + // Indicates that the input event is from a trusted source such as a directly attached + // input device or an application with system-wide event injection permission. + POLICY_FLAG_TRUSTED = 0x02000000, + /* These flags are set by the input reader policy as it intercepts each event. */ // Indicates that the screen was off when the event was received and the event diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h index 0834e86..3599163 100644 --- a/include/ui/InputDispatcher.h +++ b/include/ui/InputDispatcher.h @@ -913,7 +913,6 @@ private: void drainInboundQueueLocked(); void releasePendingEventLocked(); void releaseInboundEventLocked(EventEntry* entry); - bool isEventFromTrustedSourceLocked(EventEntry* entry); // Dispatch state. bool mDispatchEnabled; @@ -960,10 +959,10 @@ private: nsecs_t currentTime, ConfigurationChangedEntry* entry); bool dispatchKeyLocked( nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout, - bool dropEvent, nsecs_t* nextWakeupTime); + DropReason* dropReason, nsecs_t* nextWakeupTime); bool dispatchMotionLocked( nsecs_t currentTime, MotionEntry* entry, - bool dropEvent, nsecs_t* nextWakeupTime); + DropReason* dropReason, nsecs_t* nextWakeupTime); void dispatchEventToCurrentInputTargetsLocked( nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample); diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp index 58c2cdf..41b6ff3 100644 --- a/libs/ui/InputDispatcher.cpp +++ b/libs/ui/InputDispatcher.cpp @@ -370,7 +370,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout, } } done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout, - dropReason != DROP_REASON_NOT_DROPPED, nextWakeupTime); + &dropReason, nextWakeupTime); break; } @@ -380,7 +380,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout, dropReason = DROP_REASON_APP_SWITCH; } done = dispatchMotionLocked(currentTime, typedEntry, - dropReason != DROP_REASON_NOT_DROPPED, nextWakeupTime); + &dropReason, nextWakeupTime); break; } @@ -431,6 +431,9 @@ void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropR const char* reason; switch (dropReason) { case DROP_REASON_POLICY: +#if DEBUG_INBOUND_EVENT_DETAILS + LOGD("Dropped event because policy requested that it not be delivered to the application."); +#endif reason = "inbound event was dropped because the policy requested that it not be " "delivered to the application"; break; @@ -473,7 +476,7 @@ bool InputDispatcher::isAppSwitchKeyCode(int32_t keyCode) { bool InputDispatcher::isAppSwitchKeyEventLocked(KeyEntry* keyEntry) { return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) && isAppSwitchKeyCode(keyEntry->keyCode) - && isEventFromTrustedSourceLocked(keyEntry) + && (keyEntry->policyFlags & POLICY_FLAG_TRUSTED) && (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER); } @@ -541,12 +544,6 @@ void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) { mAllocator.releaseEventEntry(entry); } -bool InputDispatcher::isEventFromTrustedSourceLocked(EventEntry* entry) { - InjectionState* injectionState = entry->injectionState; - return ! injectionState - || hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid); -} - void InputDispatcher::resetKeyRepeatLocked() { if (mKeyRepeatState.lastKeyEntry) { mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry); @@ -559,7 +556,8 @@ InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked( KeyEntry* entry = mKeyRepeatState.lastKeyEntry; // Reuse the repeated key entry if it is otherwise unreferenced. - uint32_t policyFlags = entry->policyFlags & (POLICY_FLAG_RAW_MASK | POLICY_FLAG_PASS_TO_USER); + uint32_t policyFlags = (entry->policyFlags & POLICY_FLAG_RAW_MASK) + | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED; if (entry->refCount == 1) { mAllocator.recycleKeyEntry(entry); entry->eventTime = currentTime; @@ -608,19 +606,13 @@ bool InputDispatcher::dispatchConfigurationChangedLocked( bool InputDispatcher::dispatchKeyLocked( nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout, - bool dropEvent, nsecs_t* nextWakeupTime) { + DropReason* dropReason, nsecs_t* nextWakeupTime) { // Give the policy a chance to intercept the key. if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) { - bool trusted; - if (! dropEvent && mFocusedWindow) { - trusted = checkInjectionPermission(mFocusedWindow, entry->injectionState); - } else { - trusted = isEventFromTrustedSourceLocked(entry); - } - if (trusted) { + if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) { CommandEntry* commandEntry = postCommandLocked( & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible); - if (! dropEvent && mFocusedWindow) { + if (mFocusedWindow) { commandEntry->inputChannel = mFocusedWindow->inputChannel; } commandEntry->keyEntry = entry; @@ -630,13 +622,16 @@ bool InputDispatcher::dispatchKeyLocked( entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE; } } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) { + if (*dropReason == DROP_REASON_NOT_DROPPED) { + *dropReason = DROP_REASON_POLICY; + } resetTargetsLocked(); setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_SUCCEEDED); return true; } // Clean up if dropping the event. - if (dropEvent) { + if (*dropReason != DROP_REASON_NOT_DROPPED) { resetTargetsLocked(); setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED); return true; @@ -648,7 +643,8 @@ bool InputDispatcher::dispatchKeyLocked( if (entry->repeatCount == 0 && entry->action == AKEY_EVENT_ACTION_DOWN - && ! entry->isInjected()) { + && (entry->policyFlags & POLICY_FLAG_TRUSTED) + && !entry->isInjected()) { if (mKeyRepeatState.lastKeyEntry && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) { // We have seen two identical key downs in a row which indicates that the device @@ -713,9 +709,9 @@ void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyE } bool InputDispatcher::dispatchMotionLocked( - nsecs_t currentTime, MotionEntry* entry, bool dropEvent, nsecs_t* nextWakeupTime) { + nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) { // Clean up if dropping the event. - if (dropEvent) { + if (*dropReason != DROP_REASON_NOT_DROPPED) { resetTargetsLocked(); setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED); return true; @@ -2085,6 +2081,7 @@ void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t sou return; } + policyFlags |= POLICY_FLAG_TRUSTED; mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags, keyCode, scanCode, /*byref*/ policyFlags); @@ -2130,6 +2127,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t return; } + policyFlags |= POLICY_FLAG_TRUSTED; mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags); bool needWake; @@ -2263,6 +2261,7 @@ void InputDispatcher::notifySwitch(nsecs_t when, int32_t switchCode, int32_t swi switchCode, switchValue, policyFlags); #endif + policyFlags |= POLICY_FLAG_TRUSTED; mPolicy->notifySwitch(when, switchCode, switchValue, policyFlags); } @@ -2275,7 +2274,11 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, #endif nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis); - bool trusted = hasInjectionPermission(injectorPid, injectorUid); + + uint32_t policyFlags = POLICY_FLAG_INJECTED; + if (hasInjectionPermission(injectorPid, injectorUid)) { + policyFlags |= POLICY_FLAG_TRUSTED; + } EventEntry* injectedEntry; switch (event->getType()) { @@ -2291,11 +2294,8 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t flags = keyEvent->getFlags(); int32_t keyCode = keyEvent->getKeyCode(); int32_t scanCode = keyEvent->getScanCode(); - uint32_t policyFlags = POLICY_FLAG_INJECTED; - if (trusted) { - mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags, - keyCode, scanCode, /*byref*/ policyFlags); - } + mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags, + keyCode, scanCode, /*byref*/ policyFlags); mLock.lock(); injectedEntry = mAllocator.obtainKeyEntry(eventTime, deviceId, keyEvent->getSource(), @@ -2314,10 +2314,7 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event, } nsecs_t eventTime = motionEvent->getEventTime(); - uint32_t policyFlags = POLICY_FLAG_INJECTED; - if (trusted) { - mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags); - } + mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags); mLock.lock(); const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes(); diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index f21d357..d9bceec 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -1057,6 +1057,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public boolean interceptKeyBeforeDispatching(WindowState win, int action, int flags, int keyCode, int metaState, int repeatCount, int policyFlags) { + if ((policyFlags & WindowManagerPolicy.FLAG_TRUSTED) == 0) { + return false; + } + final boolean keyguardOn = keyguardOn(); final boolean down = (action == KeyEvent.ACTION_DOWN); final boolean canceled = ((flags & KeyEvent.FLAG_CANCELED) != 0); @@ -1083,7 +1087,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (!down) { mHomePressed = false; - if (! canceled) { + if (!canceled) { // If an incoming call is ringing, HOME is totally disabled. // (The user is already on the InCallScreen at this point, // and his ONLY options are to answer or reject the call.) @@ -1735,7 +1739,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down, int policyFlags, boolean isScreenOn) { int result = ACTION_PASS_TO_USER; - + if ((policyFlags & WindowManagerPolicy.FLAG_TRUSTED) == 0) { + return result; + } + + if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0) { + performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); + } + final boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0; diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java index ed1243a..df41264 100644 --- a/services/java/com/android/server/InputManager.java +++ b/services/java/com/android/server/InputManager.java @@ -359,11 +359,6 @@ public class InputManager { private static final String CALIBRATION_DIR_PATH = "usr/idc/"; @SuppressWarnings("unused") - public void virtualKeyDownFeedback() { - mWindowManagerService.mInputMonitor.virtualKeyDownFeedback(); - } - - @SuppressWarnings("unused") public void notifyConfigurationChanged(long whenNanos) { mWindowManagerService.sendNewConfiguration(); } diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index a23737b..abf848c 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -5244,13 +5244,6 @@ public class WindowManagerService extends IWindowManager.Stub mTempInputWindows.clear(); } - /* Provides feedback for a virtual key down. */ - public void virtualKeyDownFeedback() { - synchronized (mWindowMap) { - mPolicy.performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); - } - } - /* Notifies that the lid switch changed state. */ public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen); diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp index 18037e4..a0b0aba 100644 --- a/services/jni/com_android_server_InputManager.cpp +++ b/services/jni/com_android_server_InputManager.cpp @@ -50,7 +50,6 @@ static struct { jmethodID notifyLidSwitchChanged; jmethodID notifyInputChannelBroken; jmethodID notifyANR; - jmethodID virtualKeyDownFeedback; jmethodID interceptKeyBeforeQueueing; jmethodID interceptKeyBeforeDispatching; jmethodID checkInjectEventsPermission; @@ -192,6 +191,8 @@ public: /* --- InputDispatcherPolicyInterface implementation --- */ + virtual void notifySwitch(nsecs_t when, int32_t switchCode, int32_t switchValue, + uint32_t policyFlags); virtual void notifyConfigurationChanged(nsecs_t when); virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle, const sp<InputChannel>& inputChannel); @@ -205,8 +206,6 @@ public: virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags); virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel, const KeyEvent* keyEvent, uint32_t policyFlags); - virtual void notifySwitch(nsecs_t when, int32_t switchCode, int32_t switchValue, - uint32_t policyFlags); virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType); virtual bool checkInjectEventsPermissionNonReentrant( int32_t injectorPid, int32_t injectorUid); @@ -255,7 +254,6 @@ private: static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow); - static bool isPolicyKey(int32_t keyCode, bool isScreenOn); static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName); static inline JNIEnv* jniEnv() { @@ -291,37 +289,6 @@ void NativeInputManager::dump(String8& dump) { dump.append("\n"); } -bool NativeInputManager::isPolicyKey(int32_t keyCode, bool isScreenOn) { - // Special keys that the WindowManagerPolicy might care about. - switch (keyCode) { - case AKEYCODE_VOLUME_UP: - case AKEYCODE_VOLUME_DOWN: - case AKEYCODE_ENDCALL: - case AKEYCODE_POWER: - case AKEYCODE_CALL: - case AKEYCODE_HOME: - case AKEYCODE_MENU: - case AKEYCODE_SEARCH: - // media keys - case AKEYCODE_HEADSETHOOK: - case AKEYCODE_MEDIA_PLAY_PAUSE: - case AKEYCODE_MEDIA_STOP: - case AKEYCODE_MEDIA_NEXT: - case AKEYCODE_MEDIA_PREVIOUS: - case AKEYCODE_MEDIA_REWIND: - case AKEYCODE_MEDIA_FAST_FORWARD: - // The policy always cares about these keys. - return true; - default: - // We need to pass all keys to the policy in the following cases: - // - screen is off - // - keyguard is visible - // - policy is performing key chording - //return ! isScreenOn || keyguardVisible || chording; - return true; // XXX stubbed out for now - } -} - bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { if (env->ExceptionCheck()) { LOGE("An exception was thrown by callback '%s'.", methodName); @@ -454,115 +421,6 @@ bool NativeInputManager::getDisplayInfo(int32_t displayId, return result; } -bool NativeInputManager::isScreenOn() { - return android_server_PowerManagerService_isScreenOn(); -} - -bool NativeInputManager::isScreenBright() { - return android_server_PowerManagerService_isScreenBright(); -} - -void NativeInputManager::interceptKeyBeforeQueueing(nsecs_t when, - int32_t deviceId, int32_t action, int32_t &flags, - int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) { -#if DEBUG_INPUT_DISPATCHER_POLICY - LOGD("interceptKeyBeforeQueueing - when=%lld, deviceId=%d, action=%d, flags=%d, " - "keyCode=%d, scanCode=%d, policyFlags=0x%x", - when, deviceId, action, flags, keyCode, scanCode, policyFlags); -#endif - - bool down = action == AKEY_EVENT_ACTION_DOWN; - if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) { - policyFlags |= POLICY_FLAG_VIRTUAL; - flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY; - - if (down) { - JNIEnv* env = jniEnv(); - env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.virtualKeyDownFeedback); - checkAndClearExceptionFromCallback(env, "virtualKeyDownFeedback"); - } - } - - 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; - - bool isScreenOn = this->isScreenOn(); - bool isScreenBright = this->isScreenBright(); - - jint wmActions = 0; - if (isPolicyKey(keyCode, isScreenOn)) { - JNIEnv* env = jniEnv(); - - wmActions = env->CallIntMethod(mCallbacksObj, - gCallbacksClassInfo.interceptKeyBeforeQueueing, - when, keyCode, down, policyFlags, isScreenOn); - if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) { - wmActions = 0; - } - } else { - wmActions = WM_ACTION_PASS_TO_USER; - } - - if (! isScreenOn) { - // Key presses and releases wake the device. - policyFlags |= POLICY_FLAG_WOKE_HERE; - flags |= AKEY_EVENT_FLAG_WOKE_HERE; - } - - if (! isScreenBright) { - // Key presses and releases brighten the screen if dimmed. - policyFlags |= POLICY_FLAG_BRIGHT_HERE; - } - - 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; - } -} - -void NativeInputManager::interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) { -#if DEBUG_INPUT_DISPATCHER_POLICY - LOGD("interceptGenericBeforeQueueing - when=%lld, policyFlags=0x%x", when, policyFlags); -#endif - - if (isScreenOn()) { - // Only dispatch events when the device is awake. - // Do not wake the device. - policyFlags |= POLICY_FLAG_PASS_TO_USER; - - if (! isScreenBright()) { - // Brighten the screen if dimmed. - policyFlags |= POLICY_FLAG_BRIGHT_HERE; - } - } -} - -void NativeInputManager::notifySwitch(nsecs_t when, int32_t switchCode, - int32_t switchValue, uint32_t policyFlags) { -#if DEBUG_INPUT_DISPATCHER_POLICY - LOGD("notifySwitch - when=%lld, switchCode=%d, switchValue=%d, policyFlags=0x%x", - when, switchCode, switchValue, policyFlags); -#endif - - JNIEnv* env = jniEnv(); - - switch (switchCode) { - case SW_LID: - env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged, - when, switchValue == 0); - checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged"); - break; - } -} - bool NativeInputManager::filterTouchEvents() { if (mFilterTouchEvents < 0) { JNIEnv* env = jniEnv(); @@ -692,6 +550,24 @@ void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDevi } } +void NativeInputManager::notifySwitch(nsecs_t when, int32_t switchCode, + int32_t switchValue, uint32_t policyFlags) { +#if DEBUG_INPUT_DISPATCHER_POLICY + LOGD("notifySwitch - when=%lld, switchCode=%d, switchValue=%d, policyFlags=0x%x", + when, switchCode, switchValue, policyFlags); +#endif + + JNIEnv* env = jniEnv(); + + switch (switchCode) { + case SW_LID: + env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged, + when, switchValue == 0); + checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged"); + break; + } +} + void NativeInputManager::notifyConfigurationChanged(nsecs_t when) { #if DEBUG_INPUT_DISPATCHER_POLICY LOGD("notifyConfigurationChanged - when=%lld", when); @@ -944,13 +820,88 @@ void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) { mInputManager->getDispatcher()->setInputDispatchMode(enabled, frozen); } -bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel, - const KeyEvent* keyEvent, uint32_t policyFlags) { +bool NativeInputManager::isScreenOn() { + return android_server_PowerManagerService_isScreenOn(); +} + +bool NativeInputManager::isScreenBright() { + return android_server_PowerManagerService_isScreenBright(); +} + +void NativeInputManager::interceptKeyBeforeQueueing(nsecs_t when, + int32_t deviceId, int32_t action, int32_t &flags, + int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) { +#if DEBUG_INPUT_DISPATCHER_POLICY + LOGD("interceptKeyBeforeQueueing - when=%lld, deviceId=%d, action=%d, flags=%d, " + "keyCode=%d, scanCode=%d, policyFlags=0x%x", + when, deviceId, action, flags, keyCode, scanCode, policyFlags); +#endif + + if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) { + policyFlags |= POLICY_FLAG_VIRTUAL; + flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY; + } + + 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; + bool isScreenOn = this->isScreenOn(); - if (! isPolicyKey(keyEvent->getKeyCode(), isScreenOn)) { - return false; + bool isScreenBright = this->isScreenBright(); + + JNIEnv* env = jniEnv(); + jint wmActions = env->CallIntMethod(mCallbacksObj, + gCallbacksClassInfo.interceptKeyBeforeQueueing, + when, keyCode, action == AKEY_EVENT_ACTION_DOWN, policyFlags, isScreenOn); + if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) { + wmActions = 0; + } + + if (policyFlags & POLICY_FLAG_TRUSTED) { + if (! isScreenOn) { + // Key presses and releases wake the device. + policyFlags |= POLICY_FLAG_WOKE_HERE; + flags |= AKEY_EVENT_FLAG_WOKE_HERE; + } + + if (! isScreenBright) { + // Key presses and releases brighten the screen if dimmed. + policyFlags |= POLICY_FLAG_BRIGHT_HERE; + } + + 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; + } +} + +void NativeInputManager::interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) { +#if DEBUG_INPUT_DISPATCHER_POLICY + LOGD("interceptGenericBeforeQueueing - when=%lld, policyFlags=0x%x", when, policyFlags); +#endif + + if (isScreenOn()) { + // Only dispatch events when the device is awake. + // Do not wake the device. + policyFlags |= POLICY_FLAG_PASS_TO_USER; + + if ((policyFlags & POLICY_FLAG_TRUSTED) && !isScreenBright()) { + // Brighten the screen if dimmed. + policyFlags |= POLICY_FLAG_BRIGHT_HERE; + } + } +} + +bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel, + const KeyEvent* keyEvent, uint32_t policyFlags) { JNIEnv* env = jniEnv(); // Note: inputChannel may be null. @@ -1365,9 +1316,6 @@ int register_android_server_InputManager(JNIEnv* env) { GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz, "notifyANR", "(Ljava/lang/Object;Landroid/view/InputChannel;)J"); - GET_METHOD_ID(gCallbacksClassInfo.virtualKeyDownFeedback, gCallbacksClassInfo.clazz, - "virtualKeyDownFeedback", "()V"); - GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz, "interceptKeyBeforeQueueing", "(JIZIZ)I"); |