Support 180-degree screen rotation for Stem Buttons.

Bug: 17961466
Change-Id: I1892db400724bb80fb92bdf0e2cbaf3102dd7c80
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 97565aa..dae7879 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -147,7 +147,33 @@
 static const size_t keyCodeRotationMapSize =
         sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
 
+static int32_t rotateStemKey(int32_t value, int32_t orientation,
+        const int32_t map[][2], size_t mapSize) {
+    if (orientation == DISPLAY_ORIENTATION_180) {
+        for (size_t i = 0; i < mapSize; i++) {
+            if (value == map[i][0]) {
+                return map[i][1];
+            }
+        }
+    }
+    return value;
+}
+
+// The mapping can be defined using input device configuration properties keyboard.rotated.stem_X
+static int32_t stemKeyRotationMap[][2] = {
+        // key codes enumerated with the original (unrotated) key first
+        // no rotation,           180 degree rotation
+        { AKEYCODE_STEM_PRIMARY, AKEYCODE_STEM_PRIMARY },
+        { AKEYCODE_STEM_1,       AKEYCODE_STEM_1 },
+        { AKEYCODE_STEM_2,       AKEYCODE_STEM_2 },
+        { AKEYCODE_STEM_3,       AKEYCODE_STEM_3 },
+};
+static const size_t stemKeyRotationMapSize =
+        sizeof(stemKeyRotationMap) / sizeof(stemKeyRotationMap[0]);
+
 static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
+    keyCode = rotateStemKey(keyCode, orientation,
+            stemKeyRotationMap, stemKeyRotationMapSize);
     return rotateValueUsingRotationMap(keyCode, orientation,
             keyCodeRotationMap, keyCodeRotationMapSize);
 }
@@ -2260,18 +2286,36 @@
     }
 }
 
+static void mapStemKey(int32_t keyCode, const PropertyMap& config, char const *property) {
+    int32_t mapped = 0;
+    if (config.tryGetProperty(String8(property), mapped) && mapped > 0) {
+        for (size_t i = 0; i < stemKeyRotationMapSize; i++) {
+            if (stemKeyRotationMap[i][0] == keyCode) {
+                stemKeyRotationMap[i][1] = mapped;
+                return;
+            }
+        }
+    }
+}
+
 void KeyboardInputMapper::configureParameters() {
     mParameters.orientationAware = false;
-    getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
+    const PropertyMap& config = getDevice()->getConfiguration();
+    config.tryGetProperty(String8("keyboard.orientationAware"),
             mParameters.orientationAware);
 
     mParameters.hasAssociatedDisplay = false;
     if (mParameters.orientationAware) {
         mParameters.hasAssociatedDisplay = true;
+
+        mapStemKey(AKEYCODE_STEM_PRIMARY, config, "keyboard.rotated.stem_primary");
+        mapStemKey(AKEYCODE_STEM_1, config, "keyboard.rotated.stem_1");
+        mapStemKey(AKEYCODE_STEM_2, config, "keyboard.rotated.stem_2");
+        mapStemKey(AKEYCODE_STEM_3, config, "keyboard.rotated.stem_3");
     }
 
     mParameters.handlesKeyRepeat = false;
-    getDevice()->getConfiguration().tryGetProperty(String8("keyboard.handlesKeyRepeat"),
+    config.tryGetProperty(String8("keyboard.handlesKeyRepeat"),
             mParameters.handlesKeyRepeat);
 }