am c4db5ece: am 8e0c88ea: Merge "servicemanager: log pid and uid on selinux denial"

* commit 'c4db5ece1b34ada975041c167215d41a58f788ca':
  servicemanager: log pid and uid on selinux denial
diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h
index 111139b..eb5840e 100644
--- a/include/input/KeyCharacterMap.h
+++ b/include/input/KeyCharacterMap.h
@@ -124,6 +124,11 @@
      * the mapping in some way. */
     status_t mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const;
 
+    /* Tries to find a replacement key code for a given key code and meta state
+     * in character map. */
+    void tryRemapKey(int32_t scanCode, int32_t metaState,
+            int32_t* outKeyCode, int32_t* outMetaState) const;
+
 #ifdef __ANDROID__
     /* Reads a key map from a parcel. */
     static sp<KeyCharacterMap> readFromParcel(Parcel* parcel);
@@ -151,6 +156,9 @@
 
         /* The fallback keycode if the key is not handled. */
         int32_t fallbackKeyCode;
+
+        /* The replacement keycode if the key has to be replaced outright. */
+        int32_t replacementKeyCode;
     };
 
     struct Key {
diff --git a/include/input/Keyboard.h b/include/input/Keyboard.h
index 519bb22..d4903e9 100644
--- a/include/input/Keyboard.h
+++ b/include/input/Keyboard.h
@@ -88,6 +88,13 @@
 extern int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState);
 
 /**
+ * Normalizes the meta state such that if either the left or right modifier
+ * meta state bits are set then the result will also include the universal
+ * bit for that modifier.
+ */
+extern int32_t normalizeMetaState(int32_t oldMetaState);
+
+/**
  * Returns true if a key is a meta key like ALT or CAPS_LOCK.
  */
 extern bool isMetaKey(int32_t keyCode);
diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp
index 732ebd0..dd01a93 100644
--- a/libs/input/KeyCharacterMap.cpp
+++ b/libs/input/KeyCharacterMap.cpp
@@ -332,33 +332,75 @@
     if (usageCode) {
         ssize_t index = mKeysByUsageCode.indexOfKey(usageCode);
         if (index >= 0) {
-#if DEBUG_MAPPING
-    ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
-            scanCode, usageCode, *outKeyCode);
-#endif
             *outKeyCode = mKeysByUsageCode.valueAt(index);
+#if DEBUG_MAPPING
+            ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
+                    scanCode, usageCode, *outKeyCode);
+#endif
             return OK;
         }
     }
     if (scanCode) {
         ssize_t index = mKeysByScanCode.indexOfKey(scanCode);
         if (index >= 0) {
-#if DEBUG_MAPPING
-    ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
-            scanCode, usageCode, *outKeyCode);
-#endif
             *outKeyCode = mKeysByScanCode.valueAt(index);
+#if DEBUG_MAPPING
+            ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
+                    scanCode, usageCode, *outKeyCode);
+#endif
             return OK;
         }
     }
 
 #if DEBUG_MAPPING
-        ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Failed.", scanCode, usageCode);
+    ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Failed.", scanCode, usageCode);
 #endif
     *outKeyCode = AKEYCODE_UNKNOWN;
     return NAME_NOT_FOUND;
 }
 
