Merge "Revert "Revert "Remove GLTrace support"""
diff --git a/cmds/cmd/Android.mk b/cmds/cmd/Android.mk
new file mode 100644
index 0000000..ac2f4c0
--- /dev/null
+++ b/cmds/cmd/Android.mk
@@ -0,0 +1,20 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	cmd.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libutils \
+	liblog \
+	libbinder
+	
+
+ifeq ($(TARGET_OS),linux)
+	LOCAL_CFLAGS += -DXP_UNIX
+	#LOCAL_SHARED_LIBRARIES += librt
+endif
+
+LOCAL_MODULE:= cmd
+
+include $(BUILD_EXECUTABLE)
diff --git a/cmds/cmd/MODULE_LICENSE_APACHE2 b/cmds/cmd/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cmds/cmd/MODULE_LICENSE_APACHE2
diff --git a/cmds/cmd/NOTICE b/cmds/cmd/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/cmds/cmd/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-2008, 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.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/cmds/cmd/cmd.cpp b/cmds/cmd/cmd.cpp
new file mode 100644
index 0000000..ed740d3
--- /dev/null
+++ b/cmds/cmd/cmd.cpp
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "cmd"
+
+#include <utils/Log.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <binder/IResultReceiver.h>
+#include <binder/IServiceManager.h>
+#include <binder/TextOutput.h>
+#include <utils/Vector.h>
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+using namespace android;
+
+static int sort_func(const String16* lhs, const String16* rhs)
+{
+    return lhs->compare(*rhs);
+}
+
+class MyResultReceiver : public BnResultReceiver
+{
+public:
+    virtual void send(int32_t /*resultCode*/) {
+    }
+};
+
+int main(int argc, char* const argv[])
+{
+    signal(SIGPIPE, SIG_IGN);
+    sp<ProcessState> proc = ProcessState::self();
+    proc->startThreadPool();
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    fflush(stdout);
+    if (sm == NULL) {
+        ALOGE("Unable to get default service manager!");
+        aerr << "cmd: Unable to get default service manager!" << endl;
+        return 20;
+    }
+
+    if (argc == 1) {
+        aout << "cmd: no service specified; use -l to list all services" << endl;
+        return 20;
+    }
+
+    if ((argc == 2) && (strcmp(argv[1], "-l") == 0)) {
+        Vector<String16> services = sm->listServices();
+        services.sort(sort_func);
+        aout << "Currently running services:" << endl;
+
+        for (size_t i=0; i<services.size(); i++) {
+            sp<IBinder> service = sm->checkService(services[i]);
+            if (service != NULL) {
+                aout << "  " << services[i] << endl;
+            }
+        }
+        return 0;
+    }
+
+    Vector<String16> args;
+    for (int i=2; i<argc; i++) {
+        args.add(String16(argv[i]));
+    }
+    String16 cmd = String16(argv[1]);
+    sp<IBinder> service = sm->checkService(cmd);
+    if (service == NULL) {
+        aerr << "Can't find service: " << argv[1] << endl;
+        return 20;
+    }
+
+    // TODO: block until a result is returned to MyResultReceiver.
+    IBinder::shellCommand(service, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, args,
+            new MyResultReceiver());
+    return 0;
+}
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 59c1d12..1da7308 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -300,7 +300,7 @@
     dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
     dump_file("MEMORY INFO", "/proc/meminfo");
     run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-t", NULL);
-    run_command("PROCRANK", 20, "procrank", NULL);
+    run_command("PROCRANK", 20, SU_PATH, "root", "procrank", NULL);
     dump_file("VIRTUAL MEMORY STATS", "/proc/vmstat");
     dump_file("VMALLOC INFO", "/proc/vmallocinfo");
     dump_file("SLAB INFO", "/proc/slabinfo");
@@ -337,22 +337,32 @@
     if (timeout < 20000) {
         timeout = 20000;
     }
-    run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime", "-d", "*:v", NULL);
+    run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime",
+                                                        "-v", "printable",
+                                                        "-d",
+                                                        "*:v", NULL);
     timeout = logcat_timeout("events");
     if (timeout < 20000) {
         timeout = 20000;
     }
-    run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events", "-v", "threadtime", "-d", "*:v", NULL);
+    run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events",
+                                                       "-v", "threadtime",
+                                                       "-v", "printable",
+                                                       "-d",
+                                                       "*:v", NULL);
     timeout = logcat_timeout("radio");
     if (timeout < 20000) {
         timeout = 20000;
     }
-    run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL);
+    run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio",
+                                                       "-v", "threadtime",
+                                                       "-v", "printable",
+                                                       "-d",
+                                                       "*:v", NULL);
 
     run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
 
-    // raft disabled as per http://b/24159112
-    // run_command("RAFT LOGS", 300, SU_PATH, "root", "logcompressor", "-r", RAFT_DIR, NULL);
+    run_command("RAFT LOGS", 300, SU_PATH, "root", "logcompressor", "-r", RAFT_DIR, NULL);
 
     /* show the traces we collected in main(), if that was done */
     if (dump_traces_path != NULL) {
@@ -420,8 +430,12 @@
     }
 
     /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
-    run_command("LAST LOGCAT", 10, "logcat", "-L", "-v", "threadtime",
-                                             "-b", "all", "-d", "*:v", NULL);
+    run_command("LAST LOGCAT", 10, "logcat", "-L",
+                                             "-b", "all",
+                                             "-v", "threadtime",
+                                             "-v", "printable",
+                                             "-d",
+                                             "*:v", NULL);
 
     /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
 
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 7fa9a39..8596f96 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -23,6 +23,12 @@
 #include <cutils/log.h>
 #endif
 
+struct audit_data {
+    pid_t pid;
+    uid_t uid;
+    const char *name;
+};
+
 const char *str8(const uint16_t *x, size_t x_len)
 {
     static char buf[128];
@@ -56,34 +62,39 @@
 static char *service_manager_context;
 static struct selabel_handle* sehandle;
 
-static bool check_mac_perms(pid_t spid, const char *tctx, const char *perm, const char *name)
+static bool check_mac_perms(pid_t spid, uid_t uid, const char *tctx, const char *perm, const char *name)
 {
     char *sctx = NULL;
     const char *class = "service_manager";
     bool allowed;
+    struct audit_data ad;
 
     if (getpidcon(spid, &sctx) < 0) {
         ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid);
         return false;
     }
 
-    int result = selinux_check_access(sctx, tctx, class, perm, (void *) name);
+    ad.pid = spid;
+    ad.uid = uid;
+    ad.name = name;
+
+    int result = selinux_check_access(sctx, tctx, class, perm, (void *) &ad);
     allowed = (result == 0);
 
     freecon(sctx);
     return allowed;
 }
 
