Loading core/java/android/view/KeyCharacterMap.java +46 −9 Original line number Original line Diff line number Diff line Loading @@ -386,19 +386,19 @@ public class KeyCharacterMap implements Parcelable { * * * @param keyCode The key code. * @param keyCode The key code. * @param metaState The meta key modifier state. * @param metaState The meta key modifier state. * @param outFallbackAction The fallback action object to populate. * @return The fallback action, or null if none. Remember to recycle the fallback action. * @return True if a fallback action was found, false otherwise. * * * @hide * @hide */ */ public boolean getFallbackAction(int keyCode, int metaState, public FallbackAction getFallbackAction(int keyCode, int metaState) { FallbackAction outFallbackAction) { FallbackAction action = FallbackAction.obtain(); if (outFallbackAction == null) { throw new IllegalArgumentException("fallbackAction must not be null"); } metaState = KeyEvent.normalizeMetaState(metaState); metaState = KeyEvent.normalizeMetaState(metaState); return nativeGetFallbackAction(mPtr, keyCode, metaState, outFallbackAction); if (nativeGetFallbackAction(mPtr, keyCode, metaState, action)) { action.metaState = KeyEvent.normalizeMetaState(action.metaState); return action; } action.recycle(); return null; } } /** /** Loading Loading @@ -727,7 +727,44 @@ public class KeyCharacterMap implements Parcelable { * @hide * @hide */ */ public static final class FallbackAction { public static final class FallbackAction { private static final int MAX_RECYCLED = 10; private static final Object sRecycleLock = new Object(); private static FallbackAction sRecycleBin; private static int sRecycledCount; private FallbackAction next; public int keyCode; public int keyCode; public int metaState; public int metaState; private FallbackAction() { } public static FallbackAction obtain() { final FallbackAction target; synchronized (sRecycleLock) { if (sRecycleBin == null) { target = new FallbackAction(); } else { target = sRecycleBin; sRecycleBin = target.next; sRecycledCount--; target.next = null; } } return target; } public void recycle() { synchronized (sRecycleLock) { if (sRecycledCount < MAX_RECYCLED) { next = sRecycleBin; sRecycleBin = this; sRecycledCount += 1; } else { next = null; } } } } } } } core/java/android/view/ViewRootImpl.java +13 −16 Original line number Original line Diff line number Diff line Loading @@ -328,8 +328,6 @@ public final class ViewRootImpl implements ViewParent, private final int mDensity; private final int mDensity; final KeyCharacterMap.FallbackAction mFallbackAction = new KeyCharacterMap.FallbackAction(); /** /** * Consistency verifier for debugging purposes. * Consistency verifier for debugging purposes. */ */ Loading Loading @@ -4481,20 +4479,19 @@ public final class ViewRootImpl implements ViewParent, final int keyCode = event.getKeyCode(); final int keyCode = event.getKeyCode(); final int metaState = event.getMetaState(); final int metaState = event.getMetaState(); KeyEvent fallbackEvent = null; synchronized (mFallbackAction) { // Check for fallback actions specified by the key character map. // Check for fallback actions specified by the key character map. if (kcm.getFallbackAction(keyCode, metaState, mFallbackAction)) { KeyCharacterMap.FallbackAction fallbackAction = int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK; kcm.getFallbackAction(keyCode, metaState); fallbackEvent = KeyEvent.obtain( if (fallbackAction != null) { final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK; KeyEvent fallbackEvent = KeyEvent.obtain( event.getDownTime(), event.getEventTime(), event.getDownTime(), event.getEventTime(), event.getAction(), mFallbackAction.keyCode, event.getAction(), fallbackAction.keyCode, event.getRepeatCount(), mFallbackAction.metaState, event.getRepeatCount(), fallbackAction.metaState, event.getDeviceId(), event.getScanCode(), event.getDeviceId(), event.getScanCode(), flags, event.getSource(), null); flags, event.getSource(), null); } fallbackAction.recycle(); } if (fallbackEvent != null) { dispatchKey(fallbackEvent); dispatchKey(fallbackEvent); } } } } Loading include/androidfw/Input.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -262,6 +262,8 @@ public: inline int32_t getFlags() const { return mFlags; } inline int32_t getFlags() const { return mFlags; } inline void setFlags(int32_t flags) { mFlags = flags; } inline int32_t getKeyCode() const { return mKeyCode; } inline int32_t getKeyCode() const { return mKeyCode; } inline int32_t getScanCode() const { return mScanCode; } inline int32_t getScanCode() const { return mScanCode; } Loading policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +62 −41 Original line number Original line Diff line number Diff line Loading @@ -463,8 +463,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { Intent mHomeIntent; Intent mHomeIntent; Intent mCarDockIntent; Intent mCarDockIntent; Intent mDeskDockIntent; Intent mDeskDockIntent; int mShortcutKeyPressed = -1; boolean mSearchKeyShortcutPending; boolean mConsumeShortcutKeyUp; boolean mConsumeSearchKeyUp; // support for activating the lock screen while the screen is on // support for activating the lock screen while the screen is on boolean mAllowLockscreenWhenOn; boolean mAllowLockscreenWhenOn; Loading Loading @@ -509,7 +509,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { ShortcutManager mShortcutManager; ShortcutManager mShortcutManager; PowerManager.WakeLock mBroadcastWakeLock; PowerManager.WakeLock mBroadcastWakeLock; final KeyCharacterMap.FallbackAction mFallbackAction = new KeyCharacterMap.FallbackAction(); // Fallback actions by key code. private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions = new SparseArray<KeyCharacterMap.FallbackAction>(); private static final int MSG_ENABLE_POINTER_LOCATION = 1; private static final int MSG_ENABLE_POINTER_LOCATION = 1; private static final int MSG_DISABLE_POINTER_LOCATION = 2; private static final int MSG_DISABLE_POINTER_LOCATION = 2; Loading Loading @@ -1709,7 +1711,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (false) { if (false) { Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount=" Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount=" + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed); + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed + " canceled=" + canceled); } } // If we think we might have a volume down & power key chord on the way // If we think we might have a volume down & power key chord on the way Loading Loading @@ -1842,13 +1845,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { } else if (keyCode == KeyEvent.KEYCODE_SEARCH) { } else if (keyCode == KeyEvent.KEYCODE_SEARCH) { if (down) { if (down) { if (repeatCount == 0) { if (repeatCount == 0) { mShortcutKeyPressed = keyCode; mSearchKeyShortcutPending = true; mConsumeShortcutKeyUp = false; mConsumeSearchKeyUp = false; } } } else if (keyCode == mShortcutKeyPressed) { } else { mShortcutKeyPressed = -1; mSearchKeyShortcutPending = false; if (mConsumeShortcutKeyUp) { if (mConsumeSearchKeyUp) { mConsumeShortcutKeyUp = false; mConsumeSearchKeyUp = false; return -1; return -1; } } } } Loading @@ -1865,10 +1868,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { // even if no shortcut was invoked. This prevents text from being // even if no shortcut was invoked. This prevents text from being // inadvertently inserted when using a keyboard that has built-in macro // inadvertently inserted when using a keyboard that has built-in macro // shortcut keys (that emit Search+x) and some of them are not registered. // shortcut keys (that emit Search+x) and some of them are not registered. if (mShortcutKeyPressed != -1) { if (mSearchKeyShortcutPending) { final KeyCharacterMap kcm = event.getKeyCharacterMap(); final KeyCharacterMap kcm = event.getKeyCharacterMap(); if (kcm.isPrintingKey(keyCode)) { if (kcm.isPrintingKey(keyCode)) { mConsumeShortcutKeyUp = true; mConsumeSearchKeyUp = true; mSearchKeyShortcutPending = false; if (down && repeatCount == 0 && !keyguardOn) { if (down && repeatCount == 0 && !keyguardOn) { Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState); Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState); if (shortcutIntent != null) { if (shortcutIntent != null) { Loading @@ -1878,13 +1882,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { } catch (ActivityNotFoundException ex) { } catch (ActivityNotFoundException ex) { Slog.w(TAG, "Dropping shortcut key combination because " Slog.w(TAG, "Dropping shortcut key combination because " + "the activity to which it is registered was not found: " + "the activity to which it is registered was not found: " + KeyEvent.keyCodeToString(mShortcutKeyPressed) + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex); + "+" + KeyEvent.keyCodeToString(keyCode), ex); } } } else { } else { Slog.i(TAG, "Dropping unregistered shortcut key combination: " Slog.i(TAG, "Dropping unregistered shortcut key combination: " + KeyEvent.keyCodeToString(mShortcutKeyPressed) + "SEARCH+" + KeyEvent.keyCodeToString(keyCode)); + "+" + KeyEvent.keyCodeToString(keyCode)); } } } } return -1; return -1; Loading Loading @@ -1964,51 +1966,70 @@ public class PhoneWindowManager implements WindowManagerPolicy { + ", policyFlags=" + policyFlags); + ", policyFlags=" + policyFlags); } } KeyEvent fallbackEvent = null; if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { final KeyCharacterMap kcm = event.getKeyCharacterMap(); final KeyCharacterMap kcm = event.getKeyCharacterMap(); final int keyCode = event.getKeyCode(); final int keyCode = event.getKeyCode(); final int metaState = event.getMetaState(); final int metaState = event.getMetaState(); final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0; // Check for fallback actions specified by the key character map. // Check for fallback actions specified by the key character map. if (getFallbackAction(kcm, keyCode, metaState, mFallbackAction)) { final FallbackAction fallbackAction; if (initialDown) { fallbackAction = kcm.getFallbackAction(keyCode, metaState); } else { fallbackAction = mFallbackActions.get(keyCode); } if (fallbackAction != null) { if (DEBUG_FALLBACK) { if (DEBUG_FALLBACK) { Slog.d(TAG, "Fallback: keyCode=" + mFallbackAction.keyCode Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode + " metaState=" + Integer.toHexString(mFallbackAction.metaState)); + " metaState=" + Integer.toHexString(fallbackAction.metaState)); } } int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK; final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK; KeyEvent fallbackEvent = KeyEvent.obtain( fallbackEvent = KeyEvent.obtain( event.getDownTime(), event.getEventTime(), event.getDownTime(), event.getEventTime(), event.getAction(), mFallbackAction.keyCode, event.getAction(), fallbackAction.keyCode, event.getRepeatCount(), mFallbackAction.metaState, event.getRepeatCount(), fallbackAction.metaState, event.getDeviceId(), event.getScanCode(), event.getDeviceId(), event.getScanCode(), flags, event.getSource(), null); flags, event.getSource(), null); int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true); if ((actions & ACTION_PASS_TO_USER) != 0) { if (!interceptFallback(win, fallbackEvent, policyFlags)) { long delayMillis = interceptKeyBeforeDispatching( fallbackEvent.recycle(); win, fallbackEvent, policyFlags); fallbackEvent = null; if (delayMillis == 0) { if (DEBUG_FALLBACK) { Slog.d(TAG, "Performing fallback."); } } return fallbackEvent; if (initialDown) { mFallbackActions.put(keyCode, fallbackAction); } else if (event.getAction() == KeyEvent.ACTION_UP) { mFallbackActions.remove(keyCode); fallbackAction.recycle(); } } } } fallbackEvent.recycle(); } } } if (DEBUG_FALLBACK) { if (DEBUG_FALLBACK) { if (fallbackEvent == null) { Slog.d(TAG, "No fallback."); Slog.d(TAG, "No fallback."); } else { Slog.d(TAG, "Performing fallback: " + fallbackEvent); } } return null; } return fallbackEvent; } } private boolean getFallbackAction(KeyCharacterMap kcm, int keyCode, int metaState, private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) { FallbackAction outFallbackAction) { int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true); // Consult the key character map for specific fallback actions. if ((actions & ACTION_PASS_TO_USER) != 0) { // For example, map NUMPAD_1 to MOVE_HOME when NUMLOCK is not pressed. long delayMillis = interceptKeyBeforeDispatching( return kcm.getFallbackAction(keyCode, metaState, outFallbackAction); win, fallbackEvent, policyFlags); if (delayMillis == 0) { return true; } } return false; } } /** /** Loading services/input/InputDispatcher.cpp +32 −8 Original line number Original line Diff line number Diff line Loading @@ -3354,6 +3354,25 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& con // generated a fallback or if the window is not a foreground window, // generated a fallback or if the window is not a foreground window, // then cancel the associated fallback key, if any. // then cancel the associated fallback key, if any. if (fallbackKeyCode != -1) { if (fallbackKeyCode != -1) { // Dispatch the unhandled key to the policy with the cancel flag. #if DEBUG_OUTBOUND_EVENT_DETAILS ALOGD("Unhandled key event: Asking policy to cancel fallback action. " "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x", keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount, keyEntry->policyFlags); #endif KeyEvent event; initializeKeyEvent(&event, keyEntry); event.setFlags(event.getFlags() | AKEY_EVENT_FLAG_CANCELED); mLock.unlock(); mPolicy->dispatchUnhandledKey(connection->inputWindowHandle, &event, keyEntry->policyFlags, &event); mLock.lock(); // Cancel the fallback key. if (fallbackKeyCode != AKEYCODE_UNKNOWN) { if (fallbackKeyCode != AKEYCODE_UNKNOWN) { CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS, CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS, "application handled the original non-fallback key " "application handled the original non-fallback key " Loading @@ -3374,8 +3393,9 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& con #if DEBUG_OUTBOUND_EVENT_DETAILS #if DEBUG_OUTBOUND_EVENT_DETAILS ALOGD("Unhandled key event: Skipping unhandled key event processing " ALOGD("Unhandled key event: Skipping unhandled key event processing " "since this is not an initial down. " "since this is not an initial down. " "keyCode=%d, action=%d, repeatCount=%d", "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x", originalKeyCode, keyEntry->action, keyEntry->repeatCount); originalKeyCode, keyEntry->action, keyEntry->repeatCount, keyEntry->policyFlags); #endif #endif return false; return false; } } Loading @@ -3383,8 +3403,9 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& con // Dispatch the unhandled key to the policy. // Dispatch the unhandled key to the policy. #if DEBUG_OUTBOUND_EVENT_DETAILS #if DEBUG_OUTBOUND_EVENT_DETAILS ALOGD("Unhandled key event: Asking policy to perform fallback action. " ALOGD("Unhandled key event: Asking policy to perform fallback action. " "keyCode=%d, action=%d, repeatCount=%d", "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x", keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount); keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount, keyEntry->policyFlags); #endif #endif KeyEvent event; KeyEvent event; initializeKeyEvent(&event, keyEntry); initializeKeyEvent(&event, keyEntry); Loading Loading @@ -3903,8 +3924,10 @@ void InputDispatcher::InputState::addKeyMemento(const KeyEntry* entry, int32_t f memento.source = entry->source; memento.source = entry->source; memento.keyCode = entry->keyCode; memento.keyCode = entry->keyCode; memento.scanCode = entry->scanCode; memento.scanCode = entry->scanCode; memento.metaState = entry->metaState; memento.flags = flags; memento.flags = flags; memento.downTime = entry->downTime; memento.downTime = entry->downTime; memento.policyFlags = entry->policyFlags; } } void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry, void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry, Loading @@ -3919,6 +3942,7 @@ void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry, memento.downTime = entry->downTime; memento.downTime = entry->downTime; memento.setPointers(entry); memento.setPointers(entry); memento.hovering = hovering; memento.hovering = hovering; memento.policyFlags = entry->policyFlags; } } void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) { void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) { Loading @@ -3935,9 +3959,9 @@ void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTim const KeyMemento& memento = mKeyMementos.itemAt(i); const KeyMemento& memento = mKeyMementos.itemAt(i); if (shouldCancelKey(memento, options)) { if (shouldCancelKey(memento, options)) { outEvents.push(new KeyEntry(currentTime, outEvents.push(new KeyEntry(currentTime, memento.deviceId, memento.source, 0, memento.deviceId, memento.source, memento.policyFlags, AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED, AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED, memento.keyCode, memento.scanCode, 0, 0, memento.downTime)); memento.keyCode, memento.scanCode, memento.metaState, 0, memento.downTime)); } } } } Loading @@ -3945,7 +3969,7 @@ void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTim const MotionMemento& memento = mMotionMementos.itemAt(i); const MotionMemento& memento = mMotionMementos.itemAt(i); if (shouldCancelMotion(memento, options)) { if (shouldCancelMotion(memento, options)) { outEvents.push(new MotionEntry(currentTime, outEvents.push(new MotionEntry(currentTime, memento.deviceId, memento.source, 0, memento.deviceId, memento.source, memento.policyFlags, memento.hovering memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT ? AMOTION_EVENT_ACTION_HOVER_EXIT : AMOTION_EVENT_ACTION_CANCEL, : AMOTION_EVENT_ACTION_CANCEL, Loading Loading
core/java/android/view/KeyCharacterMap.java +46 −9 Original line number Original line Diff line number Diff line Loading @@ -386,19 +386,19 @@ public class KeyCharacterMap implements Parcelable { * * * @param keyCode The key code. * @param keyCode The key code. * @param metaState The meta key modifier state. * @param metaState The meta key modifier state. * @param outFallbackAction The fallback action object to populate. * @return The fallback action, or null if none. Remember to recycle the fallback action. * @return True if a fallback action was found, false otherwise. * * * @hide * @hide */ */ public boolean getFallbackAction(int keyCode, int metaState, public FallbackAction getFallbackAction(int keyCode, int metaState) { FallbackAction outFallbackAction) { FallbackAction action = FallbackAction.obtain(); if (outFallbackAction == null) { throw new IllegalArgumentException("fallbackAction must not be null"); } metaState = KeyEvent.normalizeMetaState(metaState); metaState = KeyEvent.normalizeMetaState(metaState); return nativeGetFallbackAction(mPtr, keyCode, metaState, outFallbackAction); if (nativeGetFallbackAction(mPtr, keyCode, metaState, action)) { action.metaState = KeyEvent.normalizeMetaState(action.metaState); return action; } action.recycle(); return null; } } /** /** Loading Loading @@ -727,7 +727,44 @@ public class KeyCharacterMap implements Parcelable { * @hide * @hide */ */ public static final class FallbackAction { public static final class FallbackAction { private static final int MAX_RECYCLED = 10; private static final Object sRecycleLock = new Object(); private static FallbackAction sRecycleBin; private static int sRecycledCount; private FallbackAction next; public int keyCode; public int keyCode; public int metaState; public int metaState; private FallbackAction() { } public static FallbackAction obtain() { final FallbackAction target; synchronized (sRecycleLock) { if (sRecycleBin == null) { target = new FallbackAction(); } else { target = sRecycleBin; sRecycleBin = target.next; sRecycledCount--; target.next = null; } } return target; } public void recycle() { synchronized (sRecycleLock) { if (sRecycledCount < MAX_RECYCLED) { next = sRecycleBin; sRecycleBin = this; sRecycledCount += 1; } else { next = null; } } } } } } }
core/java/android/view/ViewRootImpl.java +13 −16 Original line number Original line Diff line number Diff line Loading @@ -328,8 +328,6 @@ public final class ViewRootImpl implements ViewParent, private final int mDensity; private final int mDensity; final KeyCharacterMap.FallbackAction mFallbackAction = new KeyCharacterMap.FallbackAction(); /** /** * Consistency verifier for debugging purposes. * Consistency verifier for debugging purposes. */ */ Loading Loading @@ -4481,20 +4479,19 @@ public final class ViewRootImpl implements ViewParent, final int keyCode = event.getKeyCode(); final int keyCode = event.getKeyCode(); final int metaState = event.getMetaState(); final int metaState = event.getMetaState(); KeyEvent fallbackEvent = null; synchronized (mFallbackAction) { // Check for fallback actions specified by the key character map. // Check for fallback actions specified by the key character map. if (kcm.getFallbackAction(keyCode, metaState, mFallbackAction)) { KeyCharacterMap.FallbackAction fallbackAction = int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK; kcm.getFallbackAction(keyCode, metaState); fallbackEvent = KeyEvent.obtain( if (fallbackAction != null) { final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK; KeyEvent fallbackEvent = KeyEvent.obtain( event.getDownTime(), event.getEventTime(), event.getDownTime(), event.getEventTime(), event.getAction(), mFallbackAction.keyCode, event.getAction(), fallbackAction.keyCode, event.getRepeatCount(), mFallbackAction.metaState, event.getRepeatCount(), fallbackAction.metaState, event.getDeviceId(), event.getScanCode(), event.getDeviceId(), event.getScanCode(), flags, event.getSource(), null); flags, event.getSource(), null); } fallbackAction.recycle(); } if (fallbackEvent != null) { dispatchKey(fallbackEvent); dispatchKey(fallbackEvent); } } } } Loading
include/androidfw/Input.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -262,6 +262,8 @@ public: inline int32_t getFlags() const { return mFlags; } inline int32_t getFlags() const { return mFlags; } inline void setFlags(int32_t flags) { mFlags = flags; } inline int32_t getKeyCode() const { return mKeyCode; } inline int32_t getKeyCode() const { return mKeyCode; } inline int32_t getScanCode() const { return mScanCode; } inline int32_t getScanCode() const { return mScanCode; } Loading
policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +62 −41 Original line number Original line Diff line number Diff line Loading @@ -463,8 +463,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { Intent mHomeIntent; Intent mHomeIntent; Intent mCarDockIntent; Intent mCarDockIntent; Intent mDeskDockIntent; Intent mDeskDockIntent; int mShortcutKeyPressed = -1; boolean mSearchKeyShortcutPending; boolean mConsumeShortcutKeyUp; boolean mConsumeSearchKeyUp; // support for activating the lock screen while the screen is on // support for activating the lock screen while the screen is on boolean mAllowLockscreenWhenOn; boolean mAllowLockscreenWhenOn; Loading Loading @@ -509,7 +509,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { ShortcutManager mShortcutManager; ShortcutManager mShortcutManager; PowerManager.WakeLock mBroadcastWakeLock; PowerManager.WakeLock mBroadcastWakeLock; final KeyCharacterMap.FallbackAction mFallbackAction = new KeyCharacterMap.FallbackAction(); // Fallback actions by key code. private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions = new SparseArray<KeyCharacterMap.FallbackAction>(); private static final int MSG_ENABLE_POINTER_LOCATION = 1; private static final int MSG_ENABLE_POINTER_LOCATION = 1; private static final int MSG_DISABLE_POINTER_LOCATION = 2; private static final int MSG_DISABLE_POINTER_LOCATION = 2; Loading Loading @@ -1709,7 +1711,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (false) { if (false) { Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount=" Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount=" + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed); + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed + " canceled=" + canceled); } } // If we think we might have a volume down & power key chord on the way // If we think we might have a volume down & power key chord on the way Loading Loading @@ -1842,13 +1845,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { } else if (keyCode == KeyEvent.KEYCODE_SEARCH) { } else if (keyCode == KeyEvent.KEYCODE_SEARCH) { if (down) { if (down) { if (repeatCount == 0) { if (repeatCount == 0) { mShortcutKeyPressed = keyCode; mSearchKeyShortcutPending = true; mConsumeShortcutKeyUp = false; mConsumeSearchKeyUp = false; } } } else if (keyCode == mShortcutKeyPressed) { } else { mShortcutKeyPressed = -1; mSearchKeyShortcutPending = false; if (mConsumeShortcutKeyUp) { if (mConsumeSearchKeyUp) { mConsumeShortcutKeyUp = false; mConsumeSearchKeyUp = false; return -1; return -1; } } } } Loading @@ -1865,10 +1868,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { // even if no shortcut was invoked. This prevents text from being // even if no shortcut was invoked. This prevents text from being // inadvertently inserted when using a keyboard that has built-in macro // inadvertently inserted when using a keyboard that has built-in macro // shortcut keys (that emit Search+x) and some of them are not registered. // shortcut keys (that emit Search+x) and some of them are not registered. if (mShortcutKeyPressed != -1) { if (mSearchKeyShortcutPending) { final KeyCharacterMap kcm = event.getKeyCharacterMap(); final KeyCharacterMap kcm = event.getKeyCharacterMap(); if (kcm.isPrintingKey(keyCode)) { if (kcm.isPrintingKey(keyCode)) { mConsumeShortcutKeyUp = true; mConsumeSearchKeyUp = true; mSearchKeyShortcutPending = false; if (down && repeatCount == 0 && !keyguardOn) { if (down && repeatCount == 0 && !keyguardOn) { Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState); Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState); if (shortcutIntent != null) { if (shortcutIntent != null) { Loading @@ -1878,13 +1882,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { } catch (ActivityNotFoundException ex) { } catch (ActivityNotFoundException ex) { Slog.w(TAG, "Dropping shortcut key combination because " Slog.w(TAG, "Dropping shortcut key combination because " + "the activity to which it is registered was not found: " + "the activity to which it is registered was not found: " + KeyEvent.keyCodeToString(mShortcutKeyPressed) + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex); + "+" + KeyEvent.keyCodeToString(keyCode), ex); } } } else { } else { Slog.i(TAG, "Dropping unregistered shortcut key combination: " Slog.i(TAG, "Dropping unregistered shortcut key combination: " + KeyEvent.keyCodeToString(mShortcutKeyPressed) + "SEARCH+" + KeyEvent.keyCodeToString(keyCode)); + "+" + KeyEvent.keyCodeToString(keyCode)); } } } } return -1; return -1; Loading Loading @@ -1964,51 +1966,70 @@ public class PhoneWindowManager implements WindowManagerPolicy { + ", policyFlags=" + policyFlags); + ", policyFlags=" + policyFlags); } } KeyEvent fallbackEvent = null; if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { final KeyCharacterMap kcm = event.getKeyCharacterMap(); final KeyCharacterMap kcm = event.getKeyCharacterMap(); final int keyCode = event.getKeyCode(); final int keyCode = event.getKeyCode(); final int metaState = event.getMetaState(); final int metaState = event.getMetaState(); final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0; // Check for fallback actions specified by the key character map. // Check for fallback actions specified by the key character map. if (getFallbackAction(kcm, keyCode, metaState, mFallbackAction)) { final FallbackAction fallbackAction; if (initialDown) { fallbackAction = kcm.getFallbackAction(keyCode, metaState); } else { fallbackAction = mFallbackActions.get(keyCode); } if (fallbackAction != null) { if (DEBUG_FALLBACK) { if (DEBUG_FALLBACK) { Slog.d(TAG, "Fallback: keyCode=" + mFallbackAction.keyCode Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode + " metaState=" + Integer.toHexString(mFallbackAction.metaState)); + " metaState=" + Integer.toHexString(fallbackAction.metaState)); } } int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK; final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK; KeyEvent fallbackEvent = KeyEvent.obtain( fallbackEvent = KeyEvent.obtain( event.getDownTime(), event.getEventTime(), event.getDownTime(), event.getEventTime(), event.getAction(), mFallbackAction.keyCode, event.getAction(), fallbackAction.keyCode, event.getRepeatCount(), mFallbackAction.metaState, event.getRepeatCount(), fallbackAction.metaState, event.getDeviceId(), event.getScanCode(), event.getDeviceId(), event.getScanCode(), flags, event.getSource(), null); flags, event.getSource(), null); int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true); if ((actions & ACTION_PASS_TO_USER) != 0) { if (!interceptFallback(win, fallbackEvent, policyFlags)) { long delayMillis = interceptKeyBeforeDispatching( fallbackEvent.recycle(); win, fallbackEvent, policyFlags); fallbackEvent = null; if (delayMillis == 0) { if (DEBUG_FALLBACK) { Slog.d(TAG, "Performing fallback."); } } return fallbackEvent; if (initialDown) { mFallbackActions.put(keyCode, fallbackAction); } else if (event.getAction() == KeyEvent.ACTION_UP) { mFallbackActions.remove(keyCode); fallbackAction.recycle(); } } } } fallbackEvent.recycle(); } } } if (DEBUG_FALLBACK) { if (DEBUG_FALLBACK) { if (fallbackEvent == null) { Slog.d(TAG, "No fallback."); Slog.d(TAG, "No fallback."); } else { Slog.d(TAG, "Performing fallback: " + fallbackEvent); } } return null; } return fallbackEvent; } } private boolean getFallbackAction(KeyCharacterMap kcm, int keyCode, int metaState, private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) { FallbackAction outFallbackAction) { int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true); // Consult the key character map for specific fallback actions. if ((actions & ACTION_PASS_TO_USER) != 0) { // For example, map NUMPAD_1 to MOVE_HOME when NUMLOCK is not pressed. long delayMillis = interceptKeyBeforeDispatching( return kcm.getFallbackAction(keyCode, metaState, outFallbackAction); win, fallbackEvent, policyFlags); if (delayMillis == 0) { return true; } } return false; } } /** /** Loading
services/input/InputDispatcher.cpp +32 −8 Original line number Original line Diff line number Diff line Loading @@ -3354,6 +3354,25 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& con // generated a fallback or if the window is not a foreground window, // generated a fallback or if the window is not a foreground window, // then cancel the associated fallback key, if any. // then cancel the associated fallback key, if any. if (fallbackKeyCode != -1) { if (fallbackKeyCode != -1) { // Dispatch the unhandled key to the policy with the cancel flag. #if DEBUG_OUTBOUND_EVENT_DETAILS ALOGD("Unhandled key event: Asking policy to cancel fallback action. " "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x", keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount, keyEntry->policyFlags); #endif KeyEvent event; initializeKeyEvent(&event, keyEntry); event.setFlags(event.getFlags() | AKEY_EVENT_FLAG_CANCELED); mLock.unlock(); mPolicy->dispatchUnhandledKey(connection->inputWindowHandle, &event, keyEntry->policyFlags, &event); mLock.lock(); // Cancel the fallback key. if (fallbackKeyCode != AKEYCODE_UNKNOWN) { if (fallbackKeyCode != AKEYCODE_UNKNOWN) { CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS, CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS, "application handled the original non-fallback key " "application handled the original non-fallback key " Loading @@ -3374,8 +3393,9 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& con #if DEBUG_OUTBOUND_EVENT_DETAILS #if DEBUG_OUTBOUND_EVENT_DETAILS ALOGD("Unhandled key event: Skipping unhandled key event processing " ALOGD("Unhandled key event: Skipping unhandled key event processing " "since this is not an initial down. " "since this is not an initial down. " "keyCode=%d, action=%d, repeatCount=%d", "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x", originalKeyCode, keyEntry->action, keyEntry->repeatCount); originalKeyCode, keyEntry->action, keyEntry->repeatCount, keyEntry->policyFlags); #endif #endif return false; return false; } } Loading @@ -3383,8 +3403,9 @@ bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& con // Dispatch the unhandled key to the policy. // Dispatch the unhandled key to the policy. #if DEBUG_OUTBOUND_EVENT_DETAILS #if DEBUG_OUTBOUND_EVENT_DETAILS ALOGD("Unhandled key event: Asking policy to perform fallback action. " ALOGD("Unhandled key event: Asking policy to perform fallback action. " "keyCode=%d, action=%d, repeatCount=%d", "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x", keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount); keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount, keyEntry->policyFlags); #endif #endif KeyEvent event; KeyEvent event; initializeKeyEvent(&event, keyEntry); initializeKeyEvent(&event, keyEntry); Loading Loading @@ -3903,8 +3924,10 @@ void InputDispatcher::InputState::addKeyMemento(const KeyEntry* entry, int32_t f memento.source = entry->source; memento.source = entry->source; memento.keyCode = entry->keyCode; memento.keyCode = entry->keyCode; memento.scanCode = entry->scanCode; memento.scanCode = entry->scanCode; memento.metaState = entry->metaState; memento.flags = flags; memento.flags = flags; memento.downTime = entry->downTime; memento.downTime = entry->downTime; memento.policyFlags = entry->policyFlags; } } void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry, void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry, Loading @@ -3919,6 +3942,7 @@ void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry, memento.downTime = entry->downTime; memento.downTime = entry->downTime; memento.setPointers(entry); memento.setPointers(entry); memento.hovering = hovering; memento.hovering = hovering; memento.policyFlags = entry->policyFlags; } } void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) { void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) { Loading @@ -3935,9 +3959,9 @@ void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTim const KeyMemento& memento = mKeyMementos.itemAt(i); const KeyMemento& memento = mKeyMementos.itemAt(i); if (shouldCancelKey(memento, options)) { if (shouldCancelKey(memento, options)) { outEvents.push(new KeyEntry(currentTime, outEvents.push(new KeyEntry(currentTime, memento.deviceId, memento.source, 0, memento.deviceId, memento.source, memento.policyFlags, AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED, AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED, memento.keyCode, memento.scanCode, 0, 0, memento.downTime)); memento.keyCode, memento.scanCode, memento.metaState, 0, memento.downTime)); } } } } Loading @@ -3945,7 +3969,7 @@ void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTim const MotionMemento& memento = mMotionMementos.itemAt(i); const MotionMemento& memento = mMotionMementos.itemAt(i); if (shouldCancelMotion(memento, options)) { if (shouldCancelMotion(memento, options)) { outEvents.push(new MotionEntry(currentTime, outEvents.push(new MotionEntry(currentTime, memento.deviceId, memento.source, 0, memento.deviceId, memento.source, memento.policyFlags, memento.hovering memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT ? AMOTION_EVENT_ACTION_HOVER_EXIT : AMOTION_EVENT_ACTION_CANCEL, : AMOTION_EVENT_ACTION_CANCEL, Loading