+void KeyCharacterMap::tryRemapKey(int32_t keyCode, int32_t metaState,
+                                  int32_t *outKeyCode, int32_t *outMetaState) const {
+    *outKeyCode = keyCode;
+    *outMetaState = metaState;
+
+    const Key* key;
+    const Behavior* behavior;
+    if (getKeyBehavior(keyCode, metaState, &key, &behavior)) {
+        if (behavior->replacementKeyCode) {
+            *outKeyCode = behavior->replacementKeyCode;
+            int32_t newMetaState = metaState & ~behavior->metaState;
+            // Reset dependent meta states.
+            if (behavior->metaState & AMETA_ALT_ON) {
+                newMetaState &= ~(AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON);
+            }
+            if (behavior->metaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
+                newMetaState &= ~AMETA_ALT_ON;
+            }
+            if (behavior->metaState & AMETA_CTRL_ON) {
+                newMetaState &= ~(AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON);
+            }
+            if (behavior->metaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) {
+                newMetaState &= ~AMETA_CTRL_ON;
+            }
+            if (behavior->metaState & AMETA_SHIFT_ON) {
+                newMetaState &= ~(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON);
+            }
+            if (behavior->metaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
+                newMetaState &= ~AMETA_SHIFT_ON;
+            }
+            // ... and put universal bits back if needed
+            *outMetaState = normalizeMetaState(newMetaState);
+        }
+    }
+
+#if DEBUG_MAPPING
+    ALOGD("tryRemapKey: keyCode=%d, metaState=0x%08x ~ "
+            "replacement keyCode=%d, replacement metaState=0x%08x.",
+            keyCode, metaState, *outKeyCode, *outMetaState);
+#endif
+}
+
 bool KeyCharacterMap::getKey(int32_t keyCode, const Key** outKey) const {
     ssize_t index = mKeys.indexOfKey(keyCode);
     if (index >= 0) {
@@ -584,6 +626,7 @@
             int32_t metaState = parcel->readInt32();
             char16_t character = parcel->readInt32();
             int32_t fallbackKeyCode = parcel->readInt32();
+            int32_t replacementKeyCode = parcel->readInt32();
             if (parcel->errorCheck()) {
                 return NULL;
             }
@@ -592,6 +635,7 @@
             behavior->metaState = metaState;
             behavior->character = character;
             behavior->fallbackKeyCode = fallbackKeyCode;
+            behavior->replacementKeyCode = replacementKeyCode;
             if (lastBehavior) {
                 lastBehavior->next = behavior;
             } else {
@@ -624,6 +668,7 @@
             parcel->writeInt32(behavior->metaState);
             parcel->writeInt32(behavior->character);
             parcel->writeInt32(behavior->fallbackKeyCode);
+            parcel->writeInt32(behavior->replacementKeyCode);
         }
         parcel->writeInt32(0);
     }
@@ -655,13 +700,14 @@
 // --- KeyCharacterMap::Behavior ---
 
 KeyCharacterMap::Behavior::Behavior() :
-        next(NULL), metaState(0), character(0), fallbackKeyCode(0) {
+        next(NULL), metaState(0), character(0), fallbackKeyCode(0), replacementKeyCode(0) {
 }
 
 KeyCharacterMap::Behavior::Behavior(const Behavior& other) :
         next(other.next ? new Behavior(*other.next) : NULL),
         metaState(other.metaState), character(other.character),
-        fallbackKeyCode(other.fallbackKeyCode) {
+        fallbackKeyCode(other.fallbackKeyCode),
+        replacementKeyCode(other.replacementKeyCode) {
 }
 
 
@@ -923,6 +969,7 @@
     Behavior behavior;
     bool haveCharacter = false;
     bool haveFallback = false;
+    bool haveReplacement = false;
 
     do {
         char ch = mTokenizer->peekChar();
@@ -939,6 +986,11 @@
                         mTokenizer->getLocation().string());
                 return BAD_VALUE;
             }
+            if (haveReplacement) {
+                ALOGE("%s: Cannot combine character literal with replace action.",
+                        mTokenizer->getLocation().string());
+                return BAD_VALUE;
+            }
             behavior.character = character;
             haveCharacter = true;
         } else {
@@ -949,6 +1001,11 @@
                             mTokenizer->getLocation().string());
                     return BAD_VALUE;
                 }
+                if (haveReplacement) {
+                    ALOGE("%s: Cannot combine 'none' with replace action.",
+                            mTokenizer->getLocation().string());
+                    return BAD_VALUE;
+                }
                 haveCharacter = true;
             } else if (token == "fallback") {
                 mTokenizer->skipDelimiters(WHITESPACE);
@@ -960,13 +1017,36 @@
                             token.string());
                     return BAD_VALUE;
                 }