-static bool check_mac_perms_from_getcon(pid_t spid, const char *perm)
+static bool check_mac_perms_from_getcon(pid_t spid, uid_t uid, const char *perm)
 {
     if (selinux_enabled <= 0) {
         return true;
     }
 
-    return check_mac_perms(spid, service_manager_context, perm, NULL);
+    return check_mac_perms(spid, uid, service_manager_context, perm, NULL);
 }
 
-static bool check_mac_perms_from_lookup(pid_t spid, const char *perm, const char *name)
+static bool check_mac_perms_from_lookup(pid_t spid, uid_t uid, const char *perm, const char *name)
 {
     bool allowed;
     char *tctx = NULL;
@@ -102,27 +113,27 @@
         return false;
     }
 
-    allowed = check_mac_perms(spid, tctx, perm, name);
+    allowed = check_mac_perms(spid, uid, tctx, perm, name);
     freecon(tctx);
     return allowed;
 }
 
-static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid)
+static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
 {
     const char *perm = "add";
-    return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0;
+    return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
 }
 
-static int svc_can_list(pid_t spid)
+static int svc_can_list(pid_t spid, uid_t uid)
 {
     const char *perm = "list";
-    return check_mac_perms_from_getcon(spid, perm) ? 1 : 0;
+    return check_mac_perms_from_getcon(spid, uid, perm) ? 1 : 0;
 }
 
-static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid)
+static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
 {
     const char *perm = "find";
-    return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0;
+    return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
 }
 
 struct svcinfo
@@ -184,7 +195,7 @@
         }
     }
 
