Revert "Revert "Add system accelerators for BACK and HOME.""

This reverts commit d671f98a27f547ebcddff8dc962fe895549355e2.

Change-Id: Ibec48f81653bd2f755fc59a241fa7836baf53233
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index a750a3d..ce14f99 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -2366,9 +2366,38 @@
 
     policyFlags |= POLICY_FLAG_TRUSTED;
 
+    int32_t keyCode = args->keyCode;
+    if (metaState & AMETA_META_ON && args->action == AKEY_EVENT_ACTION_DOWN) {
+        int32_t newKeyCode = AKEYCODE_UNKNOWN;
+        if (keyCode == AKEYCODE_DEL) {
+            newKeyCode = AKEYCODE_BACK;
+        } else if (keyCode == AKEYCODE_ENTER) {
+            newKeyCode = AKEYCODE_HOME;
+        }
+        if (newKeyCode != AKEYCODE_UNKNOWN) {
+            AutoMutex _l(mLock);
+            struct KeyReplacement replacement = {keyCode, args->deviceId};
+            mReplacedKeys.add(replacement, newKeyCode);
+            keyCode = newKeyCode;
+            metaState &= ~AMETA_META_ON;
+        }
+    } else if (args->action == AKEY_EVENT_ACTION_UP) {
+        // In order to maintain a consistent stream of up and down events, check to see if the key
+        // going up is one we've replaced in a down event and haven't yet replaced in an up event,
+        // even if the modifier was released between the down and the up events.
+        AutoMutex _l(mLock);
+        struct KeyReplacement replacement = {keyCode, args->deviceId};
+        ssize_t index = mReplacedKeys.indexOfKey(replacement);
+        if (index >= 0) {
+            keyCode = mReplacedKeys.valueAt(index);
+            mReplacedKeys.removeItemsAt(index);
+            metaState &= ~AMETA_META_ON;
+        }
+    }
+
     KeyEvent event;
     event.initialize(args->deviceId, args->source, args->action,
-            flags, args->keyCode, args->scanCode, metaState, 0,
+            flags, keyCode, args->scanCode, metaState, 0,
             args->downTime, args->eventTime);
 
     mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
@@ -2391,7 +2420,7 @@
         int32_t repeatCount = 0;
         KeyEntry* newEntry = new KeyEntry(args->eventTime,
                 args->deviceId, args->source, policyFlags,
-                args->action, flags, args->keyCode, args->scanCode,
+                args->action, flags, keyCode, args->scanCode,
                 metaState, repeatCount, args->downTime);
 
         needWake = enqueueInboundEventLocked(newEntry);
@@ -3050,6 +3079,7 @@
 
     mTouchStatesByDisplay.clear();
     mLastHoverWindowHandle.clear();
+    mReplacedKeys.clear();
 }
 
 void InputDispatcher::logDispatchStateLocked() {
@@ -3188,6 +3218,18 @@
         dump.append(INDENT "InboundQueue: <empty>\n");
     }
 
+    if (!mReplacedKeys.isEmpty()) {
+        dump.append(INDENT "ReplacedKeys:\n");
+        for (size_t i = 0; i < mReplacedKeys.size(); i++) {
+            const KeyReplacement& replacement = mReplacedKeys.keyAt(i);
+            int32_t newKeyCode = mReplacedKeys.valueAt(i);
+            dump.appendFormat(INDENT2 "%zu: originalKeyCode=%d, deviceId=%d, newKeyCode=%d\n",
+                    i, replacement.keyCode, replacement.deviceId, newKeyCode);
+        }
+    } else {
+        dump.append(INDENT "ReplacedKeys: <empty>\n");
+    }
+
     if (!mConnectionsByFd.isEmpty()) {
         dump.append(INDENT "Connections:\n");
         for (size_t i = 0; i < mConnectionsByFd.size(); i++) {