-                if (haveFallback) {
-                    ALOGE("%s: Cannot combine multiple fallback key codes.",
+                if (haveFallback || haveReplacement) {
+                    ALOGE("%s: Cannot combine multiple fallback/replacement key codes.",
                             mTokenizer->getLocation().string());
                     return BAD_VALUE;
                 }
                 behavior.fallbackKeyCode = keyCode;
                 haveFallback = true;
+            } else if (token == "replace") {
+                mTokenizer->skipDelimiters(WHITESPACE);
+                token = mTokenizer->nextToken(WHITESPACE);
+                int32_t keyCode = getKeyCodeByLabel(token.string());
+                if (!keyCode) {
+                    ALOGE("%s: Invalid key code label for replace, got '%s'.",
+                            mTokenizer->getLocation().string(),
+                            token.string());
+                    return BAD_VALUE;
+                }
+                if (haveCharacter) {
+                    ALOGE("%s: Cannot combine character literal with replace action.",
+                            mTokenizer->getLocation().string());
+                    return BAD_VALUE;
+                }
+                if (haveFallback || haveReplacement) {
+                    ALOGE("%s: Cannot combine multiple fallback/replacement key codes.",
+                            mTokenizer->getLocation().string());
+                    return BAD_VALUE;
+                }
+                behavior.replacementKeyCode = keyCode;
+                haveReplacement = true;
+
             } else {
                 ALOGE("%s: Expected a key behavior after ':'.",
                         mTokenizer->getLocation().string());
@@ -1016,8 +1096,10 @@
             newBehavior->next = key->firstBehavior;
             key->firstBehavior = newBehavior;
 #if DEBUG_PARSER
-            ALOGD("Parsed key meta: keyCode=%d, meta=0x%x, char=%d, fallback=%d.", mKeyCode,
-                    newBehavior->metaState, newBehavior->character, newBehavior->fallbackKeyCode);
+            ALOGD("Parsed key meta: keyCode=%d, meta=0x%x, char=%d, fallback=%d replace=%d.",
+                    mKeyCode,
+                    newBehavior->metaState, newBehavior->character,
+                    newBehavior->fallbackKeyCode, newBehavior->replacementKeyCode);
 #endif
             break;
         }
diff --git a/libs/input/Keyboard.cpp b/libs/input/Keyboard.cpp
index f4d9507..9a01395 100644
--- a/libs/input/Keyboard.cpp
+++ b/libs/input/Keyboard.cpp
@@ -176,6 +176,11 @@
                 ~(mask | AMETA_ALT_ON | AMETA_SHIFT_ON | AMETA_CTRL_ON | AMETA_META_ON);
     }
 
+    return normalizeMetaState(newMetaState);
+}
+
+int32_t normalizeMetaState(int32_t oldMetaState) {
+    int32_t newMetaState = oldMetaState;
     if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
         newMetaState |= AMETA_ALT_ON;
     }
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index 6b60c7c..5859606 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -438,10 +438,12 @@
     return false;
 }
 
-status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
-        int32_t* outKeycode, uint32_t* outFlags) const {
+status_t EventHub::mapKey(int32_t deviceId,
+        int32_t scanCode, int32_t usageCode, int32_t metaState,
+        int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const {
     AutoMutex _l(mLock);
     Device* device = getDeviceLocked(deviceId);
+    status_t status = NAME_NOT_FOUND;
 
     if (device) {
         // Check the key character map first.
@@ -449,22 +451,34 @@
         if (kcm != NULL) {
             if (!kcm->mapKey(scanCode, usageCode, outKeycode)) {
                 *outFlags = 0;
-                return NO_ERROR;
+                status = NO_ERROR;
             }
         }
 
         // Check the key layout next.
-        if (device->keyMap.haveKeyLayout()) {
+        if (status != NO_ERROR && device->keyMap.haveKeyLayout()) {
             if (!device->keyMap.keyLayoutMap->mapKey(
                     scanCode, usageCode, outKeycode, outFlags)) {
-                return NO_ERROR;
+                status = NO_ERROR;
+            }
+        }
+
+        if (status == NO_ERROR) {
+            if (kcm != NULL) {
+                kcm->tryRemapKey(*outKeycode, metaState, outKeycode, outMetaState);
+            } else {
+                *outMetaState = metaState;
             }
         }
     }
 
-    *outKeycode = 0;
-    *outFlags = 0;
-    return NAME_NOT_FOUND;
+    if (status != NO_ERROR) {
+        *outKeycode = 0;
+        *outFlags = 0;
+        *outMetaState = metaState;
+    }
+
+    return status;
 }
 
 status_t EventHub::mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const {
diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/EventHub.h
index 3ec4910..0f94c77 100644
--- a/services/inputflinger/EventHub.h
+++ b/services/inputflinger/EventHub.h
@@ -197,8 +197,9 @@
 
     virtual bool hasInputProperty(int32_t deviceId, int property) const = 0;
 
-    virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
-            int32_t* outKeycode, uint32_t* outFlags) const = 0;
+    virtual status_t mapKey(int32_t deviceId,
+            int32_t scanCode, int32_t usageCode, int32_t metaState,
+            int32_t* outKeycode, int32_t *outMetaState, uint32_t* outFlags) const = 0;
 
     virtual status_t mapAxis(int32_t deviceId, int32_t scanCode,
             AxisInfo* outAxisInfo) const = 0;
@@ -285,8 +286,9 @@
 
     virtual bool hasInputProperty(int32_t deviceId, int property) const;
 
-    virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
-            int32_t* outKeycode, uint32_t* outFlags) const;
+    virtual status_t mapKey(int32_t deviceId,
+            int32_t scanCode, int32_t usageCode, int32_t metaState,
+            int32_t* outKeycode, int32_t *outMetaState, uint32_t* outFlags) const;
 
     virtual status_t mapAxis(int32_t deviceId, int32_t scanCode,
             AxisInfo* outAxisInfo) const;
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 36095bf..b2cbfe8 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -2177,13 +2177,7 @@
         mCurrentHidUsage = 0;
 
         if (isKeyboardOrGamepadKey(scanCode)) {
-            int32_t keyCode;
-            uint32_t flags;
-            if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) {
-                keyCode = AKEYCODE_UNKNOWN;
-                flags = 0;
-            }
-            processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
+            processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode);
         }
         break;
     }
