Merge "Set DATA_INJECTION mode flag for sensors." into mnc-dr-dev
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 9def406..26c5b4a 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -264,9 +264,27 @@
 static void writeClockSyncMarker()
 {
   char buffer[128];
+  int len = 0;
+  int fd = open(k_traceMarkerPath, O_WRONLY);
+  if (fd == -1) {
+      fprintf(stderr, "error opening %s: %s (%d)\n", k_traceMarkerPath,
+              strerror(errno), errno);
+      return;
+  }
   float now_in_seconds = systemTime(CLOCK_MONOTONIC) / 1000000000.0f;
-  snprintf(buffer, 128, "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds);
-  writeStr(k_traceMarkerPath, buffer);
+
+  len = snprintf(buffer, 128, "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds);
+  if (write(fd, buffer, len) != len) {
+      fprintf(stderr, "error writing clock sync marker %s (%d)\n", strerror(errno), errno);
+  }
+
+  int64_t realtime_in_ms = systemTime(CLOCK_REALTIME) / 1000000;
+  len = snprintf(buffer, 128, "trace_event_clock_sync: realtime_ts=%" PRId64 "\n", realtime_in_ms);
+  if (write(fd, buffer, len) != len) {
+      fprintf(stderr, "error writing clock sync marker %s (%d)\n", strerror(errno), errno);
+  }
+
+  close(fd);
 }
 
 // Enable or disable a kernel option by writing a "1" or a "0" into a /sys
@@ -646,7 +664,6 @@
 // Disable tracing in the kernel.
 static void stopTrace()
 {
-    writeClockSyncMarker();
     setTracingEnabled(false);
 }
 
@@ -940,6 +957,7 @@
         // another.
         ok = clearTrace();
 
+        writeClockSyncMarker();
         if (ok && !async) {
             // Sleep to allow the trace to be captured.
             struct timespec timeLeft;
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index ef8db06..792f015 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -434,8 +434,6 @@
     run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL);
     run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL);
 
-    run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "connectivity", "--diag", NULL);
-
     run_command("IPTABLES", 10, SU_PATH, "root", "iptables", "-L", "-nvx", NULL);
     run_command("IP6TABLES", 10, SU_PATH, "root", "ip6tables", "-L", "-nvx", NULL);
     run_command("IPTABLE NAT", 10, SU_PATH, "root", "iptables", "-t", "nat", "-L", "-nvx", NULL);
@@ -447,25 +445,29 @@
             SU_PATH, "root", "wpa_cli", "IFNAME=wlan0", "list_networks", NULL);
 
 #ifdef FWDUMP_bcmdhd
-    run_command("DUMP WIFI INTERNAL COUNTERS", 20,
+    run_command("ND OFFLOAD TABLE", 5,
+            SU_PATH, "root", "wlutil", "nd_hostip", NULL);
+
+    run_command("DUMP WIFI INTERNAL COUNTERS (1)", 20,
             SU_PATH, "root", "wlutil", "counters", NULL);
+
+    run_command("ND OFFLOAD STATUS (1)", 5,
+            SU_PATH, "root", "wlutil", "nd_status", NULL);
+
 #endif
     dump_file("INTERRUPTS (1)", "/proc/interrupts");
 
-    property_get("dhcp.wlan0.gateway", network, "");
-    if (network[0])
-        run_command("PING GATEWAY", 10, "ping", "-c", "3", "-i", ".5", network, NULL);
-    property_get("dhcp.wlan0.dns1", network, "");
-    if (network[0])
-        run_command("PING DNS1", 10, "ping", "-c", "3", "-i", ".5", network, NULL);
-    property_get("dhcp.wlan0.dns2", network, "");
-    if (network[0])
-        run_command("PING DNS2", 10, "ping", "-c", "3", "-i", ".5", network, NULL);
+    run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "connectivity", "--diag", NULL);
+
 #ifdef FWDUMP_bcmdhd
     run_command("DUMP WIFI STATUS", 20,
             SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL);