-    if (!svc_can_find(s, len, spid)) {
+    if (!svc_can_find(s, len, spid, uid)) {
         return 0;
     }
 
@@ -204,7 +215,7 @@
     if (!handle || (len == 0) || (len > 127))
         return -1;
 
-    if (!svc_can_register(s, len, spid)) {
+    if (!svc_can_register(s, len, spid, uid)) {
         ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
              str8(s, len), handle, uid);
         return -1;
@@ -314,7 +325,7 @@
     case SVC_MGR_LIST_SERVICES: {
         uint32_t n = bio_get_uint32(msg);
 
-        if (!svc_can_list(txn->sender_pid)) {
+        if (!svc_can_list(txn->sender_pid, txn->sender_euid)) {
             ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
                     txn->sender_euid);
             return -1;
@@ -340,7 +351,14 @@
 
 static int audit_callback(void *data, security_class_t cls, char *buf, size_t len)
 {
-    snprintf(buf, len, "service=%s", !data ? "NULL" : (char *)data);
+    struct audit_data *ad = (struct audit_data *)data;
+
+    if (!ad || !ad->name) {
+        ALOGE("No service manager audit data");
+        return 0;
+    }
+
+    snprintf(buf, len, "service=%s pid=%d uid=%d", ad->name, ad->pid, ad->uid);
     return 0;
 }
 
diff --git a/include/android/keycodes.h b/include/android/keycodes.h
index ac07190..67e28da 100644
--- a/include/android/keycodes.h
+++ b/include/android/keycodes.h
@@ -751,7 +751,13 @@
      * Steps media backward one from at a time. */
     AKEYCODE_MEDIA_STEP_BACKWARD = 275,
     /** Put device to sleep unless a wakelock is held. */
-    AKEYCODE_SOFT_SLEEP = 276
+    AKEYCODE_SOFT_SLEEP = 276,
+    /** Cut key. */
+    AKEYCODE_CUT = 277,
+    /** Copy key. */
+    AKEYCODE_COPY = 278,
+    /** Paste key. */
+    AKEYCODE_PASTE = 279
 
     // 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/binder/IBinder.h b/include/binder/IBinder.h
index 43b6543..97f1fc2 100644
--- a/include/binder/IBinder.h
+++ b/include/binder/IBinder.h
@@ -33,6 +33,7 @@
 class BpBinder;
 class IInterface;
 class Parcel;
+class IResultReceiver;
 
 /**
  * Base class and low-level protocol for a remotable object.
@@ -50,6 +51,7 @@
 
         PING_TRANSACTION        = B_PACK_CHARS('_','P','N','G'),
         DUMP_TRANSACTION        = B_PACK_CHARS('_','D','M','P'),
+        SHELL_COMMAND_TRANSACTION = B_PACK_CHARS('_','C','M','D'),
         INTERFACE_TRANSACTION   = B_PACK_CHARS('_', 'N', 'T', 'F'),
         SYSPROPS_TRANSACTION    = B_PACK_CHARS('_', 'S', 'P', 'R'),
 
@@ -75,6 +77,9 @@
     virtual bool            isBinderAlive() const = 0;
     virtual status_t        pingBinder() = 0;
     virtual status_t        dump(int fd, const Vector<String16>& args) = 0;
+    static  status_t        shellCommand(const sp<IBinder>& target, int in, int out, int err,
+                                         Vector<String16>& args,
+                                         const sp<IResultReceiver>& resultReceiver);
 
     virtual status_t        transact(   uint32_t code,
                                         const Parcel& data,
diff --git a/include/binder/IResultReceiver.h b/include/binder/IResultReceiver.h
new file mode 100644
index 0000000..02dc6a6
--- /dev/null
+++ b/include/binder/IResultReceiver.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+//
+#ifndef ANDROID_IRESULT_RECEIVER_H
+#define ANDROID_IRESULT_RECEIVER_H
+
+#include <binder/IInterface.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class IResultReceiver : public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(ResultReceiver);
+
+    virtual void send(int32_t resultCode) = 0;
+
+    enum {
+        OP_SEND = IBinder::FIRST_CALL_TRANSACTION
+    };
+};
+
+// ----------------------------------------------------------------------
+
+class BnResultReceiver : public BnInterface<IResultReceiver>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IRESULT_RECEIVER_H
+
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 3ada1e9..7b80dd9 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_PARCEL_H
 #define ANDROID_PARCEL_H
 
+#include <vector>
+
 #include <cutils/native_handle.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
@@ -108,6 +110,18 @@
     status_t            writeWeakBinder(const wp<IBinder>& val);
     status_t            writeInt32Array(size_t len, const int32_t *val);
     status_t            writeByteArray(size_t len, const uint8_t *val);
+    status_t            writeBool(bool val);
+    status_t            writeChar(char16_t val);
+    status_t            writeByte(int8_t val);
+
+    status_t            writeByteVector(const std::vector<int8_t>& val);
+    status_t            writeInt32Vector(const std::vector<int32_t>& val);
+    status_t            writeInt64Vector(const std::vector<int64_t>& val);
+    status_t            writeFloatVector(const std::vector<float>& val);
+    status_t            writeDoubleVector(const std::vector<double>& val);
+    status_t            writeBoolVector(const std::vector<bool>& val);
+    status_t            writeCharVector(const std::vector<char16_t>& val);
+    status_t            writeString16Vector(const std::vector<String16>& val);
 
     template<typename T>
     status_t            write(const Flattenable<T>& val);
@@ -118,7 +132,7 @@
 
     // Place a native_handle into the parcel (the native_handle's file-
     // descriptors are dup'ed, so it is safe to delete the native_handle
-    // when this function returns). 
+    // when this function returns).
     // Doesn't take ownership of the native_handle.
     status_t            writeNativeHandle(const native_handle* handle);
     
@@ -169,14 +183,30 @@
     status_t            readDouble(double *pArg) const;
     intptr_t            readIntPtr() const;
     status_t            readIntPtr(intptr_t *pArg) const;
+    bool                readBool() const;
+    status_t            readBool(bool *pArg) const;
+    char16_t            readChar() const;
+    status_t            readChar(char16_t *pArg) const;
+    int8_t              readByte() const;
+    status_t            readByte(int8_t *pArg) const;
 
     const char*         readCString() const;
     String8             readString8() const;
     String16            readString16() const;
+    status_t            readString16(String16* pArg) const;
     const char16_t*     readString16Inplace(size_t* outLen) const;
     sp<IBinder>         readStrongBinder() const;
     wp<IBinder>         readWeakBinder() const;
 
+    status_t            readByteVector(std::vector<int8_t>* val) const;
+    status_t            readInt32Vector(std::vector<int32_t>* val) const;
+    status_t            readInt64Vector(std::vector<int64_t>* val) const;
+    status_t            readFloatVector(std::vector<float>* val) const;
+    status_t            readDoubleVector(std::vector<double>* val) const;
+    status_t            readBoolVector(std::vector<bool>* val) const;
+    status_t            readCharVector(std::vector<char16_t>* val) const;
+    status_t            readString16Vector(std::vector<String16>* val) const;
+
     template<typename T>
     status_t            read(Flattenable<T>& val) const;
 
@@ -342,9 +372,11 @@
 
 private:
     size_t mBlobAshmemSize;
+    size_t mOpenAshmemSize;
 
 public:
     size_t getBlobAshmemSize() const;
+    size_t getOpenAshmemSize() const;
 };
 
 // ---------------------------------------------------------------------------
@@ -412,9 +444,9 @@
 
 // Generic acquire and release of objects.
 void acquire_object(const sp<ProcessState>& proc,
-                    const flat_binder_object& obj, const void* who);
+                    const flat_binder_object& obj, const void* who, size_t* outAshmemSize);
 void release_object(const sp<ProcessState>& proc,
-                    const flat_binder_object& obj, const void* who);
+                    const flat_binder_object& obj, const void* who, size_t* outAshmemSize);
 
 void flatten_binder(const sp<ProcessState>& proc,
                     const sp<IBinder>& binder, flat_binder_object* out);
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index be1874a..b8cba2f 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -113,14 +113,10 @@
     // allow for the asynchronous behavior. If it is not enabled queue/dequeue
     // calls may block.
     //
-    // This function should not be called when there are any currently dequeued
-    // buffer slots, doing so will result in a BAD_VALUE error.
-    //
     // Return of a value other than NO_ERROR means an error has occurred:
     // * NO_INIT - the buffer queue has been abandoned.
-    // * BAD_VALUE - one of the below conditions occurred:
-    //     * client has one or more buffers dequeued
-    //     * this call would cause the maxBufferCount value to be exceeded
+    // * BAD_VALUE - this call would cause the maxBufferCount value to be
+    //               exceeded
     virtual status_t setAsyncMode(bool async) = 0;
 
     // dequeueBuffer requests a new buffer slot for the client to use. Ownership
diff --git a/include/input/Input.h b/include/input/Input.h
index 093219a..aca8112 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 efc1687..b7012eb 100644
--- a/include/input/InputEventLabels.h
+++ b/include/input/InputEventLabels.h
@@ -316,6 +316,9 @@
     DEFINE_KEYCODE(MEDIA_STEP_FORWARD),
     DEFINE_KEYCODE(MEDIA_STEP_BACKWARD),
     DEFINE_KEYCODE(SOFT_SLEEP),
+    DEFINE_KEYCODE(CUT),
+    DEFINE_KEYCODE(COPY),
+    DEFINE_KEYCODE(PASTE),
 
     { NULL, 0 }
 };
diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h
index 111139b..7935927 100644
--- a/include/input/KeyCharacterMap.h
+++ b/include/input/KeyCharacterMap.h
@@ -31,6 +31,9 @@
 #include <utils/Unicode.h>
 #include <utils/RefBase.h>
 
+// Maximum number of keys supported by KeyCharacterMaps
+#define MAX_KEYS 8192
+
 namespace android {
 
 /**
@@ -124,6 +127,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 +159,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/binder/Android.mk b/libs/binder/Android.mk
index ce29ea6..19298e2 100644
--- a/libs/binder/Android.mk
+++ b/libs/binder/Android.mk
@@ -27,6 +27,7 @@
     IPCThreadState.cpp \
     IPermissionController.cpp \
     IProcessInfoService.cpp \
+    IResultReceiver.cpp \
     ProcessInfoService.cpp \
     IServiceManager.cpp \
     MemoryDealer.cpp \
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index e39093d..c4d47ca 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -20,6 +20,7 @@
 #include <utils/misc.h>
 #include <binder/BpBinder.h>
 #include <binder/IInterface.h>
+#include <binder/IResultReceiver.h>
 #include <binder/Parcel.h>
 
 #include <stdio.h>
@@ -59,6 +60,24 @@
     return false;
 }
 
+
+status_t IBinder::shellCommand(const sp<IBinder>& target, int in, int out, int err,
+    Vector<String16>& args, const sp<IResultReceiver>& resultReceiver)
+{
+    Parcel send;
+    Parcel reply;
+    send.writeFileDescriptor(in);
+    send.writeFileDescriptor(out);
+    send.writeFileDescriptor(err);
+    const size_t numArgs = args.size();
+    send.writeInt32(numArgs);
+    for (size_t i = 0; i < numArgs; i++) {
+        send.writeString16(args[i]);
+    }
+    send.writeStrongBinder(resultReceiver != NULL ? IInterface::asBinder(resultReceiver) : NULL);
+    return target->transact(SHELL_COMMAND_TRANSACTION, send, &reply);
+}
+
 // ---------------------------------------------------------------------------
 
 class BBinder::Extras
@@ -129,7 +148,7 @@
     return INVALID_OPERATION;
 }
 
-    status_t BBinder::dump(int /*fd*/, const Vector<String16>& /*args*/)
+status_t BBinder::dump(int /*fd*/, const Vector<String16>& /*args*/)
 {
     return NO_ERROR;
 }
@@ -204,6 +223,25 @@
             return dump(fd, args);
         }
 
+        case SHELL_COMMAND_TRANSACTION: {
+            int in = data.readFileDescriptor();
+            int out = data.readFileDescriptor();
+            int err = data.readFileDescriptor();
+            int argc = data.readInt32();
+            Vector<String16> args;
+            for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
+               args.add(data.readString16());
+            }
+            sp<IResultReceiver> resultReceiver = IResultReceiver::asInterface(
+                    data.readStrongBinder());
+
+            // XXX can't add virtuals until binaries are updated.
+            //return shellCommand(in, out, err, args, resultReceiver);
+            if (resultReceiver != NULL) {
+                resultReceiver->send(INVALID_OPERATION);
+            }
+        }
+
         case SYSPROPS_TRANSACTION: {
             report_sysprop_change();
             return NO_ERROR;
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 345ba20..c0e0296 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -20,6 +20,7 @@
 #include <binder/BpBinder.h>
 
 #include <binder/IPCThreadState.h>
+#include <binder/IResultReceiver.h>
 #include <utils/Log.h>
 
 #include <stdio.h>
diff --git a/libs/binder/Debug.cpp b/libs/binder/Debug.cpp
index bdb7182..a8f2da5 100644
--- a/libs/binder/Debug.cpp
+++ b/libs/binder/Debug.cpp
@@ -138,7 +138,7 @@
         *pos = 0;
         return pos;
     }
-    
+
     if( fullContext ) {
         *pos++ = '0';
         *pos++ = 'x';
@@ -167,21 +167,21 @@
     if (func == NULL) func = defaultPrintFunc;
 
     size_t offset;
-    
+
     unsigned char *pos = (unsigned char *)buf;
-    
+
     if (pos == NULL) {
         if (singleLineBytesCutoff < 0) func(cookie, "\n");
         func(cookie, "(NULL)");
         return;
     }
-    
+
     if (length == 0) {
         if (singleLineBytesCutoff < 0) func(cookie, "\n");
         func(cookie, "(empty)");
         return;
     }
-    
+
     if ((int32_t)length < 0) {
         if (singleLineBytesCutoff < 0) func(cookie, "\n");
         char buf[64];
@@ -189,12 +189,12 @@
         func(cookie, buf);
         return;
     }
-    
+
     char buffer[256];
     static const size_t maxBytesPerLine = (sizeof(buffer)-1-11-4)/(3+1);
-    
+
     if (bytesPerLine > maxBytesPerLine) bytesPerLine = maxBytesPerLine;
-    
+
     const bool oneLine = (int32_t)length <= singleLineBytesCutoff;
     bool newLine = false;
     if (cStyle) {
@@ -205,7 +205,7 @@
         func(cookie, "\n");
         newLine = true;
     }
-    
+
     for (offset = 0; ; offset += bytesPerLine, pos += bytesPerLine) {
         long remain = length;
 
@@ -217,21 +217,20 @@
 
         size_t index;
         size_t word;
-        
+
         for (word = 0; word < bytesPerLine; ) {
 
             const size_t startIndex = word+(alignment-(alignment?1:0));
-            const ssize_t dir = -1;
 
             for (index = 0; index < alignment || (alignment == 0 && index < bytesPerLine); index++) {
-            
+
                 if (!cStyle) {
                     if (index == 0 && word > 0 && alignment > 0) {
                         *c++ = ' ';
                     }
-                
+
                     if (remain-- > 0) {
-                        const unsigned char val = *(pos+startIndex+(index*dir));
+                        const unsigned char val = *(pos+startIndex-index);
                         *c++ = makehexdigit(val>>4);
                         *c++ = makehexdigit(val);
                     } else if (!oneLine) {
@@ -248,14 +247,14 @@
                             *c++ = '0';
                             *c++ = 'x';
                         }
-                        const unsigned char val = *(pos+startIndex+(index*dir));
+                        const unsigned char val = *(pos+startIndex-index);
                         *c++ = makehexdigit(val>>4);
                         *c++ = makehexdigit(val);
                         remain--;
                     }
                 }
             }
-            
+
             word += index;
         }
 
@@ -272,7 +271,7 @@
                     *c++ = ' ';
                 }
             }
