Improve shortcut handling.

Shortcut keys invoked using Meta are handled as fallback actions instead
so applications can handle Meta however they like.

Change-Id: I28955bac5bba9a399eed2fc6c9b73bba3f4bf383
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index e61dd6c..79bf9d0 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -1344,11 +1344,11 @@
             return true;
         }
         
-        // Shortcuts are invoked through Search+key or Meta+key, so intercept those here
-        if ((mShortcutKeyPressed != -1 && !mConsumeShortcutKeyUp)
-                || (metaState & KeyEvent.META_META_ON) != 0) {
+        // Shortcuts are invoked through Search+key, so intercept those here
+        if (mShortcutKeyPressed != -1 && !mConsumeShortcutKeyUp) {
             if (down && repeatCount == 0 && !keyguardOn) {
-                Intent shortcutIntent = mShortcutManager.getIntent(event);
+                final KeyCharacterMap kcm = event.getKeyCharacterMap();
+                Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
                 if (shortcutIntent != null) {
                     shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                     mContext.startActivity(shortcutIntent);
@@ -1382,11 +1382,23 @@
         }
 
         if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
+            // Invoke shortcuts using Meta as a fallback.
             final KeyCharacterMap kcm = event.getKeyCharacterMap();
-            boolean fallback = kcm.getFallbackAction(event.getKeyCode(), event.getMetaState(),
-                    mFallbackAction);
+            final int keyCode = event.getKeyCode();
+            final int metaState = event.getMetaState();
+            if ((metaState & KeyEvent.META_META_ON) != 0) {
+                Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
+                        metaState & ~(KeyEvent.META_META_ON
+                                | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
+                if (shortcutIntent != null) {
+                    shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                    mContext.startActivity(shortcutIntent);
+                    return null;
+                }
+            }
 
-            if (fallback) {
+            // Check for fallback actions.
+            if (kcm.getFallbackAction(keyCode, metaState, mFallbackAction)) {
                 if (DEBUG_FALLBACK) {
                     Slog.d(TAG, "Fallback: keyCode=" + mFallbackAction.keyCode
                             + " metaState=" + Integer.toHexString(mFallbackAction.metaState));
diff --git a/policy/src/com/android/internal/policy/impl/ShortcutManager.java b/policy/src/com/android/internal/policy/impl/ShortcutManager.java
index fc66a20..75a1b01 100644
--- a/policy/src/com/android/internal/policy/impl/ShortcutManager.java
+++ b/policy/src/com/android/internal/policy/impl/ShortcutManager.java
@@ -101,18 +101,30 @@
      * This will first try an exact match (with modifiers), and then try a
      * match without modifiers (primary character on a key).
      * 
-     * @param event The key event of the key that was pressed.
+     * @param kcm The key character map of the device on which the key was pressed.
+     * @param keyCode The key code.
+     * @param metaState The meta state, omitting any modifiers that were used
+     * to invoke the shortcut.
      * @return The intent that matches the shortcut, or null if not found.
      */
-    public Intent getIntent(KeyEvent event) {
-        // First try the exact keycode (with modifiers)
-        int shortcut = event.getUnicodeChar();
-        Intent intent = shortcut != 0 ? mShortcutIntents.get(shortcut) : null; 
-        if (intent != null) return intent;
+    public Intent getIntent(KeyCharacterMap kcm, int keyCode, int metaState) {
+        Intent intent = null;
 
-        // Next try the keycode without modifiers (the primary character on that key)
-        shortcut = Character.toLowerCase(event.getUnicodeChar(0));
-        return shortcut != 0 ? mShortcutIntents.get(shortcut) : null;
+        // First try the exact keycode (with modifiers).
+        int shortcut = kcm.get(keyCode, metaState);
+        if (shortcut != 0) {
+            intent = mShortcutIntents.get(shortcut);
+        }
+
+        // Next try the primary character on that key.
+        if (intent == null) {
+            shortcut = Character.toLowerCase(kcm.getDisplayLabel(keyCode));
+            if (shortcut != 0) {
+                intent = mShortcutIntents.get(shortcut);
+            }
+        }
+
+        return intent;
     }
 
 }