-    run_command("DUMP WIFI INTERNAL COUNTERS", 20,
+
+    run_command("DUMP WIFI INTERNAL COUNTERS (2)", 20,
             SU_PATH, "root", "wlutil", "counters", NULL);
+
+    run_command("ND OFFLOAD STATUS (2)", 5,
+            SU_PATH, "root", "wlutil", "nd_status", NULL);
 #endif
     dump_file("INTERRUPTS (2)", "/proc/interrupts");
 
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 7090b36..d4aa7d3 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -746,7 +746,7 @@
 
 static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
     const char* output_file_name, int swap_fd, const char *pkgname, const char *instruction_set,
-    bool vm_safe_mode, bool debuggable)
+    bool vm_safe_mode, bool debuggable, bool post_bootcomplete)
 {
     static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
 
@@ -770,8 +770,24 @@
                                                           dex2oat_compiler_filter_flag, NULL) > 0;
 
     char dex2oat_threads_buf[PROPERTY_VALUE_MAX];
-    bool have_dex2oat_threads_flag = property_get("dalvik.vm.dex2oat-threads", dex2oat_threads_buf,
-                                                  NULL) > 0;
+    bool have_dex2oat_threads_flag = false;
+    if (!post_bootcomplete) {
+        have_dex2oat_threads_flag = property_get("dalvik.vm.boot-dex2oat-threads",
+                                                 dex2oat_threads_buf,
+                                                 NULL) > 0;
+        // If there's no boot property, fall back to the image property.
+        if (!have_dex2oat_threads_flag) {
+            have_dex2oat_threads_flag = property_get("dalvik.vm.image-dex2oat-threads",
+                                                     dex2oat_threads_buf,
+                                                     NULL) > 0;
+        }
+        // If there's neither, fall back to the default property.
+    }
+    if (!have_dex2oat_threads_flag) {
+        have_dex2oat_threads_flag = property_get("dalvik.vm.dex2oat-threads",
+                                                 dex2oat_threads_buf,
+                                                 NULL) > 0;
+    }
     char dex2oat_threads_arg[PROPERTY_VALUE_MAX + 2];
     if (have_dex2oat_threads_flag) {
         sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf);
@@ -1065,9 +1081,22 @@
     return true;
 }
 
+static void SetDex2OatAndPatchOatScheduling(bool set_to_bg) {
+    if (set_to_bg) {
+        if (set_sched_policy(0, SP_BACKGROUND) < 0) {
+            ALOGE("set_sched_policy failed: %s\n", strerror(errno));
+            exit(70);
+        }
+        if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
+            ALOGE("setpriority failed: %s\n", strerror(errno));
+            exit(71);
+        }
+    }
+}
+
 int dexopt(const char *apk_path, uid_t uid, bool is_public,
            const char *pkgname, const char *instruction_set, int dexopt_needed,
-           bool vm_safe_mode, bool debuggable, const char* oat_dir)
+           bool vm_safe_mode, bool debuggable, const char* oat_dir, bool boot_complete)
 {
     struct utimbuf ut;
     struct stat input_stat;
@@ -1198,14 +1227,7 @@
             ALOGE("capset failed: %s\n", strerror(errno));
             exit(66);
         }
-        if (set_sched_policy(0, SP_BACKGROUND) < 0) {
-            ALOGE("set_sched_policy failed: %s\n", strerror(errno));
-            exit(70);
-        }
-        if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
-            ALOGE("setpriority failed: %s\n", strerror(errno));
-            exit(71);
-        }
+        SetDex2OatAndPatchOatScheduling(boot_complete);
         if (flock(out_fd, LOCK_EX | LOCK_NB) != 0) {
             ALOGE("flock(%s) failed: %s\n", out_path, strerror(errno));
             exit(67);
@@ -1222,7 +1244,7 @@
                 input_file_name++;
             }
             run_dex2oat(input_fd, out_fd, input_file_name, out_path, swap_fd, pkgname,
-                        instruction_set, vm_safe_mode, debuggable);
+                        instruction_set, vm_safe_mode, debuggable, boot_complete);
         } else {
             ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
             exit(73);
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index 13e3168..f67e838 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -48,9 +48,9 @@
 static int do_dexopt(char **arg, char reply[REPLY_MAX] __unused)
 {
     /* apk_path, uid, is_public, pkgname, instruction_set,
-     * dexopt_needed, vm_safe_mode, debuggable, oat_dir */
+     * dexopt_needed, vm_safe_mode, debuggable, oat_dir, boot_complete */
     return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], atoi(arg[5]),
-                  atoi(arg[6]), atoi(arg[7]), arg[8]);
+                  atoi(arg[6]), atoi(arg[7]), arg[8], atoi(arg[9]));
 }
 
 static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] __unused)