-            
+
             *c++ = '\'';
             if (length > bytesPerLine) *c++ = '\n';
         } else {
@@ -284,7 +283,7 @@
         *c = 0;
         func(cookie, buffer);
         newLine = true;
-        
+
         if (length <= bytesPerLine) break;
         length -= bytesPerLine;
     }
diff --git a/libs/binder/IResultReceiver.cpp b/libs/binder/IResultReceiver.cpp
new file mode 100644
index 0000000..2a22b69
--- /dev/null
+++ b/libs/binder/IResultReceiver.cpp
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "ResultReceiver"
+
+#include <binder/IResultReceiver.h>
+
+#include <utils/Log.h>
+#include <binder/Parcel.h>
+#include <utils/String8.h>
+
+#include <private/binder/Static.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class BpResultReceiver : public BpInterface<IResultReceiver>
+{
+public:
+    BpResultReceiver(const sp<IBinder>& impl)
+        : BpInterface<IResultReceiver>(impl)
+    {
+    }
+
+    virtual void send(int32_t resultCode) {
+        Parcel data;
+        data.writeInterfaceToken(IResultReceiver::getInterfaceDescriptor());
+        data.writeInt32(resultCode);
+        remote()->transact(OP_SEND, data, NULL, IBinder::FLAG_ONEWAY);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(ResultReceiver, "com.android.internal.os.IResultReceiver");
+
+// ----------------------------------------------------------------------
+
+status_t BnResultReceiver::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case OP_SEND: {
+            CHECK_INTERFACE(IResultReceiver, data, reply);
+            int32_t resultCode = data.readInt32();
+            send(resultCode);
+            if (reply != NULL) {
+                reply->writeNoException();
+            }
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}; // namespace android
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 134aadc..61f24d6 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -33,7 +33,7 @@
 sp<IServiceManager> defaultServiceManager()
 {
     if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
-    
+
     {
         AutoMutex _l(gDefaultServiceManagerLock);
         while (gDefaultServiceManager == NULL) {
@@ -43,7 +43,7 @@
                 sleep(1);
         }
     }
-    
+
     return gDefaultServiceManager;
 }
 
@@ -67,11 +67,16 @@
 
 bool checkPermission(const String16& permission, pid_t pid, uid_t uid)
 {
+#ifdef __BRILLO__
+    // Brillo doesn't currently run ActivityManager or support framework permissions.
+    return true;
+#endif
+
     sp<IPermissionController> pc;
     gDefaultServiceManagerLock.lock();
     pc = gPermissionController;
     gDefaultServiceManagerLock.unlock();
-    
+
     int64_t startTime = 0;
 
     while (true) {
@@ -85,14 +90,14 @@
                 }
                 return res;
             }
-            
+
             // Is this a permission failure, or did the controller go away?
             if (IInterface::asBinder(pc)->isBinderAlive()) {
                 ALOGW("Permission failure: %s from uid=%d pid=%d",
                         String8(permission).string(), uid, pid);
                 return false;
             }
-            
+
             // Object is dead!
             gDefaultServiceManagerLock.lock();
             if (gPermissionController == pc) {
@@ -100,7 +105,7 @@
             }
             gDefaultServiceManagerLock.unlock();
         }
-    
+
         // Need to retrieve the permission controller.
         sp<IBinder> binder = defaultServiceManager()->checkService(_permission);
         if (binder == NULL) {
@@ -113,7 +118,7 @@
             sleep(1);
         } else {
             pc = interface_cast<IPermissionController>(binder);
-            // Install the new permission controller, and try again.        
+            // Install the new permission controller, and try again.
             gDefaultServiceManagerLock.lock();
             gPermissionController = pc;
             gDefaultServiceManagerLock.unlock();
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 8315c58..5a62fce 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -96,7 +96,7 @@
 };
 
 void acquire_object(const sp<ProcessState>& proc,
-    const flat_binder_object& obj, const void* who)
+    const flat_binder_object& obj, const void* who, size_t* outAshmemSize)
 {
     switch (obj.type) {
         case BINDER_TYPE_BINDER:
@@ -123,8 +123,13 @@
             return;
         }
         case BINDER_TYPE_FD: {
-            // intentionally blank -- nothing to do to acquire this, but we do
-            // recognize it as a legitimate object type.
+            if (obj.cookie != 0) {
+                // If we own an ashmem fd, keep track of how much memory it refers to.
+                int size = ashmem_get_size_region(obj.handle);
+                if (size > 0) {
+                    *outAshmemSize += size;
+                }
+            }
             return;
         }
     }