@@ -2208,8 +2202,18 @@
         || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
 }
 
-void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
-        int32_t scanCode, uint32_t policyFlags) {
+void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode,
+        int32_t usageCode) {
+    int32_t keyCode;
+    int32_t keyMetaState;
+    uint32_t policyFlags;
+
+    if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, mMetaState,
+                              &keyCode, &keyMetaState, &policyFlags)) {
+        keyCode = AKEYCODE_UNKNOWN;
+        keyMetaState = mMetaState;
+        policyFlags = 0;
+    }
 
     if (down) {
         // Rotate key codes according to orientation if needed.
@@ -2262,6 +2266,12 @@
     if (metaStateChanged) {
         mMetaState = newMetaState;
         updateLedState(false);
+
+        // If global meta state changed send it along with the key.
+        // If it has not changed then we'll use what keymap gave us,
+        // since key replacement logic might temporarily reset a few
+        // meta bits for given key.
+        keyMetaState = newMetaState;
     }
 
     nsecs_t downTime = mDownTime;
@@ -2289,7 +2299,7 @@
 
     NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
             down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
-            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
+            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
     getListener()->notifyKey(&args);
 }
 
@@ -3543,8 +3553,10 @@
 
         virtualKey.scanCode = virtualKeyDefinition.scanCode;
         int32_t keyCode;
+        int32_t dummyKeyMetaState;
         uint32_t flags;
-        if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, 0, &keyCode, &flags)) {
+        if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, 0, 0,
+                                  &keyCode, &dummyKeyMetaState, &flags)) {
             ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
                     virtualKey.scanCode);
             mVirtualKeys.pop(); // drop the key
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index 7cb4680..30c84b1 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -1154,8 +1154,7 @@
 
     bool isKeyboardOrGamepadKey(int32_t scanCode);
 
-    void processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode,
-            uint32_t policyFlags);
+    void processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode);
 
     ssize_t findKeyDown(int32_t scanCode);
 
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index f34b810..42bc865 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -518,8 +518,9 @@
         return false;
     }
 
-    virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
-            int32_t* outKeycode, uint32_t* outFlags) const {
+    virtual status_t mapKey(int32_t deviceId,
+            int32_t scanCode, int32_t usageCode, int32_t metaState,
+            int32_t* outKeycode, int32_t *outMetaState, uint32_t* outFlags) const {
         Device* device = getDevice(deviceId);
         if (device) {
             const KeyInfo* key = getKey(device, scanCode, usageCode);
@@ -530,6 +531,9 @@
                 if (outFlags) {
                     *outFlags = key->flags;
                 }
+                if (outMetaState) {
+                    *outMetaState = metaState;
+                }
                 return OK;
             }
         }