@@ -194,7 +194,7 @@
 struct cmdinfo cmds[] = {
     { "ping",                 0, do_ping },
     { "install",              5, do_install },
-    { "dexopt",               9, do_dexopt },
+    { "dexopt",               10, do_dexopt },
     { "markbootcomplete",     1, do_mark_boot_complete },
     { "movedex",              3, do_move_dex },
     { "rmdex",                2, do_rm_dex },
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 7ec5793..24b9084 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -243,7 +243,7 @@
 int free_cache(const char *uuid, int64_t free_size);
 int dexopt(const char *apk_path, uid_t uid, bool is_public, const char *pkgName,
            const char *instruction_set, int dexopt_needed, bool vm_safe_mode,
-           bool debuggable, const char* oat_dir);
+           bool debuggable, const char* oat_dir, bool boot_complete);
 int mark_boot_complete(const char *instruction_set);
 int movefiles();
 int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId);
diff --git a/data/etc/android.hardware.audio.pro.xml b/data/etc/android.hardware.audio.pro.xml
new file mode 100644
index 0000000..5328d41
--- /dev/null
+++ b/data/etc/android.hardware.audio.pro.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- This is the feature indicating professional audio, as specified by the
+     CDD. ONLY devices that meet the CDD's requirements may declare this
+     feature. -->
+<permissions>
+    <feature name="android.hardware.audio.pro" />
+</permissions>
diff --git a/include/android/keycodes.h b/include/android/keycodes.h
index 1f55d9f..15bb786 100644
--- a/include/android/keycodes.h
+++ b/include/android/keycodes.h
@@ -722,20 +722,7 @@
     AKEYCODE_NAVIGATE_PREVIOUS = 260,
     AKEYCODE_NAVIGATE_NEXT   = 261,
     AKEYCODE_NAVIGATE_IN     = 262,
-    AKEYCODE_NAVIGATE_OUT    = 263,
-    /** Primary stem key for Wear
-     * Main power/reset button on watch. */
-    AKEYCODE_STEM_PRIMARY = 264,
-    /** Generic stem key 1 for Wear */
-    AKEYCODE_STEM_1 = 265,
-    /** Generic stem key 2 for Wear */
-    AKEYCODE_STEM_2 = 266,
-    /** Generic stem key 3 for Wear */
-    AKEYCODE_STEM_3 = 267,
-    AKEYCODE_MEDIA_SKIP_FORWARD = 272,
-    AKEYCODE_MEDIA_SKIP_BACKWARD = 273,
-    AKEYCODE_MEDIA_STEP_FORWARD = 274,
-    AKEYCODE_MEDIA_STEP_BACKWARD = 275
+    AKEYCODE_NAVIGATE_OUT    = 263
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/include/input/Input.h b/include/input/Input.h
index 4a67f47..92b3d36 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -111,6 +111,11 @@
 #define MAX_POINTERS 16
 
 /*
+ * Maximum number of samples supported per motion event.
+ */
+#define MAX_SAMPLES UINT16_MAX
+
+/*
  * Maximum pointer id value supported in a motion event.
  * Smallest pointer id is 0.
  * (This is limited by our use of BitSet32 to track pointer assignments.)
diff --git a/include/input/InputEventLabels.h b/include/input/InputEventLabels.h
index 344f2f3..3962001 100644
--- a/include/input/InputEventLabels.h
+++ b/include/input/InputEventLabels.h
@@ -303,14 +303,6 @@
     DEFINE_KEYCODE(NAVIGATE_NEXT),
     DEFINE_KEYCODE(NAVIGATE_IN),
     DEFINE_KEYCODE(NAVIGATE_OUT),
-    DEFINE_KEYCODE(STEM_PRIMARY),
-    DEFINE_KEYCODE(STEM_1),
-    DEFINE_KEYCODE(STEM_2),
-    DEFINE_KEYCODE(STEM_3),
-    DEFINE_KEYCODE(MEDIA_SKIP_FORWARD),
-    DEFINE_KEYCODE(MEDIA_SKIP_BACKWARD),
-    DEFINE_KEYCODE(MEDIA_STEP_FORWARD),
-    DEFINE_KEYCODE(MEDIA_STEP_BACKWARD),
 
     { NULL, 0 }
 };
diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h
index e70666a..3f0914b 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;
+
 #if HAVE_ANDROID_OS
     /* 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/include/ui/DisplayInfo.h b/include/ui/DisplayInfo.h
index 799944f..ad73ee7 100644
--- a/include/ui/DisplayInfo.h
+++ b/include/ui/DisplayInfo.h
@@ -36,6 +36,7 @@
     bool secure;
     nsecs_t appVsyncOffset;
     nsecs_t presentationDeadline;
+    int colorTransform;
 };
 
 /* Display orientations as defined in Surface.java and ISurfaceComposer.h. */
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index d7a7885..8bdbc22 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -348,7 +348,7 @@
             uint32_t height = data.readUint32();
             PixelFormat format = static_cast<PixelFormat>(data.readInt32());
             uint32_t usage = data.readUint32();