@@ -133,7 +138,7 @@
 }
 
 void release_object(const sp<ProcessState>& proc,
-    const flat_binder_object& obj, const void* who)
+    const flat_binder_object& obj, const void* who, size_t* outAshmemSize)
 {
     switch (obj.type) {
         case BINDER_TYPE_BINDER:
@@ -160,7 +165,14 @@
             return;
         }
         case BINDER_TYPE_FD: {
-            if (obj.cookie != 0) close(obj.handle);
+            if (obj.cookie != 0) {
+                int size = ashmem_get_size_region(obj.handle);
+                if (size > 0) {
+                    *outAshmemSize -= size;
+                }
+
+                close(obj.handle);
+            }
             return;
         }
     }
@@ -502,7 +514,7 @@
 
             flat_binder_object* flat
                 = reinterpret_cast<flat_binder_object*>(mData + off);
-            acquire_object(proc, *flat, this);
+            acquire_object(proc, *flat, this, &mOpenAshmemSize);
 
             if (flat->type == BINDER_TYPE_FD) {
                 // If this is a file descriptor, we need to dup it so the
@@ -715,6 +727,190 @@
     return NULL;
 }
 
+status_t Parcel::writeByteVector(const std::vector<int8_t>& val)
+{
+    if (val.size() > std::numeric_limits<int32_t>::max()) {
+        return BAD_VALUE;
+    }
+
+    status_t status = writeInt32(val.size());
+
+    if (status != OK) {
+        return status;
+    }
+
+    for (const auto& item : val) {
+        status = writeByte(item);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val)
+{
+    if (val.size() > std::numeric_limits<int32_t>::max()) {
+        return BAD_VALUE;
+    }
+
+    status_t status = writeInt32(val.size());
+
+    if (status != OK) {
+        return status;
+    }
+
+    for (const auto& item : val) {
+        status = writeInt32(item);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+status_t Parcel::writeInt64Vector(const std::vector<int64_t>& val)
+{
+    if (val.size() > std::numeric_limits<int32_t>::max()) {
+        return BAD_VALUE;
+    }
+
+    status_t status = writeInt32(val.size());
+
+    if (status != OK) {
+        return status;
+    }
+
+    for (const auto& item : val) {
+        status = writeInt64(item);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+status_t Parcel::writeFloatVector(const std::vector<float>& val)
+{
+    if (val.size() > std::numeric_limits<int32_t>::max()) {
+        return BAD_VALUE;
+    }
+
+    status_t status = writeInt32(val.size());
+
+    if (status != OK) {
+        return status;
+    }
+
+    for (const auto& item : val) {
+        status = writeFloat(item);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+status_t Parcel::writeDoubleVector(const std::vector<double>& val)
+{
+    if (val.size() > std::numeric_limits<int32_t>::max()) {
+        return BAD_VALUE;
+    }
+
+    status_t status = writeInt32(val.size());
+
+    if (status != OK) {
+        return status;
+    }
+
+    for (const auto& item : val) {
+        status = writeDouble(item);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+status_t Parcel::writeBoolVector(const std::vector<bool>& val)
+{
+    if (val.size() > std::numeric_limits<int32_t>::max()) {
+        return BAD_VALUE;
+    }
+
+    status_t status = writeInt32(val.size());
+
+    if (status != OK) {
+        return status;
+    }
+
+    for (const auto& item : val) {
+        status = writeBool(item);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+status_t Parcel::writeCharVector(const std::vector<char16_t>& val)
+{
+    if (val.size() > std::numeric_limits<int32_t>::max()) {
+        return BAD_VALUE;
+    }
+
+    status_t status = writeInt32(val.size());
+
+    if (status != OK) {
+        return status;
+    }
+
+    for (const auto& item : val) {
+        status = writeChar(item);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+status_t Parcel::writeString16Vector(const std::vector<String16>& val)
+{
+    if (val.size() > std::numeric_limits<int32_t>::max()) {
+        return BAD_VALUE;
+    }
+
+    status_t status = writeInt32(val.size());
+
+    if (status != OK) {
+        return status;
+    }
+
+    for (const auto& item : val) {
+        status = writeString16(item);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
 status_t Parcel::writeInt32(int32_t val)
 {
     return writeAligned(val);
@@ -758,6 +954,21 @@
     return ret;
 }
 
+status_t Parcel::writeBool(bool val)
+{
+    return writeInt32(int32_t(val));
+}
+
+status_t Parcel::writeChar(char16_t val)
+{
+    return writeInt32(int32_t(val));
+}
+
+status_t Parcel::writeByte(int8_t val)
+{
+    return writeInt32(int32_t(val));
+}
+
 status_t Parcel::writeInt64(int64_t val)
 {
     return writeAligned(val);
@@ -1024,7 +1235,7 @@
         // Need to write meta-data?
         if (nullMetaData || val.binder != 0) {
             mObjects[mObjectsSize] = mDataPos;
-            acquire_object(ProcessState::self(), val, this);
+            acquire_object(ProcessState::self(), val, this, &mOpenAshmemSize);
             mObjectsSize++;
         }
 
@@ -1132,6 +1343,232 @@
     return err;
 }
 
+status_t Parcel::readByteVector(std::vector<int8_t>* val) const {
+    val->clear();
+
+    int32_t size;
+    status_t status = readInt32(&size);
+
+    if (status != OK) {
+        return status;
+    }
+
+    if (size < 0) {
+        return BAD_VALUE;
+    }
+
+    val->resize(size);
+
+    for (auto& v : *val) {
+        status = readByte(&v);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+status_t Parcel::readInt32Vector(std::vector<int32_t>* val) const {
+    val->clear();
+
+    int32_t size;
+    status_t status = readInt32(&size);
+
+    if (status != OK) {
+        return status;
+    }
+
+    if (size < 0) {
+        return BAD_VALUE;
+    }
+
+    val->resize(size);
+
+    for (auto& v: *val) {
+        status = readInt32(&v);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+status_t Parcel::readInt64Vector(std::vector<int64_t>* val) const {
+    val->clear();
+
+    int32_t size;
+    status_t status = readInt32(&size);
+
+    if (status != OK) {
+        return status;
+    }
+
+    if (size < 0) {
+        return BAD_VALUE;
+    }
+
+    val->resize(size);
+
+    for (auto& v : *val) {
+        status = readInt64(&v);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+status_t Parcel::readFloatVector(std::vector<float>* val) const {
+    val->clear();
+
+    int32_t size;
+    status_t status = readInt32(&size);
+
+    if (status != OK) {
+        return status;
+    }
+
+    if (size < 0) {
+        return BAD_VALUE;
+    }
+
+    val->resize(size);
+
+    for (auto& v : *val) {
+        status = readFloat(&v);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+status_t Parcel::readDoubleVector(std::vector<double>* val) const {
+    val->clear();
+
+    int32_t size;
+    status_t status = readInt32(&size);
+
+    if (status != OK) {
+        return status;
+    }
+
+    if (size < 0) {
+        return BAD_VALUE;
+    }
+
+    val->resize(size);
+
+    for (auto& v : *val) {
+        status = readDouble(&v);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+status_t Parcel::readBoolVector(std::vector<bool>* val) const {
+    val->clear();
+
+    int32_t size;
+    status_t status = readInt32(&size);
+
+    if (status != OK) {
+        return status;
+    }
+
+    if (size < 0) {
+        return BAD_VALUE;
+    }
+
+    val->resize(size);
+
+    /* C++ bool handling means a vector of bools isn't necessarily addressable
+     * (we might use individual bits)
+     */
+    for (int32_t i = 0; i < size; size++) {
+        bool data;
+        status = readBool(&data);
+        (*val)[i] = data;
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+status_t Parcel::readCharVector(std::vector<char16_t>* val) const {
+    val->clear();
+
+    int32_t size;
+    status_t status = readInt32(&size);
+
+    if (status != OK) {
+        return status;
+    }
+
+    if (size < 0) {
+        return BAD_VALUE;
+    }
+
+    val->resize(size);
+
+    for (auto& v : *val) {
+        status = readChar(&v);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+status_t Parcel::readString16Vector(std::vector<String16>* val) const {
+    val->clear();
+
+    int32_t size;
+    status_t status = readInt32(&size);
+
+    if (status != OK) {
+        return status;
+    }
+
+    if (size < 0) {
+        return BAD_VALUE;
+    }
+
+    val->reserve(size);
+
+    while (size-- > 0) {
+        const char16_t *data;
+        size_t size;
+        data = readString16Inplace(&size);
+
+        if (data == nullptr) {
+            return UNKNOWN_ERROR;
+        }
+
+        val->emplace_back(data, size);
+    }
+
+    return OK;
+}
+
+
 status_t Parcel::readInt32(int32_t *pArg) const
 {
     return readAligned(pArg);
@@ -1250,6 +1687,44 @@
     return readAligned<intptr_t>();
 }
 
+status_t Parcel::readBool(bool *pArg) const
+{
+    int32_t tmp;
+    status_t ret = readInt32(&tmp);
+    *pArg = (tmp != 0);
+    return ret;
+}
+
+bool Parcel::readBool() const
+{
+    return readInt32() != 0;
+}
+
+status_t Parcel::readChar(char16_t *pArg) const
+{
+    int32_t tmp;
+    status_t ret = readInt32(&tmp);
+    *pArg = char16_t(tmp);
+    return ret;
+}
+
+char16_t Parcel::readChar() const
+{
+    return char16_t(readInt32());
+}
+
+status_t Parcel::readByte(int8_t *pArg) const
+{
+    int32_t tmp;
+    status_t ret = readInt32(&tmp);
+    *pArg = int8_t(tmp);
+    return ret;
+}
+
+int8_t Parcel::readByte() const
+{
+    return int8_t(readInt32());
+}
 
 const char* Parcel::readCString() const
 {
@@ -1288,6 +1763,19 @@
     return String16();
 }
 
+status_t Parcel::readString16(String16* pArg) const
+{
+    size_t len;
+    const char16_t* str = readString16Inplace(&len);
+    if (str) {
+        pArg->setTo(str, len);
+        return 0;
+    } else {
+        *pArg = String16();
+        return UNKNOWN_ERROR;
+    }
+}
+
 const char16_t* Parcel::readString16Inplace(size_t* outLen) const
 {
     int32_t size = readInt32();
@@ -1607,7 +2095,7 @@
         i--;
         const flat_binder_object* flat
             = reinterpret_cast<flat_binder_object*>(data+objects[i]);
-        release_object(proc, *flat, this);
+        release_object(proc, *flat, this, &mOpenAshmemSize);
     }
 }
 
@@ -1621,7 +2109,7 @@
         i--;
         const flat_binder_object* flat
             = reinterpret_cast<flat_binder_object*>(data+objects[i]);
-        acquire_object(proc, *flat, this);
+        acquire_object(proc, *flat, this, &mOpenAshmemSize);
     }
 }
 
@@ -1809,7 +2297,7 @@
                     // will need to rescan because we may have lopped off the only FDs
                     mFdsKnown = false;
                 }
-                release_object(proc, *flat, this);
+                release_object(proc, *flat, this, &mOpenAshmemSize);
             }
             binder_size_t* objects =
                 (binder_size_t*)realloc(mObjects, objectsSize*sizeof(binder_size_t));
@@ -1896,6 +2384,7 @@
     mAllowFds = true;
     mOwner = NULL;
     mBlobAshmemSize = 0;
+    mOpenAshmemSize = 0;
 }
 
 void Parcel::scanForFds() const
@@ -1918,6 +2407,11 @@
     return mBlobAshmemSize;
 }
 
+size_t Parcel::getOpenAshmemSize() const
+{
+    return mOpenAshmemSize;
+}
+
 // --- Parcel::Blob ---
 
 Parcel::Blob::Blob() :
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index deec330..0cb018c 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -159,14 +159,6 @@
             return NO_INIT;
         }
 
-        // There must be no dequeued buffers when changing the async mode.
-        for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
-            if (mSlots[s].mBufferState == BufferSlot::DEQUEUED) {
-                BQ_LOGE("setAsyncMode: buffer owned by producer");
-                return BAD_VALUE;
-            }
-        }
-
         if ((mCore->mMaxAcquiredBufferCount + mCore->mMaxDequeuedBufferCount +
                 (async || mCore->mDequeueBufferCannotBlock ? 1 : 0)) >
                 mCore->mMaxBufferCount) {
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index 81c0549..0a0fc4b 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -246,6 +246,11 @@
         break;
     }
 
+    // Set DATA_INJECTION flag here. Defined in HAL 1_4.
+    if (halVersion >= SENSORS_DEVICE_API_VERSION_1_4) {
+        mFlags |= (hwSensor->flags & DATA_INJECTION_MASK);
+    }
+
     // For the newer HALs log errors if reporting mask flags are set incorrectly.
     if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
         // Wake-up flag is set here.
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index 7455cd9..882b14c 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -616,10 +616,6 @@
                 TEST_PRODUCER_USAGE_BITS))) << "slot: " << dequeuedSlot;
     }
 
-    // Client has one or more buffers dequeued
-    EXPECT_EQ(BAD_VALUE, mProducer->setAsyncMode(false)) << "asyncMode: "
-            << false;
-
     // Abandon buffer queue
     ASSERT_OK(mConsumer->consumerDisconnect());
 
diff --git a/libs/gui/tests/SurfaceTextureGLThreadToGL_test.cpp b/libs/gui/tests/SurfaceTextureGLThreadToGL_test.cpp
index b4e25f3..c4d0aaa 100644
--- a/libs/gui/tests/SurfaceTextureGLThreadToGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGLThreadToGL_test.cpp
@@ -31,6 +31,8 @@
         }
     };
 
+    SetUpWindowAndContext();
+
     runProducerThread(new PT());
 
     mFC->waitForFrame();
@@ -50,6 +52,8 @@
         }
     };
 
+    SetUpWindowAndContext();
+
     runProducerThread(new PT());
 
     mFC->waitForFrame();
@@ -75,6 +79,8 @@
         }
     };
 
+    SetUpWindowAndContext();
+
     runProducerThread(new PT());
 
     for (int i = 0; i < NUM_ITERATIONS; i++) {
@@ -104,6 +110,8 @@
         }
     };
 
+    SetUpWindowAndContext();
+
     runProducerThread(new PT());
 
     for (int i = 0; i < NUM_ITERATIONS; i++) {
@@ -134,6 +142,8 @@
         }
     };
 
+    SetUpWindowAndContext();
+
     runProducerThread(new PT());
 
     // Allow three frames to be rendered and queued before starting the
diff --git a/libs/gui/tests/SurfaceTextureGLToGL.h b/libs/gui/tests/SurfaceTextureGLToGL.h
index 5a2eff3..5d43a48 100644
--- a/libs/gui/tests/SurfaceTextureGLToGL.h
+++ b/libs/gui/tests/SurfaceTextureGLToGL.h
@@ -34,7 +34,9 @@
 
     virtual void SetUp() {
         SurfaceTextureGLTest::SetUp();
+    }
 
+    void SetUpWindowAndContext() {
         mProducerEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
                 mANW.get(), NULL);
         ASSERT_EQ(EGL_SUCCESS, eglGetError());
diff --git a/libs/gui/tests/SurfaceTextureGLToGL_test.cpp b/libs/gui/tests/SurfaceTextureGLToGL_test.cpp
index b3f6066..c28b4d1 100644
--- a/libs/gui/tests/SurfaceTextureGLToGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGLToGL_test.cpp
@@ -33,6 +33,8 @@
     // to 2, and max acquired already defaults to 1.
     ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
 
+    SetUpWindowAndContext();
+
     // Do the producer side of things
     EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
             mProducerEglSurface, mProducerEglContext));
@@ -85,6 +87,8 @@
     // Set max dequeued to 2, and max acquired already defaults to 1.
     ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
 
+    SetUpWindowAndContext();
+
     // Do the producer side of things
     EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
             mProducerEglSurface, mProducerEglContext));
@@ -152,6 +156,7 @@
 }
 
 TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceUnrefsBuffers) {
+    SetUpWindowAndContext();
     sp<GraphicBuffer> buffers[2];
 
     // This test requires async mode to run on a single thread.
@@ -197,6 +202,7 @@
 }
 
 TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceAfterAbandonUnrefsBuffers) {
+    SetUpWindowAndContext();
     sp<GraphicBuffer> buffers[3];
 
     // This test requires async mode to run on a single thread.
@@ -254,6 +260,7 @@
 }
 
 TEST_F(SurfaceTextureGLToGLTest, EglMakeCurrentBeforeConsumerDeathUnrefsBuffers) {
+    SetUpWindowAndContext();
     sp<GraphicBuffer> buffer;
 
     EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
@@ -291,6 +298,7 @@
 }
 
 TEST_F(SurfaceTextureGLToGLTest, EglMakeCurrentAfterConsumerDeathUnrefsBuffers) {
+    SetUpWindowAndContext();
     sp<GraphicBuffer> buffer;
 
     EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
@@ -335,6 +343,8 @@
     // Set max dequeued to 2, and max acquired already defaults to 1.
     ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
 
+    SetUpWindowAndContext();
+
     // Set the user buffer size.
     native_window_set_buffers_user_dimensions(mANW.get(), texWidth, texHeight);
 
@@ -393,6 +403,8 @@
     // Set max dequeued to 2, and max acquired already defaults to 1.
     ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
 
+    SetUpWindowAndContext();
+
     // Set the transform hint.
     mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
 
@@ -455,6 +467,8 @@
     // Set max dequeued to 2, and max acquired already defaults to 1.
     ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
 
+    SetUpWindowAndContext();
+
     // Set the transform hint.
     mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
 
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 0155007..a624663 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/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp
index 732ebd0..fe649fb 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) {
@@ -565,6 +607,10 @@
     if (parcel->errorCheck()) {
         return NULL;
     }
+    if (numKeys > MAX_KEYS) {
+        ALOGE("Too many keys in KeyCharacterMap (%d > %d)", numKeys, MAX_KEYS);
+        return NULL;
+    }
 
     for (size_t i = 0; i < numKeys; i++) {
         int32_t keyCode = parcel->readInt32();
@@ -584,6 +630,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 +639,7 @@
             behavior->metaState = metaState;
             behavior->character = character;
             behavior->fallbackKeyCode = fallbackKeyCode;
+            behavior->replacementKeyCode = replacementKeyCode;
             if (lastBehavior) {
                 lastBehavior->next = behavior;
             } else {
@@ -624,6 +672,7 @@
             parcel->writeInt32(behavior->metaState);
             parcel->writeInt32(behavior->character);
             parcel->writeInt32(behavior->fallbackKeyCode);
+            parcel->writeInt32(behavior->replacementKeyCode);
         }
         parcel->writeInt32(0);
     }
@@ -655,13 +704,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 +973,7 @@
     Behavior behavior;
     bool haveCharacter = false;
     bool haveFallback = false;
+    bool haveReplacement = false;
 
     do {
         char ch = mTokenizer->peekChar();
@@ -939,6 +990,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 +1005,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 +1021,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 +1100,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/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 72d390c..4fe0946 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -113,6 +113,7 @@
         GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
         allocator.free(handle);
     }
+    handle = NULL;
     mWrappedBuffer = 0;
 }
 
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 7c905ae..fb29276 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -592,15 +592,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..e10a101 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);
 }
 