-            int buf;
+            int buf = 0;
             sp<Fence> fence;
             int result = dequeueBuffer(&buf, &fence, async, width, height,
                     format, usage);
@@ -389,7 +389,7 @@
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
             sp<GraphicBuffer> buffer = new GraphicBuffer();
             data.read(*buffer.get());
-            int slot;
+            int slot = 0;
             int result = attachBuffer(&slot, buffer);
             reply->writeInt32(slot);
             reply->writeInt32(result);
@@ -416,7 +416,7 @@
         }
         case QUERY: {
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
-            int value;
+            int value = 0;
             int what = data.readInt32();
             int res = query(what, &value);
             reply->writeInt32(value);
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index 1b8d06e..235cbbd 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -223,6 +223,10 @@
         }
         if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor->requiredPermission) {
             mRequiredPermission = hwSensor->requiredPermission;
+            if (!strcmp(mRequiredPermission, SENSOR_PERMISSION_BODY_SENSORS)) {
+                AppOpsManager appOps;
+                mRequiredAppOp = appOps.permissionToOpCode(String16(SENSOR_PERMISSION_BODY_SENSORS));
+            }
         }
 
         if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp
index 9934151..33608b5 100644
--- a/libs/gui/SensorManager.cpp
+++ b/libs/gui/SensorManager.cpp
@@ -110,10 +110,20 @@
 }
 
 status_t SensorManager::assertStateLocked() const {
+    bool initSensorManager = false;
     if (mSensorServer == NULL) {
-        // try for 10 seconds before giving up ...
+        initSensorManager = true;
+    } else {
+        // Ping binder to check if sensorservice is alive.
+        status_t err = IInterface::asBinder(mSensorServer)->pingBinder();
+        if (err != NO_ERROR) {
+            initSensorManager = true;
+        }
+    }
+    if (initSensorManager) {
+        // try for 300 seconds (60*5(getService() tries for 5 seconds)) before giving up ...
         const String16 name("sensorservice");
-        for (int i = 0;i < 10; i++) {
+        for (int i = 0; i < 60; i++) {
             status_t err = getService(name, &mSensorServer);
             if (err == NAME_NOT_FOUND) {
                 sleep(1);
@@ -135,9 +145,7 @@
             DeathObserver(SensorManager& mgr) : mSensorManger(mgr) { }
         };
 
-        if (mSensorServer == NULL) {
-            ALOGE("FATAL getsensorservice returned NULL");
-        }
+        LOG_ALWAYS_FATAL_IF(mSensorServer.get() == NULL, "getService(SensorService) NULL");
 
         mDeathObserver = new DeathObserver(*const_cast<SensorManager *>(this));
         IInterface::asBinder(mSensorServer)->linkToDeath(mDeathObserver);
@@ -146,6 +154,8 @@
         size_t count = mSensors.size();
         mSensorList =
                 static_cast<Sensor const**>(malloc(count * sizeof(Sensor*)));
+        LOG_ALWAYS_FATAL_IF(mSensorList == NULL, "mSensorList NULL");
+
         for (size_t i=0 ; i<count ; i++) {
             mSensorList[i] = mSensors.array() + i;
         }
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 2c1418e..b64cb2c 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -424,7 +424,8 @@
 status_t MotionEvent::readFromParcel(Parcel* parcel) {
     size_t pointerCount = parcel->readInt32();
     size_t sampleCount = parcel->readInt32();
-    if (pointerCount == 0 || pointerCount > MAX_POINTERS || sampleCount == 0) {
+    if (pointerCount == 0 || pointerCount > MAX_POINTERS ||
+            sampleCount == 0 || sampleCount > MAX_SAMPLES) {
         return BAD_VALUE;
     }
 
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 0382f57..7f83da5 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -51,6 +51,10 @@
 // Minimum time difference between consecutive samples before attempting to resample.
 static const nsecs_t RESAMPLE_MIN_DELTA = 2 * NANOS_PER_MS;
 
+// Maximum time difference between consecutive samples before attempting to resample
+// by extrapolation.
+static const nsecs_t RESAMPLE_MAX_DELTA = 20 * NANOS_PER_MS;
+
 // Maximum time to predict forward from the last known state, to avoid predicting too
 // far into the future.  This time is further bounded by 50% of the last time delta.
 static const nsecs_t RESAMPLE_MAX_PREDICTION = 8 * NANOS_PER_MS;
@@ -724,7 +728,7 @@
         nsecs_t delta = future.eventTime - current->eventTime;
         if (delta < RESAMPLE_MIN_DELTA) {
 #if DEBUG_RESAMPLING
-            ALOGD("Not resampled, delta time is %lld ns.", delta);
+            ALOGD("Not resampled, delta time is too small: %lld ns.", delta);
 #endif
             return;
         }
@@ -736,7 +740,12 @@
         nsecs_t delta = current->eventTime - other->eventTime;
         if (delta < RESAMPLE_MIN_DELTA) {
 #if DEBUG_RESAMPLING
-            ALOGD("Not resampled, delta time is %lld ns.", delta);
+            ALOGD("Not resampled, delta time is too small: %lld ns.", delta);
+#endif
+            return;
+        } else if (delta > RESAMPLE_MAX_DELTA) {
+#if DEBUG_RESAMPLING
+            ALOGD("Not resampled, delta time is too large: %lld ns.", delta);
 #endif
             return;
         }
diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp
index b03e01e..df3f0dd 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/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 8378907..cdec565 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -595,15 +595,6 @@
         return setError(EGL_BAD_SURFACE, EGL_FALSE);
 
     egl_surface_t * const s = get_surface(surface);
-    ANativeWindow* window = s->win.get();
-    if (window) {
-        int result = native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
-        if (result != OK) {
-            ALOGE("eglDestroySurface: native_window_api_disconnect (win=%p) "
-                  "failed (%#x)",
-                  window, result);
-        }
-    }
     EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
     if (result == EGL_TRUE) {
         _s.terminate();
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/host/InputDriver.cpp b/services/inputflinger/host/InputDriver.cpp
index cb4ccbe..630a596 100644
--- a/services/inputflinger/host/InputDriver.cpp
+++ b/services/inputflinger/host/InputDriver.cpp
@@ -14,11 +14,8 @@
  * limitations under the License.
  */
 
-#include <functional>
 #include <stdint.h>
 #include <sys/types.h>
-#include <unordered_map>
-#include <vector>
 
 #define LOG_TAG "InputDriver"
 
@@ -28,9 +25,7 @@
 #include "InputHost.h"
 
 #include <hardware/input.h>
-#include <input/InputDevice.h>
 #include <utils/Log.h>
-#include <utils/PropertyMap.h>
 #include <utils/String8.h>
 
 #define INDENT2 "    "
@@ -42,7 +37,6 @@
     .create_device_definition = create_device_definition,
     .create_input_report_definition = create_input_report_definition,
     .create_output_report_definition = create_output_report_definition,
-    .free_report_definition = free_report_definition,
     .input_device_definition_add_report = input_device_definition_add_report,
     .input_report_definition_add_collection = input_report_definition_add_collection,
     .input_report_definition_declare_usage_int = input_report_definition_declare_usage_int,
@@ -75,214 +69,78 @@
     result.appendFormat(INDENT2 "HAL Input Driver (%s)\n", mName.string());
 }
 
-} // namespace android
-
-struct input_property_map {
-    android::PropertyMap* propertyMap;
-};
-
-struct input_property {
-    android::String8 key;
-    android::String8 value;
-};
-
-struct input_device_identifier {
-    const char* name;
-    const char* uniqueId;
-    input_bus_t bus;
-    int32_t     vendorId;
-    int32_t     productId;
-    int32_t     version;
-};
-
-struct input_device_definition {
-    std::vector<input_report_definition*> reportDefs;
-};
-
-struct input_device_handle {
-    input_device_identifier_t* id;
-    input_device_definition_t* def;
-};
-
-struct input_int_usage {
-    input_usage_t usage;
-    int32_t min;
-    int32_t max;
-    float   resolution;
-};
-
-struct input_collection {
-    int32_t arity;
-    std::vector<input_int_usage> intUsages;
-    std::vector<input_usage_t> boolUsages;
-};
-
-struct InputCollectionIdHasher {
-    std::size_t operator()(const input_collection_id& id) const {
-        return std::hash<int>()(static_cast<int>(id));
-    }
-};
-
-struct input_report_definition {
-    std::unordered_map<input_collection_id_t, input_collection, InputCollectionIdHasher> collections;
-};
 
 // HAL wrapper functions
 
-namespace android {
-
-::input_device_identifier_t* create_device_identifier(input_host_t* host,
+input_device_identifier_t* create_device_identifier(input_host_t* host,
         const char* name, int32_t product_id, int32_t vendor_id,
         input_bus_t bus, const char* unique_id) {
-    auto identifier = new ::input_device_identifier {
-        .name = name,
-        .productId = product_id,
-        .vendorId = vendor_id,
-        //.bus = bus,
-        .uniqueId = unique_id,
-    };
-    // store this identifier somewhere? in the host?
-    return identifier;
-}
-
-input_device_definition_t* create_device_definition(input_host_t* host) {
-    return new ::input_device_definition;
-}
-
-input_report_definition_t* create_input_report_definition(input_host_t* host) {
-    return new ::input_report_definition;
-}
-
-input_report_definition_t* create_output_report_definition(input_host_t* host) {
-    return new ::input_report_definition;
-}
-
-void free_report_definition(input_host_t* host, input_report_definition_t* report_def) {
-    delete report_def;
-}
-
-void input_device_definition_add_report(input_host_t* host,
-        input_device_definition_t* d, input_report_definition_t* r) {
-    d->reportDefs.push_back(r);
-}
-
-void input_report_definition_add_collection(input_host_t* host,
-        input_report_definition_t* report, input_collection_id_t id, int32_t arity) {
-    report->collections[id] = {.arity = arity};
-}
-
-void input_report_definition_declare_usage_int(input_host_t* host,
-        input_report_definition_t* report, input_collection_id_t id,
-        input_usage_t usage, int32_t min, int32_t max, float resolution) {
-    if (report->collections.find(id) != report->collections.end()) {
-        report->collections[id].intUsages.push_back({
-                .usage = usage, .min = min, .max = max, .resolution = resolution});
-    }
-}
-
-void input_report_definition_declare_usages_bool(input_host_t* host,
-        input_report_definition_t* report, input_collection_id_t id,
-        input_usage_t* usage, size_t usage_count) {
-    if (report->collections.find(id) != report->collections.end()) {
-        for (size_t i = 0; i < usage_count; ++i) {
-            report->collections[id].boolUsages.push_back(usage[i]);
-        }
-    }
-}
-
-input_device_handle_t* register_device(input_host_t* host,
-        input_device_identifier_t* id, input_device_definition_t* d) {
-    ALOGD("Registering device %s with %d input reports", id->name, d->reportDefs.size());
-    return new input_device_handle{ .id = id, .def = d };
-}
-
-input_report_t* input_allocate_report(input_host_t* host, input_report_definition_t* r) {
-    ALOGD("Allocating input report for definition %p", r);
     return nullptr;
 }
 
+input_device_definition_t* create_device_definition(input_host_t* host) {
+    return nullptr;
+}
+
+input_report_definition_t* create_input_report_definition(input_host_t* host) {
+    return nullptr;
+}
+
+input_report_definition_t* create_output_report_definition(input_host_t* host) {
+    return nullptr;
+}
+
+void input_device_definition_add_report(input_host_t* host,
+        input_device_definition_t* d, input_report_definition_t* r) { }
+
+void input_report_definition_add_collection(input_host_t* host,
+        input_report_definition_t* report, input_collection_id_t id, int32_t arity) { }
+
+void input_report_definition_declare_usage_int(input_host_t* host,
+        input_report_definition_t* report, input_collection_id_t id,
+        input_usage_t usage, int32_t min, int32_t max, float resolution) { }
+
+void input_report_definition_declare_usages_bool(input_host_t* host,
+        input_report_definition_t* report, input_collection_id_t id,
+        input_usage_t* usage, size_t usage_count) { }
+
+
+input_device_handle_t* register_device(input_host_t* host,
+        input_device_identifier_t* id, input_device_definition_t* d) {
+    return nullptr;
+}
+
+input_report_t* input_allocate_report(input_host_t* host, input_report_definition_t* r) {
+    return nullptr;
+}
 void input_report_set_usage_int(input_host_t* host, input_report_t* r,
         input_collection_id_t id, input_usage_t usage, int32_t value, int32_t arity_index) { }
 
 void input_report_set_usage_bool(input_host_t* host, input_report_t* r,
         input_collection_id_t id, input_usage_t usage, bool value, int32_t arity_index) { }
 
-void report_event(input_host_t* host, input_device_handle_t* d, input_report_t* report) {
-    ALOGD("report_event %p for handle %p", report, d);
-}
+void report_event(input_host_t* host, input_device_handle_t* d, input_report_t* report) { }
 
 input_property_map_t* input_get_device_property_map(input_host_t* host,
         input_device_identifier_t* id) {
-    InputDeviceIdentifier idi;
-    idi.name = id->name;
-    idi.uniqueId = id->uniqueId;
-    idi.bus = id->bus;
-    idi.vendor = id->vendorId;
-    idi.product = id->productId;
-    idi.version = id->version;
-
-    String8 configFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
-            idi, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
-    if (configFile.isEmpty()) {
-        ALOGD("No input device configuration file found for device '%s'.",
-                idi.name.string());
-    } else {
-        auto propMap = new input_property_map_t();
-        status_t status = PropertyMap::load(configFile, &propMap->propertyMap);
-        if (status) {
-            ALOGE("Error loading input device configuration file for device '%s'. "
-                    "Using default configuration.",
-                    idi.name.string());
-            delete propMap;
-            return nullptr;
-        }
-        return propMap;
-    }
     return nullptr;
 }
 
 input_property_t* input_get_device_property(input_host_t* host, input_property_map_t* map,
         const char* key) {
-    String8 keyString(key);
-    if (map != nullptr) {
-        if (map->propertyMap->hasProperty(keyString)) {
-            auto prop = new input_property_t();
-            if (!map->propertyMap->tryGetProperty(keyString, prop->value)) {
-                delete prop;
-                return nullptr;
-            }
-            prop->key = keyString;
-            return prop;
-        }
-    }
     return nullptr;
 }
 
 const char* input_get_property_key(input_host_t* host, input_property_t* property) {
-    if (property != nullptr) {
-        return property->key.string();
-    }
     return nullptr;
 }
 
 const char* input_get_property_value(input_host_t* host, input_property_t* property) {
-    if (property != nullptr) {
-        return property->value.string();
-    }
     return nullptr;
 }
 
-void input_free_device_property(input_host_t* host, input_property_t* property) {
-    if (property != nullptr) {
-        delete property;
-    }
-}
+void input_free_device_property(input_host_t* host, input_property_t* property) { }
 
-void input_free_device_property_map(input_host_t* host, input_property_map_t* map) {
-    if (map != nullptr) {
-        delete map->propertyMap;
-        delete map;
-    }
-}
+void input_free_device_property_map(input_host_t* host, input_property_map_t* map) { }
 
 } // namespace android
diff --git a/services/inputflinger/host/InputDriver.h b/services/inputflinger/host/InputDriver.h
index 9bc14a7..7734ac2 100644
--- a/services/inputflinger/host/InputDriver.h
+++ b/services/inputflinger/host/InputDriver.h
@@ -68,8 +68,6 @@
 
 input_report_definition_t* create_output_report_definition(input_host_t* host);
 
-void free_report_definition(input_host_t* host, input_report_definition_t* report_def);
-
 void input_device_definition_add_report(input_host_t* host,
         input_device_definition_t* d, input_report_definition_t* r);
 
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;
             }
         }
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 2dad005..0859149 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -336,10 +336,20 @@
     HWC_DISPLAY_HEIGHT,
     HWC_DISPLAY_DPI_X,
     HWC_DISPLAY_DPI_Y,
+    HWC_DISPLAY_COLOR_TRANSFORM,
     HWC_DISPLAY_NO_ATTRIBUTE,
 };
 #define NUM_DISPLAY_ATTRIBUTES (sizeof(DISPLAY_ATTRIBUTES) / sizeof(DISPLAY_ATTRIBUTES)[0])
 
+static const uint32_t PRE_HWC15_DISPLAY_ATTRIBUTES[] = {
+    HWC_DISPLAY_VSYNC_PERIOD,
+    HWC_DISPLAY_WIDTH,
+    HWC_DISPLAY_HEIGHT,
+    HWC_DISPLAY_DPI_X,
+    HWC_DISPLAY_DPI_Y,
+    HWC_DISPLAY_NO_ATTRIBUTE,
+};
+
 status_t HWComposer::queryDisplayProperties(int disp) {
 
     LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
@@ -362,6 +372,12 @@
     for (size_t c = 0; c < numConfigs; ++c) {
         err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
                 DISPLAY_ATTRIBUTES, values);
+        // If this is a pre-1.5 HWC, it may not know about color transform, so
+        // try again with a smaller set of attributes
+        if (err != NO_ERROR) {
+            err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
+                    PRE_HWC15_DISPLAY_ATTRIBUTES, values);
+        }
         if (err != NO_ERROR) {
             // we can't get this display's info. turn it off.
             mDisplayData[disp].connected = false;
@@ -386,6 +402,9 @@
                 case HWC_DISPLAY_DPI_Y:
                     config.ydpi = values[i] / 1000.0f;
                     break;
+                case HWC_DISPLAY_COLOR_TRANSFORM:
+                    config.colorTransform = values[i];
+                    break;
                 default:
                     ALOG_ASSERT(false, "unknown display attribute[%zu] %#x",
                             i, DISPLAY_ATTRIBUTES[i]);
@@ -1162,9 +1181,11 @@
             result.appendFormat("  Display[%zd] configurations (* current):\n", i);
             for (size_t c = 0; c < disp.configs.size(); ++c) {
                 const DisplayConfig& config(disp.configs[c]);
-                result.appendFormat("    %s%zd: %ux%u, xdpi=%f, ydpi=%f, refresh=%" PRId64 "\n",
-                        c == disp.currentConfig ? "* " : "", c, config.width, config.height,
-                        config.xdpi, config.ydpi, config.refresh);
+                result.appendFormat("    %s%zd: %ux%u, xdpi=%f, ydpi=%f"
+                        ", refresh=%" PRId64 ", colorTransform=%d\n",
+                        c == disp.currentConfig ? "* " : "", c,
+                        config.width, config.height, config.xdpi, config.ydpi,
+                        config.refresh, config.colorTransform);
             }
 
             if (disp.list) {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index cc98b4c..5e0b3d8 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -257,6 +257,7 @@
         float xdpi;
         float ydpi;
         nsecs_t refresh;
+        int colorTransform;
     };
 
     // Query display parameters.  Pass in a display index (e.g.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 01ffac2..fdc3650 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -632,6 +632,7 @@
         info.ydpi = ydpi;
         info.fps = float(1e9 / hwConfig.refresh);
         info.appVsyncOffset = VSYNC_EVENT_PHASE_OFFSET_NS;
+        info.colorTransform = hwConfig.colorTransform;
 
         // This is how far in advance a buffer must be queued for
         // presentation at a given time.  If you want a buffer to appear