@@ -2952,15 +2962,15 @@
     // multitouch.  The spot-based presentation relies on being able to accurately
     // locate two or more fingers on the touch pad.
     mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT)
-            ? Parameters::GESTURE_MODE_POINTER : Parameters::GESTURE_MODE_SPOTS;
+            ? Parameters::GESTURE_MODE_SINGLE_TOUCH : Parameters::GESTURE_MODE_MULTI_TOUCH;
 
     String8 gestureModeString;
     if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
             gestureModeString)) {
-        if (gestureModeString == "pointer") {
-            mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER;
-        } else if (gestureModeString == "spots") {
-            mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
+        if (gestureModeString == "single-touch") {
+            mParameters.gestureMode = Parameters::GESTURE_MODE_SINGLE_TOUCH;
+        } else if (gestureModeString == "multi-touch") {
+            mParameters.gestureMode = Parameters::GESTURE_MODE_MULTI_TOUCH;
         } else if (gestureModeString != "default") {
             ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
         }
@@ -3028,11 +3038,11 @@
     dump.append(INDENT3 "Parameters:\n");
 
     switch (mParameters.gestureMode) {
-    case Parameters::GESTURE_MODE_POINTER:
-        dump.append(INDENT4 "GestureMode: pointer\n");
+    case Parameters::GESTURE_MODE_SINGLE_TOUCH:
+        dump.append(INDENT4 "GestureMode: single-touch\n");
         break;
-    case Parameters::GESTURE_MODE_SPOTS:
-        dump.append(INDENT4 "GestureMode: spots\n");
+    case Parameters::GESTURE_MODE_MULTI_TOUCH:
+        dump.append(INDENT4 "GestureMode: multi-touch\n");
         break;
     default:
         assert(false);
@@ -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
@@ -4826,14 +4838,17 @@
     }
 
     // Update the pointer presentation and spots.
-    if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
-        mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
+    if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
+        mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
         if (finishPreviousGesture || cancelPreviousGesture) {
             mPointerController->clearSpots();
         }
-        mPointerController->setSpots(mPointerGesture.currentGestureCoords,
-                mPointerGesture.currentGestureIdToIndex,
-                mPointerGesture.currentGestureIdBits);
+
+        if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
+            mPointerController->setSpots(mPointerGesture.currentGestureCoords,
+                     mPointerGesture.currentGestureIdToIndex,
+                     mPointerGesture.currentGestureIdBits);
+        }
     } else {
         mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
     }
@@ -4842,9 +4857,8 @@
     switch (mPointerGesture.currentGestureMode) {
     case PointerGesture::NEUTRAL:
     case PointerGesture::QUIET:
-        if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
-                && (mPointerGesture.lastGestureMode == PointerGesture::SWIPE
-                        || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)) {
+        if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH
+                && mPointerGesture.lastGestureMode == PointerGesture::FREEFORM) {
             // Remind the user of where the pointer is after finishing a gesture with spots.
             mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
         }
@@ -4854,15 +4868,15 @@
     case PointerGesture::BUTTON_CLICK_OR_DRAG:
     case PointerGesture::HOVER:
     case PointerGesture::PRESS:
+    case PointerGesture::SWIPE:
         // Unfade the pointer when the current gesture manipulates the
         // area directly under the pointer.
         mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
         break;
-    case PointerGesture::SWIPE:
     case PointerGesture::FREEFORM:
         // Fade the pointer when the current gesture manipulates a different
         // area and there are spots to guide the user experience.
-        if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
+        if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
             mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
         } else {
             mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index 7cb4680..3a5c76f 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);
 
@@ -1306,8 +1305,8 @@
         bool hasButtonUnderPad;
 
         enum GestureMode {
-            GESTURE_MODE_POINTER,
-            GESTURE_MODE_SPOTS,
+            GESTURE_MODE_SINGLE_TOUCH,
+            GESTURE_MODE_MULTI_TOUCH,
         };
         GestureMode gestureMode;
 
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;
             }
         }