SF: Make screenshot surface async
am: 605d15afbb

Change-Id: Id24c7ccb275dcad914bda83b825c71af90aac637
diff --git a/cmds/atrace/Android.mk b/cmds/atrace/Android.mk
index a787e95..bfb3838 100644
--- a/cmds/atrace/Android.mk
+++ b/cmds/atrace/Android.mk
@@ -16,6 +16,7 @@
     libcutils \
     libutils \
     libz \
+    libbase
 
 LOCAL_INIT_RC := atrace.rc
 
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index facf300..290d7a8 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -31,6 +31,8 @@
 #include <unistd.h>
 #include <zlib.h>
 
+#include <memory>
+
 #include <binder/IBinder.h>
 #include <binder/IServiceManager.h>
 #include <binder/Parcel.h>
@@ -41,6 +43,7 @@
 #include <utils/Timers.h>
 #include <utils/Tokenizer.h>
 #include <utils/Trace.h>
+#include <android-base/file.h>
 
 using namespace android;
 
@@ -532,11 +535,11 @@
 
 // Set the system property that indicates which apps should perform
 // application-level tracing.
-static bool setAppCmdlineProperty(const char* cmdline)
+static bool setAppCmdlineProperty(char* cmdline)
 {
     char buf[PROPERTY_KEY_MAX];
     int i = 0;
-    const char* start = cmdline;
+    char* start = cmdline;
     while (start != NULL) {
         if (i == MAX_PACKAGES) {
             fprintf(stderr, "error: only 16 packages could be traced at once\n");
@@ -586,24 +589,14 @@
 // kernel.
 static bool verifyKernelTraceFuncs(const char* funcs)
 {
-    int fd = open(k_ftraceFilterPath, O_RDONLY);
-    if (fd == -1) {
-        fprintf(stderr, "error opening %s: %s (%d)\n", k_ftraceFilterPath,
+    std::string buf;
+    if (!android::base::ReadFileToString(k_ftraceFilterPath, &buf)) {
+         fprintf(stderr, "error opening %s: %s (%d)\n", k_ftraceFilterPath,
             strerror(errno), errno);
-        return false;
+         return false;
     }
 
-    char buf[4097];
-    ssize_t n = read(fd, buf, 4096);
-    close(fd);
-    if (n == -1) {
-        fprintf(stderr, "error reading %s: %s (%d)\n", k_ftraceFilterPath,
-            strerror(errno), errno);
-        return false;
-    }
-
-    buf[n] = '\0';
-    String8 funcList = String8::format("\n%s", buf);
+    String8 funcList = String8::format("\n%s",buf.c_str());
 
     // Make sure that every function listed in funcs is in the list we just
     // read from the kernel, except for wildcard inputs.
@@ -623,7 +616,6 @@
         func = strtok(NULL, ",");
     }
     free(myFuncs);
-
     return ok;
 }
 
@@ -753,7 +745,7 @@
         }
         packageList += value;
     }
-    ok &= setAppCmdlineProperty(packageList.data());
+    ok &= setAppCmdlineProperty(&packageList[0]);
     ok &= pokeBinderServices();
 
     // Disable all the sysfs enables.  This is done as a separate loop from
@@ -852,30 +844,34 @@
 
     if (g_compress) {
         z_stream zs;
-        uint8_t *in, *out;
-        int result, flush;
-
         memset(&zs, 0, sizeof(zs));
-        result = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
+
+        int result = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
         if (result != Z_OK) {
             fprintf(stderr, "error initializing zlib: %d\n", result);
             close(traceFD);
             return;
         }
 
-        const size_t bufSize = 64*1024;
-        in = (uint8_t*)malloc(bufSize);
-        out = (uint8_t*)malloc(bufSize);
-        flush = Z_NO_FLUSH;
+        constexpr size_t bufSize = 64*1024;
+        std::unique_ptr<uint8_t> in(new uint8_t[bufSize]);
+        std::unique_ptr<uint8_t> out(new uint8_t[bufSize]);
+        if (!in || !out) {
+            fprintf(stderr, "couldn't allocate buffers\n");
+            close(traceFD);
+            return;
+        }
 
-        zs.next_out = out;
+        int flush = Z_NO_FLUSH;
+
+        zs.next_out = reinterpret_cast<Bytef*>(out.get());
         zs.avail_out = bufSize;
 
         do {
 
             if (zs.avail_in == 0) {
                 // More input is needed.
-                result = read(traceFD, in, bufSize);
+                result = read(traceFD, in.get(), bufSize);
                 if (result < 0) {
                     fprintf(stderr, "error reading trace: %s (%d)\n",
                             strerror(errno), errno);
@@ -884,14 +880,14 @@
                 } else if (result == 0) {
                     flush = Z_FINISH;
                 } else {
-                    zs.next_in = in;
+                    zs.next_in = reinterpret_cast<Bytef*>(in.get());
                     zs.avail_in = result;
                 }
             }
 
             if (zs.avail_out == 0) {
                 // Need to write the output.
-                result = write(outFd, out, bufSize);
+                result = write(outFd, out.get(), bufSize);
                 if ((size_t)result < bufSize) {
                     fprintf(stderr, "error writing deflated trace: %s (%d)\n",
                             strerror(errno), errno);
@@ -899,7 +895,7 @@
                     zs.avail_out = bufSize; // skip the final write
                     break;
                 }
-                zs.next_out = out;
+                zs.next_out = reinterpret_cast<Bytef*>(out.get());
                 zs.avail_out = bufSize;
             }
 
@@ -911,7 +907,7 @@
 
         if (zs.avail_out < bufSize) {
             size_t bytes = bufSize - zs.avail_out;
-            result = write(outFd, out, bytes);
+            result = write(outFd, out.get(), bytes);
             if ((size_t)result < bytes) {
                 fprintf(stderr, "error writing deflated trace: %s (%d)\n",
                         strerror(errno), errno);
@@ -922,9 +918,6 @@
         if (result != Z_OK) {
             fprintf(stderr, "error cleaning up zlib: %d\n", result);
         }
-
-        free(in);
-        free(out);
     } else {
         ssize_t sent = 0;
         while ((sent = sendfile(outFd, traceFD, NULL, 64*1024*1024)) > 0);
@@ -980,7 +973,7 @@
                     "  -k fname,...    trace the listed kernel functions\n"
                     "  -n              ignore signals\n"
                     "  -s N            sleep for N seconds before tracing [default 0]\n"
-                    "  -t N            trace for N seconds [defualt 5]\n"
+                    "  -t N            trace for N seconds [default 5]\n"
                     "  -z              compress the trace dump\n"
                     "  --async_start   start circular trace and return immediatly\n"
                     "  --async_dump    dump the current contents of circular trace buffer\n"
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index 791a7c4..2dc8787 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -16,7 +16,7 @@
 
 LOCAL_SHARED_LIBRARIES := libcutils liblog libselinux libbase
 # ZipArchive support, the order matters here to get all symbols.
-LOCAL_STATIC_LIBRARIES := libziparchive libz libmincrypt
+LOCAL_STATIC_LIBRARIES := libziparchive libz libcrypto_static
 LOCAL_HAL_STATIC_LIBRARIES := libdumpstate
 LOCAL_CFLAGS += -Wall -Werror -Wno-unused-parameter
 LOCAL_INIT_RC := dumpstate.rc
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 279c010..bce966d 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -35,6 +35,7 @@
 #include <unistd.h>
 
 #include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
 #include <cutils/properties.h>
 
 #include "private/android_filesystem_config.h"
@@ -43,10 +44,9 @@
 #include <cutils/log.h>
 
 #include "dumpstate.h"
-#include "ScopedFd.h"
 #include "ziparchive/zip_writer.h"
 
-#include "mincrypt/sha256.h"
+#include <openssl/sha.h>
 
 using android::base::StringPrintf;
 
@@ -629,8 +629,9 @@
 }
 
 bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
-    ScopedFd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
-    if (fd.get() == -1) {
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK
+            | O_CLOEXEC)));
+    if (fd == -1) {
         MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
         return false;
     }
@@ -702,7 +703,8 @@
     dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
     dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
     dump_file("MEMORY INFO", "/proc/meminfo");
-    run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-H", NULL);
+    run_command("CPU INFO", 10, "top", "-b", "-n", "1", "-H", "-s", "6",
+                "-o", "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name", NULL);
     run_command("PROCRANK", 20, SU_PATH, "root", "procrank", NULL);
     dump_file("VIRTUAL MEMORY STATS", "/proc/vmstat");
     dump_file("VMALLOC INFO", "/proc/vmallocinfo");
@@ -716,7 +718,8 @@
     dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
     dump_file("KERNEL SYNC", "/d/sync");
 
-    run_command("PROCESSES AND THREADS", 10, "ps", "-Z", "-t", "-p", "-P", NULL);
+    run_command("PROCESSES AND THREADS", 10, "ps", "-A", "-T", "-Z",
+                "-O", "pri,nice,rtprio,sched,pcy", NULL);
     run_command("LIBRANK", 10, SU_PATH, "root", "librank", NULL);
 
     run_command("PRINTENV", 10, "printenv", NULL);
@@ -1052,15 +1055,15 @@
 }
 
 static std::string SHA256_file_hash(std::string filepath) {
-    ScopedFd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC
-            | O_NOFOLLOW)));
-    if (fd.get() == -1) {
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
+            | O_CLOEXEC | O_NOFOLLOW)));
+    if (fd == -1) {
         MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
         return NULL;
     }
 
     SHA256_CTX ctx;
-    SHA256_init(&ctx);
+    SHA256_Init(&ctx);
 
     std::vector<uint8_t> buffer(65536);
     while (1) {
@@ -1072,13 +1075,14 @@
             return NULL;
         }
 
-        SHA256_update(&ctx, buffer.data(), bytes_read);
+        SHA256_Update(&ctx, buffer.data(), bytes_read);
     }
 
-    uint8_t hash[SHA256_DIGEST_SIZE];
-    memcpy(hash, SHA256_final(&ctx), SHA256_DIGEST_SIZE);
-    char hash_buffer[SHA256_DIGEST_SIZE * 2 + 1];
-    for(size_t i = 0; i < SHA256_DIGEST_SIZE; i++) {
+    uint8_t hash[SHA256_DIGEST_LENGTH];
+    SHA256_Final(hash, &ctx);
+
+    char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
+    for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
         sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
     }
     hash_buffer[sizeof(hash_buffer) - 1] = 0;
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 3c39129..b33d7ab 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -28,7 +28,6 @@
 #include <sys/capability.h>
 #include <sys/inotify.h>
 #include <sys/stat.h>
-#include <sys/sysconf.h>
 #include <sys/time.h>
 #include <sys/wait.h>
 #include <sys/klog.h>
@@ -181,7 +180,7 @@
 
 void for_each_pid(for_each_pid_func func, const char *header) {
     ON_DRY_RUN_RETURN();
-  __for_each_pid(for_each_pid_helper, header, (void *)func);
+    __for_each_pid(for_each_pid_helper, header, (void *) func);
 }
 
 static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
@@ -578,6 +577,7 @@
  * stuck.
  */
 int dump_file_from_fd(const char *title, const char *path, int fd) {
+    ON_DRY_RUN_RETURN(0);
     int flags = fcntl(fd, F_GETFL);
     if (flags == -1) {
         printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index f4044b2..2c37ea8 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -99,30 +99,47 @@
     return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME);
 }
 
+static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid,
+        const char* pkgname, const char* seinfo) {
+    if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) {
+        PLOG(ERROR) << "Failed to prepare " << path;
+        return -1;
+    }
+    if (selinux_android_setfilecon(path.c_str(), pkgname, seinfo, uid) < 0) {
+        PLOG(ERROR) << "Failed to setfilecon " << path;
+        return -1;
+    }
+    return 0;
+}
+
+static int prepare_app_dir(const std::string& parent, const char* name, mode_t target_mode,
+        uid_t uid, const char* pkgname, const char* seinfo) {
+    return prepare_app_dir(StringPrintf("%s/%s", parent.c_str(), name), target_mode, uid, pkgname,
+            seinfo);
+}
+
 int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
         appid_t appid, const char* seinfo, int target_sdk_version) {
     uid_t uid = multiuser_get_uid(userid, appid);
-    int target_mode = target_sdk_version >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
+    mode_t target_mode = target_sdk_version >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
     if (flags & FLAG_STORAGE_CE) {
         auto path = create_data_user_ce_package_path(uuid, userid, pkgname);
-        if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) {
-            PLOG(ERROR) << "Failed to prepare " << path;
+        if (prepare_app_dir(path, target_mode, uid, pkgname, seinfo) ||
+                prepare_app_dir(path, "cache", 0771, uid, pkgname, seinfo) ||
+                prepare_app_dir(path, "code_cache", 0771, uid, pkgname, seinfo)) {
             return -1;
         }
-        if (selinux_android_setfilecon(path.c_str(), pkgname, seinfo, uid) < 0) {
-            PLOG(ERROR) << "Failed to setfilecon " << path;
+
+        // Remember inode numbers of cache directories so that we can clear
+        // contents while CE storage is locked
+        if (write_path_inode(path, "cache", kXattrInodeCache) ||
+                write_path_inode(path, "code_cache", kXattrInodeCodeCache)) {
             return -1;
         }
     }
     if (flags & FLAG_STORAGE_DE) {
         auto path = create_data_user_de_package_path(uuid, userid, pkgname);
-        if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) == -1) {
-            PLOG(ERROR) << "Failed to prepare " << path;
-            // TODO: include result once 25796509 is fixed
-            return 0;
-        }
-        if (selinux_android_setfilecon(path.c_str(), pkgname, seinfo, uid) < 0) {
-            PLOG(ERROR) << "Failed to setfilecon " << path;
+        if (prepare_app_dir(path, target_mode, uid, pkgname, seinfo)) {
             // TODO: include result once 25796509 is fixed
             return 0;
         }
@@ -266,24 +283,29 @@
 
 int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
         ino_t ce_data_inode) {
-    std::string suffix = "";
-    bool only_cache = false;
-    if (flags & FLAG_CLEAR_CACHE_ONLY) {
-        suffix = CACHE_DIR_POSTFIX;
-        only_cache = true;
-    } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
-        suffix = CODE_CACHE_DIR_POSTFIX;
-        only_cache = true;
-    }
-
     int res = 0;
     if (flags & FLAG_STORAGE_CE) {
-        auto path = create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode) + suffix;
+        auto path = create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode);
+        if (flags & FLAG_CLEAR_CACHE_ONLY) {
+            path = read_path_inode(path, "cache", kXattrInodeCache);
+        } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
+            path = read_path_inode(path, "code_cache", kXattrInodeCodeCache);
+        }
         if (access(path.c_str(), F_OK) == 0) {
             res |= delete_dir_contents(path);
         }
     }
     if (flags & FLAG_STORAGE_DE) {
+        std::string suffix = "";
+        bool only_cache = false;
+        if (flags & FLAG_CLEAR_CACHE_ONLY) {
+            suffix = CACHE_DIR_POSTFIX;
+            only_cache = true;
+        } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
+            suffix = CODE_CACHE_DIR_POSTFIX;
+            only_cache = true;
+        }
+
         auto path = create_data_user_de_package_path(uuid, userid, pkgname) + suffix;
         if (access(path.c_str(), F_OK) == 0) {
             // TODO: include result once 25796509 is fixed
@@ -627,14 +649,9 @@
 }
 
 int get_app_data_inode(const char *uuid, const char *pkgname, int userid, int flags, ino_t *inode) {
-    struct stat buf;
-    memset(&buf, 0, sizeof(buf));
     if (flags & FLAG_STORAGE_CE) {
         auto path = create_data_user_ce_package_path(uuid, userid, pkgname);
-        if (stat(path.c_str(), &buf) == 0) {
-            *inode = buf.st_ino;
-            return 0;
-        }
+        return get_path_inode(path, inode);
     }
     return -1;
 }
@@ -2076,7 +2093,6 @@
         PLOG(ERROR) << "Could not rename " << from << " to " << to;
         return false;
     }
-
     return true;
 }
 
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index facbc72..2bc3dfa 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -65,8 +65,8 @@
                              const char *oat_dir,
                              const char *apk_path,
                              const char *instruction_set) {
-    char *file_name_start;
-    char *file_name_end;
+    const char *file_name_start;
+    const char *file_name_end;
 
     file_name_start = strrchr(apk_path, '/');
     if (file_name_start == NULL) {
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index c838993..674f760 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
+#include <sys/xattr.h>
 
 #if defined(__APPLE__)
 #include <sys/mount.h>
@@ -39,7 +40,9 @@
 #ifndef LOG_TAG
 #define LOG_TAG "installd"
 #endif
+
 #define CACHE_NOISY(x) //x
+#define DEBUG_XATTRS 0
 
 using android::base::StringPrintf;
 
@@ -105,10 +108,12 @@
         while ((ent = readdir(dir))) {
             if (ent->d_ino == ce_data_inode) {
                 auto resolved = StringPrintf("%s/%s", user_path.c_str(), ent->d_name);
+#if DEBUG_XATTRS
                 if (resolved != fallback) {
                     LOG(DEBUG) << "Resolved path " << resolved << " for inode " << ce_data_inode
                             << " instead of " << fallback;
                 }
+#endif
                 closedir(dir);
                 return resolved;
             }
@@ -551,7 +556,7 @@
         if (res == NULL) {
             return NULL;
         }
-        CACHE_NOISY(ALOGI("Allocated large cache mem block: %p size %d", res, len));
+        CACHE_NOISY(ALOGI("Allocated large cache mem block: %p size %zu", res, len));
         // Link it into our list of blocks, not disrupting the current one.
         if (cache->memBlocks == NULL) {
             *(void**)res = NULL;
@@ -576,7 +581,7 @@
         cache->curMemBlockEnd = newBlock + CACHE_BLOCK_SIZE;
         nextPos = res + len;
     }
-    CACHE_NOISY(ALOGI("cache_malloc: ret %p size %d, block=%p, nextPos=%p",
+    CACHE_NOISY(ALOGI("cache_malloc: ret %p size %zu, block=%p, nextPos=%p",
             res, len, cache->memBlocks, nextPos));
     cache->curMemBlockAvail = nextPos;
     return res;
@@ -654,7 +659,7 @@
             cache->availFiles = newAvail;
             cache->files = newFiles;
         }
-        CACHE_NOISY(ALOGI("Setting file %p at position %d in array %p", file,
+        CACHE_NOISY(ALOGI("Setting file %p at position %zd in array %p", file,
                 cache->numFiles, cache->files));
         cache->files[cache->numFiles] = file;
         cache->numFiles++;
@@ -779,6 +784,99 @@
     return 0;
 }
 
+int get_path_inode(const std::string& path, ino_t *inode) {
+    struct stat buf;
+    memset(&buf, 0, sizeof(buf));
+    if (stat(path.c_str(), &buf) != 0) {
+        PLOG(WARNING) << "Failed to stat " << path;
+        return -1;
+    } else {
+        *inode = buf.st_ino;
+        return 0;
+    }
+}
+
+/**
+ * Write the inode of a specific child file into the given xattr on the
+ * parent directory. This allows you to find the child later, even if its
+ * name is encrypted.
+ */
+int write_path_inode(const std::string& parent, const char* name, const char* inode_xattr) {
+    ino_t inode = 0;
+    uint64_t inode_raw = 0;
+    auto path = StringPrintf("%s/%s", parent.c_str(), name);
+
+    if (get_path_inode(path, &inode) != 0) {
+        // Path probably doesn't exist yet; ignore
+        return 0;
+    }
+
+    // Check to see if already set correctly
+    if (getxattr(parent.c_str(), inode_xattr, &inode_raw, sizeof(inode_raw)) == sizeof(inode_raw)) {
+        if (inode_raw == inode) {
+            // Already set correctly; skip writing
+            return 0;
+        } else {
+            PLOG(WARNING) << "Mismatched inode value; found " << inode
+                    << " on disk but marked value was " << inode_raw << "; overwriting";
+        }
+    }
+
+    inode_raw = inode;
+    if (setxattr(parent.c_str(), inode_xattr, &inode_raw, sizeof(inode_raw), 0) != 0 && errno != EOPNOTSUPP) {
+        PLOG(ERROR) << "Failed to write xattr " << inode_xattr << " at " << parent;
+        return -1;
+    } else {
+        return 0;
+    }
+}
+
+/**
+ * Read the inode of a specific child file from the given xattr on the
+ * parent directory. Returns a currently valid path for that child, which
+ * might have an encrypted name.
+ */
+std::string read_path_inode(const std::string& parent, const char* name, const char* inode_xattr) {
+    ino_t inode = 0;
+    uint64_t inode_raw = 0;
+    auto fallback = StringPrintf("%s/%s", parent.c_str(), name);
+
+    // Lookup the inode value written earlier
+    if (getxattr(parent.c_str(), inode_xattr, &inode_raw, sizeof(inode_raw)) == sizeof(inode_raw)) {
+        inode = inode_raw;
+    }
+
+    // For testing purposes, rely on the inode when defined; this could be
+    // optimized to use access() in the future.
+    if (inode != 0) {
+        DIR* dir = opendir(parent.c_str());
+        if (dir == nullptr) {
+            PLOG(ERROR) << "Failed to opendir " << parent;
+            return fallback;
+        }
+
+        struct dirent* ent;
+        while ((ent = readdir(dir))) {
+            if (ent->d_ino == inode) {
+                auto resolved = StringPrintf("%s/%s", parent.c_str(), ent->d_name);
+#if DEBUG_XATTRS
+                if (resolved != fallback) {
+                    LOG(DEBUG) << "Resolved path " << resolved << " for inode " << inode
+                            << " instead of " << fallback;
+                }
+#endif
+                closedir(dir);
+                return resolved;
+            }
+        }
+        LOG(WARNING) << "Failed to resolve inode " << inode << "; using " << fallback;
+        closedir(dir);
+        return fallback;
+    } else {
+        return fallback;
+    }
+}
+
 void add_cache_files(cache_t* cache, const std::string& data_path) {
     DIR *d;
     struct dirent *de;
@@ -796,7 +894,6 @@
         if (de->d_type == DT_DIR) {
             DIR* subdir;
             const char *name = de->d_name;
-            char* pathpos;
 
                 /* always skip "." and ".." */
             if (name[0] == '.') {
@@ -804,16 +901,9 @@
                 if ((name[1] == '.') && (name[2] == 0)) continue;
             }
 
-            strcpy(dirname, basepath);
-            pathpos = dirname + strlen(dirname);
-            if ((*(pathpos-1)) != '/') {
-                *pathpos = '/';
-                pathpos++;
-                *pathpos = 0;
-            }
-
-            // TODO: also try searching using xattr when CE is locked
-            snprintf(pathpos, sizeof(dirname)-(pathpos-dirname), "%s/cache", name);
+            auto parent = StringPrintf("%s/%s", basepath, name);
+            auto resolved = read_path_inode(parent, "cache", kXattrInodeCache);
+            strcpy(dirname, resolved.c_str());
             CACHE_NOISY(ALOGI("Adding cache files from dir: %s\n", dirname));
 
             subdir = opendir(dirname);
@@ -931,16 +1021,16 @@
 {
     CACHE_NOISY(size_t i;)
 
-    CACHE_NOISY(ALOGI("clear_cache_files: %d dirs, %d files\n", cache->numDirs, cache->numFiles));
+    CACHE_NOISY(ALOGI("clear_cache_files: %zu dirs, %zu files\n", cache->numDirs, cache->numFiles));
     CACHE_NOISY(
         for (i=0; i<cache->numDirs; i++) {
             cache_dir_t* dir = cache->dirs[i];
-            ALOGI("dir #%d: %p %s parent=%p\n", i, dir, dir->name, dir->parent);
+            ALOGI("dir #%zu: %p %s parent=%p\n", i, dir, dir->name, dir->parent);
         })
     CACHE_NOISY(
         for (i=0; i<cache->numFiles; i++) {
             cache_file_t* file = cache->files[i];
-            ALOGI("file #%d: %p %s time=%d dir=%p\n", i, file, file->name,
+            ALOGI("file #%zu: %p %s time=%d dir=%p\n", i, file, file->name,
                     (int)file->modTime, file->dir);
         })
     void* block = cache->memBlocks;
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 60df356..8123e9b 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -62,6 +62,9 @@
     int8_t* curMemBlockEnd;
 } cache_t;
 
+constexpr const char* kXattrInodeCache = "user.inode_cache";
+constexpr const char* kXattrInodeCodeCache = "user.inode_code_cache";
+
 int create_pkg_path(char path[PKG_PATH_MAX],
                     const char *pkgname,
                     const char *postfix,
@@ -118,6 +121,11 @@
 
 cache_t* start_cache_collection();
 
+int get_path_inode(const std::string& path, ino_t *inode);
+
+int write_path_inode(const std::string& parent, const char* name, const char* inode_xattr);
+std::string read_path_inode(const std::string& parent, const char* name, const char* inode_xattr);
+
 void add_cache_files(cache_t* cache, const std::string& data_path);
 
 void clear_cache_files(const std::string& data_path, cache_t* cache, int64_t free_size);
diff --git a/cmds/servicemanager/binder.h b/cmds/servicemanager/binder.h
index 7915fc2..881ab07 100644
--- a/cmds/servicemanager/binder.h
+++ b/cmds/servicemanager/binder.h
@@ -5,7 +5,7 @@
 #define _BINDER_H_
 
 #include <sys/ioctl.h>
-#include <linux/binder.h>
+#include <linux/android/binder.h>
 
 struct binder_state;
 
diff --git a/include/binder/IInterface.h b/include/binder/IInterface.h
index 4ce3613..48c8b3b 100644
--- a/include/binder/IInterface.h
+++ b/include/binder/IInterface.h
@@ -105,7 +105,7 @@
 
 
 #define CHECK_INTERFACE(interface, data, reply)                         \
-    if (!data.checkInterface(this)) { return PERMISSION_DENIED; }       \
+    if (!(data).checkInterface(this)) { return PERMISSION_DENIED; }     \
 
 
 // ----------------------------------------------------------------------
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 1c355c4..a06fb4a 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -20,14 +20,14 @@
 #include <string>
 #include <vector>
 
+#include <android-base/unique_fd.h>
 #include <cutils/native_handle.h>
-#include <nativehelper/ScopedFd.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 #include <utils/String16.h>
 #include <utils/Vector.h>
 #include <utils/Flattenable.h>
-#include <linux/binder.h>
+#include <linux/android/binder.h>
 
 #include <binder/IInterface.h>
 #include <binder/Parcelable.h>
@@ -186,14 +186,14 @@
     // semantics of the smart file descriptor. A new descriptor will be
     // created, and will be closed when the parcel is destroyed.
     status_t            writeUniqueFileDescriptor(
-                            const ScopedFd& fd);
+                            const base::unique_fd& fd);
 
     // Place a vector of file desciptors into the parcel. Each descriptor is
     // dup'd as in writeDupFileDescriptor
     status_t            writeUniqueFileDescriptorVector(
-                            const std::unique_ptr<std::vector<ScopedFd>>& val);
+                            const std::unique_ptr<std::vector<base::unique_fd>>& val);
     status_t            writeUniqueFileDescriptorVector(
-                            const std::vector<ScopedFd>& val);
+                            const std::vector<base::unique_fd>& val);
 
     // Writes a blob to the parcel.
     // If the blob is small, then it is stored in-place, otherwise it is
@@ -246,12 +246,14 @@
 
     const char*         readCString() const;
     String8             readString8() const;
+    status_t            readString8(String8* pArg) const;
     String16            readString16() const;
     status_t            readString16(String16* pArg) const;
     status_t            readString16(std::unique_ptr<String16>* pArg) const;
     const char16_t*     readString16Inplace(size_t* outLen) const;
     sp<IBinder>         readStrongBinder() const;
     status_t            readStrongBinder(sp<IBinder>* val) const;
+    status_t            readNullableStrongBinder(sp<IBinder>* val) const;
     wp<IBinder>         readWeakBinder() const;
 
     template<typename T>
@@ -268,6 +270,9 @@
     template<typename T>
     status_t            readStrongBinder(sp<T>* val) const;
 
+    template<typename T>
+    status_t            readNullableStrongBinder(sp<T>* val) const;
+
     status_t            readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const;
     status_t            readStrongBinderVector(std::vector<sp<IBinder>>* val) const;
 
@@ -320,14 +325,14 @@
 
     // Retrieve a smart file descriptor from the parcel.
     status_t            readUniqueFileDescriptor(
-                            ScopedFd* val) const;
+                            base::unique_fd* val) const;
 
 
     // Retrieve a vector of smart file descriptors from the parcel.
     status_t            readUniqueFileDescriptorVector(
-                            std::unique_ptr<std::vector<ScopedFd>>* val) const;
+                            std::unique_ptr<std::vector<base::unique_fd>>* val) const;
     status_t            readUniqueFileDescriptorVector(
-                            std::vector<ScopedFd>* val) const;
+                            std::vector<base::unique_fd>* val) const;
 
     // Reads a blob from the parcel.
     // The caller should call release() on the blob after reading its contents.
@@ -574,6 +579,22 @@
     return ret;
 }
 
+template<typename T>
+status_t Parcel::readNullableStrongBinder(sp<T>* val) const {
+    sp<IBinder> tmp;
+    status_t ret = readNullableStrongBinder(&tmp);
+
+    if (ret == OK) {
+        *val = interface_cast<T>(tmp);
+
+        if (val->get() == nullptr && tmp.get() != nullptr) {
+            ret = UNKNOWN_ERROR;
+        }
+    }
+
+    return ret;
+}
+
 template<typename T, typename U>
 status_t Parcel::unsafeReadTypedVector(
         std::vector<T>* val,
diff --git a/include/binder/PersistableBundle.h b/include/binder/PersistableBundle.h
index fe5619f..322fef9 100644
--- a/include/binder/PersistableBundle.h
+++ b/include/binder/PersistableBundle.h
@@ -18,6 +18,7 @@
 #define ANDROID_PERSISTABLE_BUNDLE_H
 
 #include <map>
+#include <set>
 #include <vector>
 
 #include <binder/Parcelable.h>
@@ -79,6 +80,19 @@
     bool getStringVector(const String16& key, std::vector<String16>* out) const;
     bool getPersistableBundle(const String16& key, PersistableBundle* out) const;
 
+    /* Getters for all keys for each value type */
+    std::set<String16> getBooleanKeys() const;
+    std::set<String16> getIntKeys() const;
+    std::set<String16> getLongKeys() const;
+    std::set<String16> getDoubleKeys() const;
+    std::set<String16> getStringKeys() const;
+    std::set<String16> getBooleanVectorKeys() const;
+    std::set<String16> getIntVectorKeys() const;
+    std::set<String16> getLongVectorKeys() const;
+    std::set<String16> getDoubleVectorKeys() const;
+    std::set<String16> getStringVectorKeys() const;
+    std::set<String16> getPersistableBundleKeys() const;
+
     friend bool operator==(const PersistableBundle& lhs, const PersistableBundle& rhs) {
         return (lhs.mBoolMap == rhs.mBoolMap && lhs.mIntMap == rhs.mIntMap &&
                 lhs.mLongMap == rhs.mLongMap && lhs.mDoubleMap == rhs.mDoubleMap &&
diff --git a/include/binder/Status.h b/include/binder/Status.h
index ce947fa..dd61616 100644
--- a/include/binder/Status.h
+++ b/include/binder/Status.h
@@ -18,6 +18,7 @@
 #define ANDROID_BINDER_STATUS_H
 
 #include <cstdint>
+#include <sstream>
 
 #include <binder/Parcel.h>
 #include <utils/String8.h>
@@ -71,6 +72,7 @@
 
     // A more readable alias for the default constructor.
     static Status ok();
+
     // Authors should explicitly pick whether their integer is:
     //  - an exception code (EX_* above)
     //  - service specific error code
@@ -83,9 +85,15 @@
     static Status fromExceptionCode(int32_t exceptionCode);
     static Status fromExceptionCode(int32_t exceptionCode,
                                     const String8& message);
+    static Status fromExceptionCode(int32_t exceptionCode,
+                                    const char* message);
+
     static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode);
     static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode,
                                            const String8& message);
+    static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode,
+                                           const char* message);
+
     static Status fromStatusT(status_t status);
 
     Status() = default;
@@ -142,11 +150,7 @@
 };  // class Status
 
 // For gtest output logging
-template<typename T>
-T& operator<< (T& stream, const Status& s) {
-    stream << s.toString8().string();
-    return stream;
-}
+std::stringstream& operator<< (std::stringstream& stream, const Status& s);
 
 }  // namespace binder
 }  // namespace android
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index af26721..74a4123 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -137,6 +137,12 @@
      * should be used */
     virtual status_t setActiveConfig(const sp<IBinder>& display, int id) = 0;
 
+    virtual status_t getDisplayColorModes(const sp<IBinder>& display,
+            Vector<android_color_mode_t>* outColorModes) = 0;
+    virtual android_color_mode_t getActiveColorMode(const sp<IBinder>& display) = 0;
+    virtual status_t setActiveColorMode(const sp<IBinder>& display,
+            android_color_mode_t colorMode) = 0;
+
     /* Capture the specified screen. requires READ_FRAME_BUFFER permission
      * This function will fail if there is a secure window on screen.
      */
@@ -193,6 +199,9 @@
         SET_POWER_MODE,
         GET_DISPLAY_STATS,
         GET_HDR_CAPABILITIES,
+        GET_DISPLAY_COLOR_MODES,
+        GET_ACTIVE_COLOR_MODE,
+        SET_ACTIVE_COLOR_MODE,
     };
 
     virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 95e8b70..b8ee331 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -83,6 +83,16 @@
     // returned by getDisplayInfo
     static status_t setActiveConfig(const sp<IBinder>& display, int id);
 
+    // Gets the list of supported color modes for the given display
+    static status_t getDisplayColorModes(const sp<IBinder>& display,
+            Vector<android_color_mode_t>* outColorModes);
+
+    // Gets the active color mode for the given display
+    static android_color_mode_t getActiveColorMode(const sp<IBinder>& display);
+
+    // Sets the active color mode for the given display
+    static status_t setActiveColorMode(const sp<IBinder>& display, android_color_mode_t colorMode);
+
     /* Triggers screen on/off or low power mode and waits for it to complete */
     static void setDisplayPowerMode(const sp<IBinder>& display, int mode);
 
diff --git a/include/media/openmax/OMX_Core.h b/include/media/openmax/OMX_Core.h
index 99a7622..bb974b3 100644
--- a/include/media/openmax/OMX_Core.h
+++ b/include/media/openmax/OMX_Core.h
@@ -516,6 +516,9 @@
      *  but must signal the event no more than 40ms after the first frame in the batch. The frames
      *  must be ordered by system timestamp inside and across batches.
      *
+     *  The component shall signal the render-timestamp of the very first frame (as well as the
+     *  first frame after each flush) unbatched (with nData1 set to 1) within 5 msec.
+     *
      *  If component is doing frame-rate conversion, it must signal the render time of each
      *  converted frame, and must interpolate media timestamps for in-between frames.
      *
@@ -735,7 +738,7 @@
         pComponentVersion,                                  \
         pSpecVersion,                                       \
         pComponentUUID)                                     \
-    ((OMX_COMPONENTTYPE*)hComponent)->GetComponentVersion(  \
+    ((OMX_COMPONENTTYPE*)(hComponent))->GetComponentVersion(\
         hComponent,                                         \
         pComponentName,                                     \
         pComponentVersion,                                  \
@@ -753,15 +756,21 @@
     When the command is "OMX_CommandStateSet" the component will queue a
     state transition to the new state idenfied in nParam.
 
+    The component shall transition from executing to loaded state within 500 msec.
+
     When the command is "OMX_CommandFlush", to flush a port's buffer queues,
     the command will force the component to return all buffers NOT CURRENTLY
     BEING PROCESSED to the application, in the order in which the buffers
     were received.
 
+    The component shall finish flusing each port within 5 msec.
+
     When the command is "OMX_CommandPortDisable" or
     "OMX_CommandPortEnable", the component's port (given by the value of
     nParam) will be stopped or restarted.
 
+    The component shall finish disabling/reenabling each port within 5 msec.
+
     When the command "OMX_CommandMarkBuffer" is used to mark a buffer, the
     pCmdData will point to a OMX_MARKTYPE structure containing the component
     handle of the component to examine the buffer chain for the mark.  nParam1
@@ -795,7 +804,7 @@
          Cmd,                                               \
          nParam,                                            \
          pCmdData)                                          \
-     ((OMX_COMPONENTTYPE*)hComponent)->SendCommand(         \
+     ((OMX_COMPONENTTYPE*)(hComponent))->SendCommand(       \
          hComponent,                                        \
          Cmd,                                               \
          nParam,                                            \
@@ -834,8 +843,8 @@
 #define OMX_GetParameter(                                   \
         hComponent,                                         \
         nParamIndex,                                        \
-        pComponentParameterStructure)                        \
-    ((OMX_COMPONENTTYPE*)hComponent)->GetParameter(         \
+        pComponentParameterStructure)                       \
+    ((OMX_COMPONENTTYPE*)(hComponent))->GetParameter(       \
         hComponent,                                         \
         nParamIndex,                                        \
         pComponentParameterStructure)    /* Macro End */
@@ -873,8 +882,8 @@
 #define OMX_SetParameter(                                   \
         hComponent,                                         \
         nParamIndex,                                        \
-        pComponentParameterStructure)                        \
-    ((OMX_COMPONENTTYPE*)hComponent)->SetParameter(         \
+        pComponentParameterStructure)                       \
+    ((OMX_COMPONENTTYPE*)(hComponent))->SetParameter(       \
         hComponent,                                         \
         nParamIndex,                                        \
         pComponentParameterStructure)    /* Macro End */
@@ -909,8 +918,8 @@
 #define OMX_GetConfig(                                      \
         hComponent,                                         \
         nConfigIndex,                                       \
-        pComponentConfigStructure)                           \
-    ((OMX_COMPONENTTYPE*)hComponent)->GetConfig(            \
+        pComponentConfigStructure)                          \
+    ((OMX_COMPONENTTYPE*)(hComponent))->GetConfig(          \
         hComponent,                                         \
         nConfigIndex,                                       \
         pComponentConfigStructure)       /* Macro End */
@@ -945,8 +954,8 @@
 #define OMX_SetConfig(                                      \
         hComponent,                                         \
         nConfigIndex,                                       \
-        pComponentConfigStructure)                           \
-    ((OMX_COMPONENTTYPE*)hComponent)->SetConfig(            \
+        pComponentConfigStructure)                          \
+    ((OMX_COMPONENTTYPE*)(hComponent))->SetConfig(          \
         hComponent,                                         \
         nConfigIndex,                                       \
         pComponentConfigStructure)       /* Macro End */
@@ -980,7 +989,7 @@
         hComponent,                                         \
         cParameterName,                                     \
         pIndexType)                                         \
-    ((OMX_COMPONENTTYPE*)hComponent)->GetExtensionIndex(    \
+    ((OMX_COMPONENTTYPE*)(hComponent))->GetExtensionIndex(  \
         hComponent,                                         \
         cParameterName,                                     \
         pIndexType)                     /* Macro End */
@@ -1006,7 +1015,7 @@
 #define OMX_GetState(                                       \
         hComponent,                                         \
         pState)                                             \
-    ((OMX_COMPONENTTYPE*)hComponent)->GetState(             \
+    ((OMX_COMPONENTTYPE*)(hComponent))->GetState(           \
         hComponent,                                         \
         pState)                         /* Macro End */
 
@@ -1037,7 +1046,7 @@
            pAppPrivate,                                     \
            nSizeBytes,                                      \
            pBuffer)                                         \
-    ((OMX_COMPONENTTYPE*)hComponent)->UseBuffer(            \
+    ((OMX_COMPONENTTYPE*)(hComponent))->UseBuffer(          \
            hComponent,                                      \
            ppBufferHdr,                                     \
            nPortIndex,                                      \
@@ -1079,7 +1088,7 @@
         nPortIndex,                                         \
         pAppPrivate,                                        \
         nSizeBytes)                                         \
-    ((OMX_COMPONENTTYPE*)hComponent)->AllocateBuffer(       \
+    ((OMX_COMPONENTTYPE*)(hComponent))->AllocateBuffer(     \
         hComponent,                                         \
         ppBuffer,                                           \
         nPortIndex,                                         \
@@ -1113,7 +1122,7 @@
         hComponent,                                         \
         nPortIndex,                                         \
         pBuffer)                                            \
-    ((OMX_COMPONENTTYPE*)hComponent)->FreeBuffer(           \
+    ((OMX_COMPONENTTYPE*)(hComponent))->FreeBuffer(         \
         hComponent,                                         \
         nPortIndex,                                         \
         pBuffer)                        /* Macro End */
@@ -1144,7 +1153,7 @@
 #define OMX_EmptyThisBuffer(                                \
         hComponent,                                         \
         pBuffer)                                            \
-    ((OMX_COMPONENTTYPE*)hComponent)->EmptyThisBuffer(      \
+    ((OMX_COMPONENTTYPE*)(hComponent))->EmptyThisBuffer(    \
         hComponent,                                         \
         pBuffer)                        /* Macro End */
 
@@ -1174,7 +1183,7 @@
 #define OMX_FillThisBuffer(                                 \
         hComponent,                                         \
         pBuffer)                                            \
-    ((OMX_COMPONENTTYPE*)hComponent)->FillThisBuffer(       \
+    ((OMX_COMPONENTTYPE*)(hComponent))->FillThisBuffer(     \
         hComponent,                                         \
         pBuffer)                        /* Macro End */
 
@@ -1216,7 +1225,7 @@
            nPortIndex,                                      \
            pAppPrivate,                                     \
            eglImage)                                        \
-    ((OMX_COMPONENTTYPE*)hComponent)->UseEGLImage(          \
+    ((OMX_COMPONENTTYPE*)(hComponent))->UseEGLImage(        \
            hComponent,                                      \
            ppBufferHdr,                                     \
            nPortIndex,                                      \
diff --git a/include/private/binder/binder_module.h b/include/private/binder/binder_module.h
index a8dd64f..2f11622 100644
--- a/include/private/binder/binder_module.h
+++ b/include/private/binder/binder_module.h
@@ -24,7 +24,7 @@
 /* obtain structures and constants from the kernel header */
 
 #include <sys/ioctl.h>
-#include <linux/binder.h>
+#include <linux/android/binder.h>
 
 #ifdef __cplusplus
 }   // namespace android
diff --git a/include/ui/DisplayInfo.h b/include/ui/DisplayInfo.h
index ad73ee7..799944f 100644
--- a/include/ui/DisplayInfo.h
+++ b/include/ui/DisplayInfo.h
@@ -36,7 +36,6 @@
     bool secure;
     nsecs_t appVsyncOffset;
     nsecs_t presentationDeadline;
-    int colorTransform;
 };
 
 /* Display orientations as defined in Surface.java and ISurfaceComposer.h. */
diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk
index 14be920..b57b02a 100644
--- a/libs/binder/Android.mk
+++ b/libs/binder/Android.mk
@@ -44,29 +44,27 @@
 
 LOCAL_PATH:= $(call my-dir)
 
-include $(CLEAR_VARS)
-LOCAL_MODULE := libbinder
-LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
-
-LOCAL_CLANG := true
-LOCAL_SANITIZE := integer
-LOCAL_SRC_FILES := $(sources)
+binder_cflags := -Wall -Wextra -Werror
 ifneq ($(TARGET_USES_64_BIT_BINDER),true)
 ifneq ($(TARGET_IS_64_BIT),true)
-LOCAL_CFLAGS += -DBINDER_IPC_32BIT=1
+binder_cflags += -DBINDER_IPC_32BIT=1
 endif
 endif
-LOCAL_CFLAGS += -Werror
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libbinder
+LOCAL_SHARED_LIBRARIES := libbase liblog libcutils libutils
+LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbase libutils
+
+LOCAL_SANITIZE := integer
+LOCAL_SRC_FILES := $(sources)
+LOCAL_CFLAGS := $(binder_cflags)
 include $(BUILD_SHARED_LIBRARY)
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := libbinder
-LOCAL_STATIC_LIBRARIES += libutils
+LOCAL_STATIC_LIBRARIES := libbase libutils
+LOCAL_EXPORT_STATIC_LIBRARY_HEADERS := libbase libutils
 LOCAL_SRC_FILES := $(sources)
-ifneq ($(TARGET_USES_64_BIT_BINDER),true)
-ifneq ($(TARGET_IS_64_BIT),true)
-LOCAL_CFLAGS += -DBINDER_IPC_32BIT=1
-endif
-endif
-LOCAL_CFLAGS += -Werror
+LOCAL_CFLAGS := $(binder_cflags)
 include $(BUILD_STATIC_LIBRARY)
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index 9a061a0..f3b86ae 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <mutex>
 #include <binder/AppOpsManager.h>
 #include <binder/Binder.h>
 #include <binder/IServiceManager.h>
@@ -22,6 +23,19 @@
 
 namespace android {
 
+namespace {
+
+#if defined(__BRILLO__)
+// Because Brillo has no application model, security policy is managed
+// statically (at build time) with SELinux controls.
+// As a consequence, it also never runs the AppOpsManager service.
+const int APP_OPS_MANAGER_UNAVAILABLE_MODE = AppOpsManager::MODE_ALLOWED;
+#else
+const int APP_OPS_MANAGER_UNAVAILABLE_MODE = AppOpsManager::MODE_IGNORED;
+#endif  // defined(__BRILLO__)
+
+}  // namespace
+
 static String16 _appops("appops");
 static pthread_mutex_t gTokenMutex = PTHREAD_MUTEX_INITIALIZER;
 static sp<IBinder> gToken;
@@ -39,10 +53,15 @@
 {
 }
 
+#if defined(__BRILLO__)
+// There is no AppOpsService on Brillo
+sp<IAppOpsService> AppOpsManager::getService() { return NULL; }
+#else
 sp<IAppOpsService> AppOpsManager::getService()
 {
+
+    std::lock_guard<Mutex> scoped_lock(mLock);
     int64_t startTime = 0;
-    mLock.lock();
     sp<IAppOpsService> service = mService;
     while (service == NULL || !IInterface::asBinder(service)->isBinderAlive()) {
         sp<IBinder> binder = defaultServiceManager()->checkService(_appops);
@@ -53,7 +72,8 @@
                 ALOGI("Waiting for app ops service");
             } else if ((uptimeMillis()-startTime) > 10000) {
                 ALOGW("Waiting too long for app ops service, giving up");
-                return NULL;
+                service = NULL;
+                break;
             }
             sleep(1);
         } else {
@@ -61,25 +81,30 @@
             mService = service;
         }
     }
-    mLock.unlock();
     return service;
 }
+#endif  // defined(__BRILLO__)
 
 int32_t AppOpsManager::checkOp(int32_t op, int32_t uid, const String16& callingPackage)
 {
     sp<IAppOpsService> service = getService();
-    return service != NULL ? service->checkOperation(op, uid, callingPackage) : MODE_IGNORED;
+    return service != NULL
+            ? service->checkOperation(op, uid, callingPackage)
+            : APP_OPS_MANAGER_UNAVAILABLE_MODE;
 }
 
 int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage) {
     sp<IAppOpsService> service = getService();
-    return service != NULL ? service->noteOperation(op, uid, callingPackage) : MODE_IGNORED;
+    return service != NULL
+            ? service->noteOperation(op, uid, callingPackage)
+            : APP_OPS_MANAGER_UNAVAILABLE_MODE;
 }
 
 int32_t AppOpsManager::startOp(int32_t op, int32_t uid, const String16& callingPackage) {
     sp<IAppOpsService> service = getService();
-    return service != NULL ? service->startOperation(getToken(service), op, uid, callingPackage)
-            : MODE_IGNORED;
+    return service != NULL
+            ? service->startOperation(getToken(service), op, uid, callingPackage)
+            : APP_OPS_MANAGER_UNAVAILABLE_MODE;
 }
 
 void AppOpsManager::finishOp(int32_t op, int32_t uid, const String16& callingPackage) {
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index c4d47ca..7ce2a31 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -237,6 +237,10 @@
 
             // XXX can't add virtuals until binaries are updated.
             //return shellCommand(in, out, err, args, resultReceiver);
+            (void)in;
+            (void)out;
+            (void)err;
+
             if (resultReceiver != NULL) {
                 resultReceiver->send(INVALID_OPERATION);
             }
diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp
index 1339a67..a2443c0 100644
--- a/libs/binder/BufferedTextOutput.cpp
+++ b/libs/binder/BufferedTextOutput.cpp
@@ -34,7 +34,7 @@
 
 struct BufferedTextOutput::BufferState : public RefBase
 {
-    BufferState(int32_t _seq)
+    explicit BufferState(int32_t _seq)
         : seq(_seq)
         , buffer(NULL)
         , bufferPos(0)
diff --git a/libs/binder/IAppOpsCallback.cpp b/libs/binder/IAppOpsCallback.cpp
index 2aaf566..f9ec593 100644
--- a/libs/binder/IAppOpsCallback.cpp
+++ b/libs/binder/IAppOpsCallback.cpp
@@ -31,7 +31,7 @@
 class BpAppOpsCallback : public BpInterface<IAppOpsCallback>
 {
 public:
-    BpAppOpsCallback(const sp<IBinder>& impl)
+    explicit BpAppOpsCallback(const sp<IBinder>& impl)
         : BpInterface<IAppOpsCallback>(impl)
     {
     }
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index 9558376..638ae5c 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -31,7 +31,7 @@
 class BpAppOpsService : public BpInterface<IAppOpsService>
 {
 public:
-    BpAppOpsService(const sp<IBinder>& impl)
+    explicit BpAppOpsService(const sp<IBinder>& impl)
         : BpInterface<IAppOpsService>(impl)
     {
     }
diff --git a/libs/binder/IBatteryStats.cpp b/libs/binder/IBatteryStats.cpp
index e32c628..ad1e69f 100644
--- a/libs/binder/IBatteryStats.cpp
+++ b/libs/binder/IBatteryStats.cpp
@@ -29,7 +29,7 @@
 class BpBatteryStats : public BpInterface<IBatteryStats>
 {
 public:
-    BpBatteryStats(const sp<IBinder>& impl)
+    explicit BpBatteryStats(const sp<IBinder>& impl)
         : BpInterface<IBatteryStats>(impl)
     {
     }
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index 5f345cf..55ad6cc 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -75,7 +75,7 @@
 class BpMemoryHeap : public BpInterface<IMemoryHeap>
 {
 public:
-    BpMemoryHeap(const sp<IBinder>& impl);
+    explicit BpMemoryHeap(const sp<IBinder>& impl);
     virtual ~BpMemoryHeap();
 
     virtual int getHeapID() const;
@@ -123,7 +123,7 @@
 class BpMemory : public BpInterface<IMemory>
 {
 public:
-    BpMemory(const sp<IBinder>& impl);
+    explicit BpMemory(const sp<IBinder>& impl);
     virtual ~BpMemory();
     virtual sp<IMemoryHeap> getMemory(ssize_t* offset=0, size_t* size=0) const;
 
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index d90798f..9b5f0d7 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -330,6 +330,7 @@
             delete st;
             pthread_setspecific(gTLS, NULL);
         }
+        pthread_key_delete(gTLS);
         gHaveTLS = false;
     }
 }
diff --git a/libs/binder/IPermissionController.cpp b/libs/binder/IPermissionController.cpp
index 6bba996..674bddf 100644
--- a/libs/binder/IPermissionController.cpp
+++ b/libs/binder/IPermissionController.cpp
@@ -31,7 +31,7 @@
 class BpPermissionController : public BpInterface<IPermissionController>
 {
 public:
-    BpPermissionController(const sp<IBinder>& impl)
+    explicit BpPermissionController(const sp<IBinder>& impl)
         : BpInterface<IPermissionController>(impl)
     {
     }
diff --git a/libs/binder/IProcessInfoService.cpp b/libs/binder/IProcessInfoService.cpp
index 76508b8..96e1a8c 100644
--- a/libs/binder/IProcessInfoService.cpp
+++ b/libs/binder/IProcessInfoService.cpp
@@ -25,7 +25,7 @@
 
 class BpProcessInfoService : public BpInterface<IProcessInfoService> {
 public:
-    BpProcessInfoService(const sp<IBinder>& impl)
+    explicit BpProcessInfoService(const sp<IBinder>& impl)
         : BpInterface<IProcessInfoService>(impl) {}
 
     virtual status_t getProcessStatesFromPids(size_t length, /*in*/ int32_t* pids,
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 61f24d6..2062b3b 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -67,11 +67,6 @@
 
 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;
@@ -131,7 +126,7 @@
 class BpServiceManager : public BpInterface<IServiceManager>
 {
 public:
-    BpServiceManager(const sp<IBinder>& impl)
+    explicit BpServiceManager(const sp<IBinder>& impl)
         : BpInterface<IServiceManager>(impl)
     {
     }
diff --git a/libs/binder/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp
index 51eac11..2a15773 100644
--- a/libs/binder/MemoryDealer.cpp
+++ b/libs/binder/MemoryDealer.cpp
@@ -126,7 +126,7 @@
         PAGE_ALIGNED = 0x00000001
     };
 public:
-    SimpleBestFitAllocator(size_t size);
+    explicit SimpleBestFitAllocator(size_t size);
     ~SimpleBestFitAllocator();
 
     size_t      allocate(size_t size, uint32_t flags = 0);
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index e88ae29..d566456 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -1112,7 +1112,7 @@
 }
 
 status_t Parcel::readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readStrongBinder);
+    return readNullableTypedVector(val, &Parcel::readNullableStrongBinder);
 }
 
 status_t Parcel::readStrongBinderVector(std::vector<sp<IBinder>>* val) const {
@@ -1187,15 +1187,15 @@
     return err;
 }
 
-status_t Parcel::writeUniqueFileDescriptor(const ScopedFd& fd) {
+status_t Parcel::writeUniqueFileDescriptor(const base::unique_fd& fd) {
     return writeDupFileDescriptor(fd.get());
 }
 
-status_t Parcel::writeUniqueFileDescriptorVector(const std::vector<ScopedFd>& val) {
+status_t Parcel::writeUniqueFileDescriptorVector(const std::vector<base::unique_fd>& val) {
     return writeTypedVector(val, &Parcel::writeUniqueFileDescriptor);
 }
 
-status_t Parcel::writeUniqueFileDescriptorVector(const std::unique_ptr<std::vector<ScopedFd>>& val) {
+status_t Parcel::writeUniqueFileDescriptorVector(const std::unique_ptr<std::vector<base::unique_fd>>& val) {
     return writeNullableTypedVector(val, &Parcel::writeUniqueFileDescriptor);
 }
 
@@ -1842,13 +1842,37 @@
 
 String8 Parcel::readString8() const
 {
-    int32_t size = readInt32();
-    // watch for potential int overflow adding 1 for trailing NUL
-    if (size > 0 && size < INT32_MAX) {
-        const char* str = (const char*)readInplace(size+1);
-        if (str) return String8(str, size);
+    String8 retString;
+    status_t status = readString8(&retString);
+    if (status != OK) {
+        // We don't care about errors here, so just return an empty string.
+        return String8();
     }
-    return String8();
+    return retString;
+}
+
+status_t Parcel::readString8(String8* pArg) const
+{
+    int32_t size;
+    status_t status = readInt32(&size);
+    if (status != OK) {
+        return status;
+    }
+    // watch for potential int overflow from size+1
+    if (size < 0 || size >= INT32_MAX) {
+        return BAD_VALUE;
+    }
+    // |writeString8| writes nothing for empty string.
+    if (size == 0) {
+        *pArg = String8();
+        return OK;
+    }
+    const char* str = (const char*)readInplace(size + 1);
+    if (str == NULL) {
+        return BAD_VALUE;
+    }
+    pArg->setTo(str, size);
+    return OK;
 }
 
 String16 Parcel::readString16() const
@@ -1913,13 +1937,25 @@
 
 status_t Parcel::readStrongBinder(sp<IBinder>* val) const
 {
+    status_t status = readNullableStrongBinder(val);
+    if (status == OK && !val->get()) {
+        status = UNEXPECTED_NULL;
+    }
+    return status;
+}
+
+status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
+{
     return unflatten_binder(ProcessState::self(), *this, val);
 }
 
 sp<IBinder> Parcel::readStrongBinder() const
 {
     sp<IBinder> val;
-    readStrongBinder(&val);
+    // Note that a lot of code in Android reads binders by hand with this
+    // method, and that code has historically been ok with getting nullptr
+    // back (while ignoring error codes).
+    readNullableStrongBinder(&val);
     return val;
 }
 
@@ -1994,7 +2030,7 @@
     return BAD_TYPE;
 }
 
-status_t Parcel::readUniqueFileDescriptor(ScopedFd* val) const
+status_t Parcel::readUniqueFileDescriptor(base::unique_fd* val) const
 {
     int got = readFileDescriptor();
 
@@ -2012,11 +2048,11 @@
 }
 
 
-status_t Parcel::readUniqueFileDescriptorVector(std::unique_ptr<std::vector<ScopedFd>>* val) const {
+status_t Parcel::readUniqueFileDescriptorVector(std::unique_ptr<std::vector<base::unique_fd>>* val) const {
     return readNullableTypedVector(val, &Parcel::readUniqueFileDescriptor);
 }
 
-status_t Parcel::readUniqueFileDescriptorVector(std::vector<ScopedFd>* val) const {
+status_t Parcel::readUniqueFileDescriptorVector(std::vector<base::unique_fd>* val) const {
     return readTypedVector(val, &Parcel::readUniqueFileDescriptor);
 }
 
diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp
index aef791c..e7078ba 100644
--- a/libs/binder/PersistableBundle.cpp
+++ b/libs/binder/PersistableBundle.cpp
@@ -32,6 +32,9 @@
 using android::sp;
 using android::status_t;
 using android::UNEXPECTED_NULL;
+using std::map;
+using std::set;
+using std::vector;
 
 enum {
     // Keep in sync with BUNDLE_MAGIC in frameworks/base/core/java/android/os/BaseBundle.java.
@@ -55,12 +58,22 @@
 
 namespace {
 template <typename T>
-bool getValue(const android::String16& key, T* out, const std::map<android::String16, T>& map) {
+bool getValue(const android::String16& key, T* out, const map<android::String16, T>& map) {
     const auto& it = map.find(key);
     if (it == map.end()) return false;
     *out = it->second;
     return true;
 }
+
+template <typename T>
+set<android::String16> getKeys(const map<android::String16, T>& map) {
+    if (map.empty()) return set<android::String16>();
+    set<android::String16> keys;
+    for (const auto& key_value_pair : map) {
+        keys.emplace(key_value_pair.first);
+    }
+    return keys;
+}
 }  // namespace
 
 namespace android {
@@ -78,7 +91,7 @@
 
 #define RETURN_IF_ENTRY_ERASED(map, key)                                 \
     {                                                                    \
-        size_t num_erased = map.erase(key);                              \
+        size_t num_erased = (map).erase(key);                            \
         if (num_erased) {                                                \
             ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
             return num_erased;                                           \
@@ -188,27 +201,27 @@
     mStringMap[key] = value;
 }
 
-void PersistableBundle::putBooleanVector(const String16& key, const std::vector<bool>& value) {
+void PersistableBundle::putBooleanVector(const String16& key, const vector<bool>& value) {
     erase(key);
     mBoolVectorMap[key] = value;
 }
 
-void PersistableBundle::putIntVector(const String16& key, const std::vector<int32_t>& value) {
+void PersistableBundle::putIntVector(const String16& key, const vector<int32_t>& value) {
     erase(key);
     mIntVectorMap[key] = value;
 }
 
-void PersistableBundle::putLongVector(const String16& key, const std::vector<int64_t>& value) {
+void PersistableBundle::putLongVector(const String16& key, const vector<int64_t>& value) {
     erase(key);
     mLongVectorMap[key] = value;
 }
 
-void PersistableBundle::putDoubleVector(const String16& key, const std::vector<double>& value) {
+void PersistableBundle::putDoubleVector(const String16& key, const vector<double>& value) {
     erase(key);
     mDoubleVectorMap[key] = value;
 }
 
-void PersistableBundle::putStringVector(const String16& key, const std::vector<String16>& value) {
+void PersistableBundle::putStringVector(const String16& key, const vector<String16>& value) {
     erase(key);
     mStringVectorMap[key] = value;
 }
@@ -238,23 +251,23 @@
     return getValue(key, out, mStringMap);
 }
 
-bool PersistableBundle::getBooleanVector(const String16& key, std::vector<bool>* out) const {
+bool PersistableBundle::getBooleanVector(const String16& key, vector<bool>* out) const {
     return getValue(key, out, mBoolVectorMap);
 }
 
-bool PersistableBundle::getIntVector(const String16& key, std::vector<int32_t>* out) const {
+bool PersistableBundle::getIntVector(const String16& key, vector<int32_t>* out) const {
     return getValue(key, out, mIntVectorMap);
 }
 
-bool PersistableBundle::getLongVector(const String16& key, std::vector<int64_t>* out) const {
+bool PersistableBundle::getLongVector(const String16& key, vector<int64_t>* out) const {
     return getValue(key, out, mLongVectorMap);
 }
 
-bool PersistableBundle::getDoubleVector(const String16& key, std::vector<double>* out) const {
+bool PersistableBundle::getDoubleVector(const String16& key, vector<double>* out) const {
     return getValue(key, out, mDoubleVectorMap);
 }
 
-bool PersistableBundle::getStringVector(const String16& key, std::vector<String16>* out) const {
+bool PersistableBundle::getStringVector(const String16& key, vector<String16>* out) const {
     return getValue(key, out, mStringVectorMap);
 }
 
@@ -262,6 +275,50 @@
     return getValue(key, out, mPersistableBundleMap);
 }
 
+set<String16> PersistableBundle::getBooleanKeys() const {
+    return getKeys(mBoolMap);
+}
+
+set<String16> PersistableBundle::getIntKeys() const {
+    return getKeys(mIntMap);
+}
+
+set<String16> PersistableBundle::getLongKeys() const {
+    return getKeys(mLongMap);
+}
+
+set<String16> PersistableBundle::getDoubleKeys() const {
+    return getKeys(mDoubleMap);
+}
+
+set<String16> PersistableBundle::getStringKeys() const {
+    return getKeys(mStringMap);
+}
+
+set<String16> PersistableBundle::getBooleanVectorKeys() const {
+    return getKeys(mBoolVectorMap);
+}
+
+set<String16> PersistableBundle::getIntVectorKeys() const {
+    return getKeys(mIntVectorMap);
+}
+
+set<String16> PersistableBundle::getLongVectorKeys() const {
+    return getKeys(mLongVectorMap);
+}
+
+set<String16> PersistableBundle::getDoubleVectorKeys() const {
+    return getKeys(mDoubleVectorMap);
+}
+
+set<String16> PersistableBundle::getStringVectorKeys() const {
+    return getKeys(mStringVectorMap);
+}
+
+set<String16> PersistableBundle::getPersistableBundleKeys() const {
+    return getKeys(mPersistableBundleMap);
+}
+
 status_t PersistableBundle::writeToParcelInner(Parcel* parcel) const {
     /*
      * To keep this implementation in sync with writeArrayMapInternal() in
@@ -363,7 +420,6 @@
     RETURN_IF_FAILED(parcel->readInt32(&num_entries));
 
     for (; num_entries > 0; --num_entries) {
-        size_t start_pos = parcel->dataPosition();
         String16 key;
         int32_t value_type;
         RETURN_IF_FAILED(parcel->readString16(&key));
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index f13f49f..319d1d9 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -52,7 +52,7 @@
 class PoolThread : public Thread
 {
 public:
-    PoolThread(bool isMain)
+    explicit PoolThread(bool isMain)
         : mIsMain(isMain)
     {
     }
@@ -366,6 +366,13 @@
 
 ProcessState::~ProcessState()
 {
+    if (mDriverFD >= 0) {
+        if (mVMStart != MAP_FAILED) {
+            munmap(mVMStart, BINDER_VM_SIZE);
+        }
+        close(mDriverFD);
+    }
+    mDriverFD = -1;
 }
         
 }; // namespace android
diff --git a/libs/binder/Static.cpp b/libs/binder/Static.cpp
index cd9509f..f0613d1 100644
--- a/libs/binder/Static.cpp
+++ b/libs/binder/Static.cpp
@@ -48,7 +48,7 @@
 class FdTextOutput : public BufferedTextOutput
 {
 public:
-    FdTextOutput(int fd) : BufferedTextOutput(MULTITHREADED), mFD(fd) { }
+    explicit FdTextOutput(int fd) : BufferedTextOutput(MULTITHREADED), mFD(fd) { }
     virtual ~FdTextOutput() { };
 
 protected:
diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp
index d3520d6..8466863 100644
--- a/libs/binder/Status.cpp
+++ b/libs/binder/Status.cpp
@@ -32,6 +32,11 @@
     return Status(exceptionCode, OK, message);
 }
 
+Status Status::fromExceptionCode(int32_t exceptionCode,
+                                 const char* message) {
+    return fromExceptionCode(exceptionCode, String8(message));
+}
+
 Status Status::fromServiceSpecificError(int32_t serviceSpecificErrorCode) {
     return Status(EX_SERVICE_SPECIFIC, serviceSpecificErrorCode);
 }
@@ -41,6 +46,11 @@
     return Status(EX_SERVICE_SPECIFIC, serviceSpecificErrorCode, message);
 }
 
+Status Status::fromServiceSpecificError(int32_t serviceSpecificErrorCode,
+                                        const char* message) {
+    return fromServiceSpecificError(serviceSpecificErrorCode, String8(message));
+}
+
 Status Status::fromStatusT(status_t status) {
     Status ret;
     ret.setFromStatusT(status);
@@ -158,5 +168,10 @@
     return ret;
 }
 
+std::stringstream& operator<< (std::stringstream& stream, const Status& s) {
+    stream << s.toString8().string();
+    return stream;
+}
+
 }  // namespace binder
 }  // namespace android
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 3df3acf..17479ca 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -252,14 +252,10 @@
             int ret;
             pthread_mutex_lock(&m_waitMutex);
             if (!m_eventTriggered) {
-#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
-                pthread_cond_timeout_np(&m_waitCond, &m_waitMutex, timeout_s * 1000);
-#else
                 struct timespec ts;
                 clock_gettime(CLOCK_REALTIME, &ts);
                 ts.tv_sec += timeout_s;
                 pthread_cond_timedwait(&m_waitCond, &m_waitMutex, &ts);
-#endif
             }
             ret = m_eventTriggered ? NO_ERROR : TIMED_OUT;
             pthread_mutex_unlock(&m_waitMutex);
@@ -739,14 +735,10 @@
                 }
                 if (ret > 0) {
                     if (m_serverStartRequested) {
-#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
-                        ret = pthread_cond_timeout_np(&m_serverWaitCond, &m_serverWaitMutex, 5000);
-#else
                         struct timespec ts;
                         clock_gettime(CLOCK_REALTIME, &ts);
                         ts.tv_sec += 5;
                         ret = pthread_cond_timedwait(&m_serverWaitCond, &m_serverWaitMutex, &ts);
-#endif
                     }
                     if (m_serverStartRequested) {
                         m_serverStartRequested = false;
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index 46feb1c..f5961cf 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -84,6 +84,7 @@
 	libutils \
 	liblog
 
+LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbinder
 
 LOCAL_MODULE := libgui
 
@@ -94,6 +95,10 @@
 	LOCAL_CFLAGS += -DDONT_USE_FENCE_SYNC
 endif
 
+ifeq ($(TARGET_BOARD_HAS_NO_SURFACE_FLINGER), true)
+	LOCAL_CFLAGS += -DHAVE_NO_SURFACE_FLINGER
+endif
+
 include $(BUILD_SHARED_LIBRARY)
 
 ifeq (,$(ONE_SHOT_MAKEFILE))
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index 569b8f9..b574f9d 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -28,8 +28,11 @@
 
 #include <inttypes.h>
 
+#include <cutils/properties.h>
+
 #include <gui/BufferItem.h>
 #include <gui/BufferQueueCore.h>
+#include <gui/GraphicBufferAlloc.h>
 #include <gui/IConsumerListener.h>
 #include <gui/IGraphicBufferAlloc.h>
 #include <gui/IProducerListener.h>
@@ -92,8 +95,24 @@
     mUniqueId(getUniqueId())
 {
     if (allocator == NULL) {
-        sp<ISurfaceComposer> composer(ComposerService::getComposerService());
-        mAllocator = composer->createGraphicBufferAlloc();
+
+#ifdef HAVE_NO_SURFACE_FLINGER
+        // Without a SurfaceFlinger, allocate in-process.  This only makes
+        // sense in systems with static SELinux configurations and no
+        // applications (since applications need dynamic SELinux policy).
+        mAllocator = new GraphicBufferAlloc();
+#else
+        // Run time check for headless, where we also allocate in-process.
+        char value[PROPERTY_VALUE_MAX];
+        property_get("config.headless", value, "0");
+        if (atoi(value) == 1) {
+            mAllocator = new GraphicBufferAlloc();
+        } else {
+            sp<ISurfaceComposer> composer(ComposerService::getComposerService());
+            mAllocator = composer->createGraphicBufferAlloc();
+        }
+#endif  // HAVE_NO_SURFACE_FLINGER
+
         if (mAllocator == NULL) {
             BQ_LOGE("createGraphicBufferAlloc failed");
         }
diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp
index 9a06011..3175b91 100644
--- a/libs/gui/IConsumerListener.cpp
+++ b/libs/gui/IConsumerListener.cpp
@@ -37,7 +37,7 @@
 class BpConsumerListener : public BpInterface<IConsumerListener>
 {
 public:
-    BpConsumerListener(const sp<IBinder>& impl)
+    explicit BpConsumerListener(const sp<IBinder>& impl)
         : BpInterface<IConsumerListener>(impl) {
     }
 
diff --git a/libs/gui/IDisplayEventConnection.cpp b/libs/gui/IDisplayEventConnection.cpp
index 9890f44..b1d3b00 100644
--- a/libs/gui/IDisplayEventConnection.cpp
+++ b/libs/gui/IDisplayEventConnection.cpp
@@ -39,7 +39,7 @@
 class BpDisplayEventConnection : public BpInterface<IDisplayEventConnection>
 {
 public:
-    BpDisplayEventConnection(const sp<IBinder>& impl)
+    explicit BpDisplayEventConnection(const sp<IBinder>& impl)
         : BpInterface<IDisplayEventConnection>(impl)
     {
     }
diff --git a/libs/gui/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp
index 3009989..d4d4702 100644
--- a/libs/gui/IGraphicBufferAlloc.cpp
+++ b/libs/gui/IGraphicBufferAlloc.cpp
@@ -37,7 +37,7 @@
 class BpGraphicBufferAlloc : public BpInterface<IGraphicBufferAlloc>
 {
 public:
-    BpGraphicBufferAlloc(const sp<IBinder>& impl)
+    explicit BpGraphicBufferAlloc(const sp<IBinder>& impl)
         : BpInterface<IGraphicBufferAlloc>(impl)
     {
     }
@@ -90,7 +90,7 @@
     class BufferReference : public BBinder {
         sp<GraphicBuffer> mBuffer;
     public:
-        BufferReference(const sp<GraphicBuffer>& buffer) : mBuffer(buffer) {}
+        explicit BufferReference(const sp<GraphicBuffer>& buffer) : mBuffer(buffer) {}
     };
 
 
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index 7c4379f..63d5be9 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -59,7 +59,7 @@
 class BpGraphicBufferConsumer : public BpInterface<IGraphicBufferConsumer>
 {
 public:
-    BpGraphicBufferConsumer(const sp<IBinder>& impl)
+    explicit BpGraphicBufferConsumer(const sp<IBinder>& impl)
         : BpInterface<IGraphicBufferConsumer>(impl)
     {
     }
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index fbd704d..56656e3 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -61,7 +61,7 @@
 class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
 {
 public:
-    BpGraphicBufferProducer(const sp<IBinder>& impl)
+    explicit BpGraphicBufferProducer(const sp<IBinder>& impl)
         : BpInterface<IGraphicBufferProducer>(impl)
     {
     }
diff --git a/libs/gui/IProducerListener.cpp b/libs/gui/IProducerListener.cpp
index 81adc95..9d18ea2 100644
--- a/libs/gui/IProducerListener.cpp
+++ b/libs/gui/IProducerListener.cpp
@@ -27,7 +27,7 @@
 class BpProducerListener : public BpInterface<IProducerListener>
 {
 public:
-    BpProducerListener(const sp<IBinder>& impl)
+    explicit BpProducerListener(const sp<IBinder>& impl)
         : BpInterface<IProducerListener>(impl) {}
 
     virtual ~BpProducerListener();
diff --git a/libs/gui/ISensorEventConnection.cpp b/libs/gui/ISensorEventConnection.cpp
index dc7a35c..59ecee7 100644
--- a/libs/gui/ISensorEventConnection.cpp
+++ b/libs/gui/ISensorEventConnection.cpp
@@ -40,7 +40,7 @@
 class BpSensorEventConnection : public BpInterface<ISensorEventConnection>
 {
 public:
-    BpSensorEventConnection(const sp<IBinder>& impl)
+    explicit BpSensorEventConnection(const sp<IBinder>& impl)
         : BpInterface<ISensorEventConnection>(impl)
     {
     }
diff --git a/libs/gui/ISensorServer.cpp b/libs/gui/ISensorServer.cpp
index 3a4c7e4..07c507a 100644
--- a/libs/gui/ISensorServer.cpp
+++ b/libs/gui/ISensorServer.cpp
@@ -42,7 +42,7 @@
 class BpSensorServer : public BpInterface<ISensorServer>
 {
 public:
-    BpSensorServer(const sp<IBinder>& impl)
+    explicit BpSensorServer(const sp<IBinder>& impl)
         : BpInterface<ISensorServer>(impl)
     {
     }
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index a8b4fa8..0a8e6a5 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -32,6 +32,8 @@
 
 #include <private/gui/LayerState.h>
 
+#include <system/graphics.h>
+
 #include <ui/DisplayInfo.h>
 #include <ui/DisplayStatInfo.h>
 #include <ui/HdrCapabilities.h>
@@ -47,7 +49,7 @@
 class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
 {
 public:
-    BpSurfaceComposer(const sp<IBinder>& impl)
+    explicit BpSurfaceComposer(const sp<IBinder>& impl)
         : BpInterface<ISurfaceComposer>(impl)
     {
     }
@@ -269,6 +271,82 @@
         return reply.readInt32();
     }
 
+    virtual status_t getDisplayColorModes(const sp<IBinder>& display,
+            Vector<android_color_mode_t>* outColorModes) {
+        Parcel data, reply;
+        status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        if (result != NO_ERROR) {
+            ALOGE("getDisplayColorModes failed to writeInterfaceToken: %d", result);
+            return result;
+        }
+        result = data.writeStrongBinder(display);
+        if (result != NO_ERROR) {
+            ALOGE("getDisplayColorModes failed to writeStrongBinder: %d", result);
+            return result;
+        }
+        result = remote()->transact(BnSurfaceComposer::GET_DISPLAY_COLOR_MODES, data, &reply);
+        if (result != NO_ERROR) {
+            ALOGE("getDisplayColorModes failed to transact: %d", result);
+            return result;
+        }
+        result = static_cast<status_t>(reply.readInt32());
+        if (result == NO_ERROR) {
+            size_t numModes = reply.readUint32();
+            outColorModes->clear();
+            outColorModes->resize(numModes);
+            for (size_t i = 0; i < numModes; ++i) {
+                outColorModes->replaceAt(static_cast<android_color_mode_t>(reply.readInt32()), i);
+            }
+        }
+        return result;
+    }
+
+    virtual android_color_mode_t getActiveColorMode(const sp<IBinder>& display) {
+        Parcel data, reply;
+        status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        if (result != NO_ERROR) {
+            ALOGE("getActiveColorMode failed to writeInterfaceToken: %d", result);
+            return static_cast<android_color_mode_t>(result);
+        }
+        result = data.writeStrongBinder(display);
+        if (result != NO_ERROR) {
+            ALOGE("getActiveColorMode failed to writeStrongBinder: %d", result);
+            return static_cast<android_color_mode_t>(result);
+        }
+        result = remote()->transact(BnSurfaceComposer::GET_ACTIVE_COLOR_MODE, data, &reply);
+        if (result != NO_ERROR) {
+            ALOGE("getActiveColorMode failed to transact: %d", result);
+            return static_cast<android_color_mode_t>(result);
+        }
+        return static_cast<android_color_mode_t>(reply.readInt32());
+    }
+
+    virtual status_t setActiveColorMode(const sp<IBinder>& display,
+            android_color_mode_t colorMode) {
+        Parcel data, reply;
+        status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        if (result != NO_ERROR) {
+            ALOGE("setActiveColorMode failed to writeInterfaceToken: %d", result);
+            return result;
+        }
+        result = data.writeStrongBinder(display);
+        if (result != NO_ERROR) {
+            ALOGE("setActiveColorMode failed to writeStrongBinder: %d", result);
+            return result;
+        }
+        result = data.writeInt32(colorMode);
+        if (result != NO_ERROR) {
+            ALOGE("setActiveColorMode failed to writeInt32: %d", result);
+            return result;
+        }
+        result = remote()->transact(BnSurfaceComposer::SET_ACTIVE_COLOR_MODE, data, &reply);
+        if (result != NO_ERROR) {
+            ALOGE("setActiveColorMode failed to transact: %d", result);
+            return result;
+        }
+        return static_cast<status_t>(reply.readInt32());
+    }
+
     virtual status_t clearAnimationFrameStats() {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -469,6 +547,56 @@
             reply->writeInt32(result);
             return NO_ERROR;
         }
+        case GET_DISPLAY_COLOR_MODES: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            Vector<android_color_mode_t> colorModes;
+            sp<IBinder> display = nullptr;
+            status_t result = data.readStrongBinder(&display);
+            if (result != NO_ERROR) {
+                ALOGE("getDisplayColorModes failed to readStrongBinder: %d", result);
+                return result;
+            }
+            result = getDisplayColorModes(display, &colorModes);
+            reply->writeInt32(result);
+            if (result == NO_ERROR) {
+                reply->writeUint32(static_cast<uint32_t>(colorModes.size()));
+                for (size_t i = 0; i < colorModes.size(); ++i) {
+                    reply->writeInt32(colorModes[i]);
+                }
+            }
+            return NO_ERROR;
+        }
+        case GET_ACTIVE_COLOR_MODE: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IBinder> display = nullptr;
+            status_t result = data.readStrongBinder(&display);
+            if (result != NO_ERROR) {
+                ALOGE("getActiveColorMode failed to readStrongBinder: %d", result);
+                return result;
+            }
+            android_color_mode_t colorMode = getActiveColorMode(display);
+            result = reply->writeInt32(static_cast<int32_t>(colorMode));
+            return result;
+        }
+        case SET_ACTIVE_COLOR_MODE: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IBinder> display = nullptr;
+            status_t result = data.readStrongBinder(&display);
+            if (result != NO_ERROR) {
+                ALOGE("getActiveColorMode failed to readStrongBinder: %d", result);
+                return result;
+            }
+            int32_t colorModeInt = 0;
+            result = data.readInt32(&colorModeInt);
+            if (result != NO_ERROR) {
+                ALOGE("setActiveColorMode failed to readInt32: %d", result);
+                return result;
+            }
+            result = setActiveColorMode(display,
+                    static_cast<android_color_mode_t>(colorModeInt));
+            result = reply->writeInt32(result);
+            return result;
+        }
         case CLEAR_ANIMATION_FRAME_STATS: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             status_t result = clearAnimationFrameStats();
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index dd5b169..47cb047 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -48,7 +48,7 @@
 class BpSurfaceComposerClient : public BpInterface<ISurfaceComposerClient>
 {
 public:
-    BpSurfaceComposerClient(const sp<IBinder>& impl)
+    explicit BpSurfaceComposerClient(const sp<IBinder>& impl)
         : BpInterface<ISurfaceComposerClient>(impl) {
     }
 
diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp
index 225bfa8..5338034 100644
--- a/libs/gui/SensorManager.cpp
+++ b/libs/gui/SensorManager.cpp
@@ -139,7 +139,7 @@
                 mSensorManager.sensorManagerDied();
             }
         public:
-            DeathObserver(SensorManager& mgr) : mSensorManager(mgr) { }
+            explicit DeathObserver(SensorManager& mgr) : mSensorManager(mgr) { }
         };
 
         LOG_ALWAYS_FATAL_IF(mSensorServer.get() == NULL, "getService(SensorService) NULL");
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 26b2209..1c460e8 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -29,6 +29,8 @@
 #include <binder/IMemory.h>
 #include <binder/IServiceManager.h>
 
+#include <system/graphics.h>
+
 #include <ui/DisplayInfo.h>
 
 #include <gui/CpuConsumer.h>
@@ -67,7 +69,7 @@
             mComposerService.composerServiceDied();
         }
      public:
-        DeathObserver(ComposerService& mgr) : mComposerService(mgr) { }
+        explicit DeathObserver(ComposerService& mgr) : mComposerService(mgr) { }
     };
 
     mDeathObserver = new DeathObserver(*const_cast<ComposerService*>(this));
@@ -771,6 +773,20 @@
     return ComposerService::getComposerService()->setActiveConfig(display, id);
 }
 
+status_t SurfaceComposerClient::getDisplayColorModes(const sp<IBinder>& display,
+        Vector<android_color_mode_t>* outColorModes) {
+    return ComposerService::getComposerService()->getDisplayColorModes(display, outColorModes);
+}
+
+android_color_mode_t SurfaceComposerClient::getActiveColorMode(const sp<IBinder>& display) {
+    return ComposerService::getComposerService()->getActiveColorMode(display);
+}
+
+status_t SurfaceComposerClient::setActiveColorMode(const sp<IBinder>& display,
+        android_color_mode_t colorMode) {
+    return ComposerService::getComposerService()->setActiveColorMode(display, colorMode);
+}
+
 void SurfaceComposerClient::setDisplayPowerMode(const sp<IBinder>& token,
         int mode) {
     ComposerService::getComposerService()->setPowerMode(token, mode);
diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk
index 6ad9986..7d984a4 100644
--- a/libs/gui/tests/Android.mk
+++ b/libs/gui/tests/Android.mk
@@ -28,6 +28,7 @@
     TextureRenderer.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
+	liblog \
 	libEGL \
 	libGLESv1_CM \
 	libGLESv2 \
diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp
index 289cc74..9c2e838 100644
--- a/libs/gui/tests/CpuConsumer_test.cpp
+++ b/libs/gui/tests/CpuConsumer_test.cpp
@@ -160,7 +160,7 @@
 };
 
 #define ASSERT_NO_ERROR(err, msg) \
-    ASSERT_EQ(NO_ERROR, err) << msg << strerror(-err)
+    ASSERT_EQ(NO_ERROR, err) << (msg) << strerror(-(err))
 
 void checkPixel(const CpuConsumer::LockedBuffer &buf,
         uint32_t x, uint32_t y, uint32_t r, uint32_t g=0, uint32_t b=0) {
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index a1578f6..b10d4eb 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -535,7 +535,7 @@
             return false;
         }
     public:
-        MyThread(const sp<GLConsumer>& mST)
+        explicit MyThread(const sp<GLConsumer>& mST)
             : mST(mST), mBufferRetired(false) {
             ctx = eglGetCurrentContext();
             sur = eglGetCurrentSurface(EGL_DRAW);
diff --git a/libs/gui/tests/SurfaceTextureGL_test.cpp b/libs/gui/tests/SurfaceTextureGL_test.cpp
index dddcf92..81d5a57 100644
--- a/libs/gui/tests/SurfaceTextureGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGL_test.cpp
@@ -437,7 +437,7 @@
 
     class ProducerThread : public Thread {
     public:
-        ProducerThread(const sp<ANativeWindow>& anw):
+        explicit ProducerThread(const sp<ANativeWindow>& anw):
                 mANW(anw) {
         }
 
@@ -620,7 +620,7 @@
 TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) {
     class ProducerThread : public Thread {
     public:
-        ProducerThread(const sp<ANativeWindow>& anw):
+        explicit ProducerThread(const sp<ANativeWindow>& anw):
                 mANW(anw),
                 mDequeueError(NO_ERROR) {
         }
diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp
index e009731..003e73d 100644
--- a/libs/input/IInputFlinger.cpp
+++ b/libs/input/IInputFlinger.cpp
@@ -28,7 +28,7 @@
 
 class BpInputFlinger : public BpInterface<IInputFlinger> {
 public:
-    BpInputFlinger(const sp<IBinder>& impl) :
+    explicit BpInputFlinger(const sp<IBinder>& impl) :
             BpInterface<IInputFlinger>(impl) { }
 
     virtual status_t doSomething() {
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index 8d73f45..81b9953 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -20,7 +20,7 @@
 namespace android {
 
 #define CHECK_OFFSET(type, member, expected_offset) \
-  static_assert((offsetof(type, member) == expected_offset), "")
+  static_assert((offsetof(type, member) == (expected_offset)), "")
 
 struct Foo {
   uint32_t dummy;
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index ac37990..fb2b857 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -424,7 +424,7 @@
     Vector<Rect> span;
     Rect* cur;
 public:
-    rasterizer(Region& reg)
+    explicit rasterizer(Region& reg)
         : bounds(INT_MAX, 0, INT_MIN, 0), storage(reg.mStorage), head(), tail(), cur() {
         storage.clear();
     }
@@ -489,7 +489,8 @@
                     merge = false;
                     break;
                 }
-                p++, q++;
+                p++;
+                q++;
             }
         }
     }
@@ -795,6 +796,11 @@
         return NO_MEMORY;
     }
 
+    if (numRects > (UINT32_MAX / sizeof(Rect))) {
+        android_errorWriteWithInfoLog(0x534e4554, "29983260", -1, NULL, 0);
+        return NO_MEMORY;
+    }
+
     Region result;
     result.mStorage.clear();
     for (size_t r = 0; r < numRects; ++r) {
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 2e18698..6fab4d9 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -545,7 +545,7 @@
 #define EGL_SYNC_NATIVE_FENCE_ANDROID		0x3144
 #define EGL_SYNC_NATIVE_FENCE_FD_ANDROID	0x3145
 #define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID	0x3146
-#define EGL_NO_NATIVE_FENCE_FD_ANDROID		-1
+#define EGL_NO_NATIVE_FENCE_FD_ANDROID		(-1)
 #ifdef EGL_EGLEXT_PROTOTYPES
 EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID( EGLDisplay dpy, EGLSyncKHR);
 #endif /* EGL_EGLEXT_PROTOTYPES */
diff --git a/opengl/libagl/arch-mips/fixed_asm.S b/opengl/libagl/arch-mips/fixed_asm.S
index e1a53bc..a30ffc5 100644
--- a/opengl/libagl/arch-mips/fixed_asm.S
+++ b/opengl/libagl/arch-mips/fixed_asm.S
@@ -17,7 +17,7 @@
 
 
     .text
-    .align
+    .align 4
 
 /*
  * this version rounds-to-nearest and saturates numbers
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index eb86860..5074fd0 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -77,7 +77,6 @@
 	GLES_CM/gl.cpp.arm 	\
 #
 
-LOCAL_CLANG := false
 LOCAL_SHARED_LIBRARIES += libcutils liblog libEGL
 LOCAL_MODULE:= libGLESv1_CM
 
@@ -105,7 +104,6 @@
 	GLES2/gl2.cpp   \
 #
 
-LOCAL_CLANG := false
 LOCAL_ARM_MODE := arm
 LOCAL_SHARED_LIBRARIES += libcutils libutils liblog libEGL
 LOCAL_MODULE:= libGLESv2
@@ -133,7 +131,6 @@
 	GLES2/gl2.cpp   \
 #
 
-LOCAL_CLANG := false
 LOCAL_ARM_MODE := arm
 LOCAL_SHARED_LIBRARIES += libcutils libutils liblog libEGL
 LOCAL_MODULE:= libGLESv3
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 7a0cce4..fcb9357 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -54,6 +54,8 @@
 // Implementation is incomplete and untested.
 #define ENABLE_EGL_KHR_GL_COLORSPACE 0
 
+#define ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS 0
+
 // ----------------------------------------------------------------------------
 
 namespace android {
@@ -84,7 +86,9 @@
         "EGL_KHR_swap_buffers_with_damage "
         "EGL_ANDROID_create_native_client_buffer "
         "EGL_ANDROID_front_buffer_auto_refresh "
+#if ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS
         "EGL_ANDROID_get_frame_timestamps "
+#endif
         ;
 extern char const * const gExtensionString  =
         "EGL_KHR_image "                        // mandatory
@@ -1212,10 +1216,12 @@
             setError(EGL_BAD_SURFACE, EGL_FALSE);
     }
 
+#if ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS
     if (attribute == EGL_TIMESTAMPS_ANDROID) {
         s->enableTimestamps = value;
         return EGL_TRUE;
     }
+#endif
 
     if (s->cnx->egl.eglSurfaceAttrib) {
         return s->cnx->egl.eglSurfaceAttrib(
@@ -2036,6 +2042,7 @@
     }
 
     switch (timestamp) {
+#if ENABLE_EGL_ANDROID_GET_FRAME_TIMESTAMPS
         case EGL_QUEUE_TIME_ANDROID:
         case EGL_RENDERING_COMPLETE_TIME_ANDROID:
         case EGL_COMPOSITION_START_TIME_ANDROID:
@@ -2043,6 +2050,7 @@
         case EGL_DISPLAY_RETIRE_TIME_ANDROID:
         case EGL_READS_DONE_TIME_ANDROID:
             return EGL_TRUE;
+#endif
         default:
             return EGL_FALSE;
     }
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index 6034a8e..6dd87c2 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -34,39 +34,65 @@
 
 #undef API_ENTRY
 #undef CALL_GL_API
+#undef CALL_GL_API_INTERNAL_CALL
+#undef CALL_GL_API_INTERNAL_SET_RETURN_VALUE
+#undef CALL_GL_API_INTERNAL_DO_RETURN
 #undef CALL_GL_API_RETURN
 
 #if USE_SLOW_BINDING
 
     #define API_ENTRY(_api) _api
 
-    #define CALL_GL_API(_api, ...)                                       \
+    #define CALL_GL_API_INTERNAL_CALL(_api, ...)                         \
         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
         if (_c) return _c->_api(__VA_ARGS__);
 
+    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE return 0;
+
+    // This stays blank, since void functions will implicitly return, and
+    // all of the other functions will return 0 based on the previous macro.
+    #define CALL_GL_API_INTERNAL_DO_RETURN
+
 #elif defined(__arm__)
 
     #define GET_TLS(reg) "mrc p15, 0, " #reg ", c13, c0, 3 \n"
 
-    #define API_ENTRY(_api) __attribute__((noinline)) _api
+    #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
 
-    #define CALL_GL_API(_api, ...)                              \
-         asm volatile(                                          \
-            GET_TLS(r12)                                        \
-            "ldr   r12, [r12, %[tls]] \n"                       \
-            "cmp   r12, #0            \n"                       \
-            "ldrne pc,  [r12, %[api]] \n"                       \
-            :                                                   \
-            : [tls] "J"(TLS_SLOT_OPENGL_API*4),                 \
-              [api] "J"(__builtin_offsetof(gl_hooks_t, gl._api))    \
-            : "r12"                                             \
-            );
+    #define CALL_GL_API_INTERNAL_CALL(_api, ...)                 \
+        asm volatile(                                            \
+            GET_TLS(r12)                                         \
+            "ldr   r12, [r12, %[tls]] \n"                        \
+            "cmp   r12, #0            \n"                        \
+            "ldrne pc,  [r12, %[api]] \n"                        \
+            :                                                    \
+            : [tls] "J"(TLS_SLOT_OPENGL_API*4),                  \
+              [api] "J"(__builtin_offsetof(gl_hooks_t, gl._api)) \
+            : "r0", "r1", "r2", "r3", "r12"                      \
+        );
+
+    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
+        asm volatile(                             \
+            "mov r0, #0 \n"                       \
+            :                                     \
+            :                                     \
+            : "r0"                                \
+        );
+
+
+    #define CALL_GL_API_INTERNAL_DO_RETURN \
+        asm volatile(                      \
+            "bx lr \n"                     \
+            :                              \
+            :                              \
+            : "r0"                         \
+        );
 
 #elif defined(__aarch64__)
 
-    #define API_ENTRY(_api) __attribute__((noinline)) _api
+    #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
 
-    #define CALL_GL_API(_api, ...)                                  \
+    #define CALL_GL_API_INTERNAL_CALL(_api, ...)                    \
         asm volatile(                                               \
             "mrs x16, tpidr_el0\n"                                  \
             "ldr x16, [x16, %[tls]]\n"                              \
@@ -77,121 +103,173 @@
             :                                                       \
             : [tls] "i" (TLS_SLOT_OPENGL_API * sizeof(void*)),      \
               [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api))   \
-            : "x16"                                                 \
+            : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x16" \
+        );
+
+    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
+        asm volatile(                             \
+            "mov w0, wzr \n"                      \
+            :                                     \
+            :                                     \
+            : "w0"                                \
+        );
+
+    #define CALL_GL_API_INTERNAL_DO_RETURN \
+        asm volatile(                      \
+            "ret \n"                       \
+            :                              \
+            :                              \
+            :                              \
         );
 
 #elif defined(__i386__)
 
-    #define API_ENTRY(_api) __attribute__((noinline,optimize("omit-frame-pointer"))) _api
+    #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
 
-    #define CALL_GL_API(_api, ...)                                  \
-        register void** fn;                                         \
+    #define CALL_GL_API_INTERNAL_CALL(_api, ...)                    \
         __asm__ volatile(                                           \
-            "mov %%gs:0, %[fn]\n"                                   \
-            "mov %P[tls](%[fn]), %[fn]\n"                           \
-            "test %[fn], %[fn]\n"                                   \
+            "mov %%gs:0, %%eax\n"                                   \
+            "mov %P[tls](%%eax), %%eax\n"                           \
+            "test %%eax, %%eax\n"                                   \
             "je 1f\n"                                               \
-            "jmp *%P[api](%[fn])\n"                                 \
+            "jmp *%P[api](%%eax)\n"                                 \
             "1:\n"                                                  \
-            : [fn] "=r" (fn)                                        \
+            :                                                       \
             : [tls] "i" (TLS_SLOT_OPENGL_API*sizeof(void*)),        \
               [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api))   \
-            : "cc"                                                  \
+            : "cc", "%eax"                                          \
             );
 
+    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
+        __asm__ volatile(                         \
+            "xor %%eax, %%eax\n"                  \
+            :                                     \
+            :                                     \
+            : "%eax"                              \
+        );
+
+    #define CALL_GL_API_INTERNAL_DO_RETURN \
+        __asm__ volatile(                  \
+            "ret\n"                        \
+            :                              \
+            :                              \
+            :                              \
+        );
+
 #elif defined(__x86_64__)
 
-    #define API_ENTRY(_api) __attribute__((noinline,optimize("omit-frame-pointer"))) _api
+    #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
 
-    #define CALL_GL_API(_api, ...)                                  \
-         register void** fn;                                        \
-         __asm__ volatile(                                          \
-            "mov %%fs:0, %[fn]\n"                                   \
-            "mov %P[tls](%[fn]), %[fn]\n"                           \
-            "test %[fn], %[fn]\n"                                   \
+    #define CALL_GL_API_INTERNAL_CALL(_api, ...)                    \
+        __asm__ volatile(                                           \
+            "mov %%fs:0, %%rax\n"                                   \
+            "mov %P[tls](%%rax), %%rax\n"                           \
+            "test %%rax, %%rax\n"                                   \
             "je 1f\n"                                               \
-            "jmp *%P[api](%[fn])\n"                                 \
+            "jmp *%P[api](%%rax)\n"                                 \
             "1:\n"                                                  \
-            : [fn] "=r" (fn)                                        \
+            :                                                       \
             : [tls] "i" (TLS_SLOT_OPENGL_API*sizeof(void*)),        \
               [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api))   \
-            : "cc"                                                  \
-            );
+            : "cc", "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9",   \
+              "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", \
+              "%xmm6", "%xmm7"                                      \
+        );
+
+    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
+        __asm__ volatile(                         \
+            "xor %%eax, %%eax\n"                  \
+            :                                     \
+            :                                     \
+            : "%eax"                              \
+        );
+
+    #define CALL_GL_API_INTERNAL_DO_RETURN \
+        __asm__ volatile(                  \
+            "retq\n"                       \
+            :                              \
+            :                              \
+            :                              \
+        );
 
 #elif defined(__mips64)
 
-    #define API_ENTRY(_api) __attribute__((noinline)) _api
+    #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
 
-    #define CALL_GL_API(_api, ...)                            \
-    register unsigned long _t0 asm("$12");                    \
-    register unsigned long _fn asm("$25");                    \
-    register unsigned long _tls asm("$3");                    \
-    register unsigned long _v0 asm("$2");                     \
-    asm volatile(                                             \
-        ".set  push\n\t"                                      \
-        ".set  noreorder\n\t"                                 \
-        "rdhwr %[tls], $29\n\t"                               \
-        "ld    %[t0], %[OPENGL_API](%[tls])\n\t"              \
-        "beqz  %[t0], 1f\n\t"                                 \
-        " move %[fn], $ra\n\t"                                \
-        "ld    %[t0], %[API](%[t0])\n\t"                      \
-        "beqz  %[t0], 1f\n\t"                                 \
-        " nop\n\t"                                            \
-        "move  %[fn], %[t0]\n\t"                              \
-        "1:\n\t"                                              \
-        "jalr  $0, %[fn]\n\t"                                 \
-        " move %[v0], $0\n\t"                                 \
-        ".set  pop\n\t"                                       \
-        : [fn] "=c"(_fn),                                     \
-          [tls] "=&r"(_tls),                                  \
-          [t0] "=&r"(_t0),                                    \
-          [v0] "=&r"(_v0)                                     \
-        : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*sizeof(void*)),\
-          [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api))  \
-        :                                                     \
+    // t0:  $12
+    // fn:  $25
+    // tls: $3
+    // v0:  $2
+    #define CALL_GL_API_INTERNAL_CALL(_api, ...)                  \
+        asm volatile(                                             \
+            ".set  push\n\t"                                      \
+            ".set  noreorder\n\t"                                 \
+            "rdhwr $3, $29\n\t"                                   \
+            "ld    $12, %[OPENGL_API]($3)\n\t"                    \
+            "beqz  $12, 1f\n\t"                                   \
+            " move $25, $ra\n\t"                                  \
+            "ld    $12, %[API]($12)\n\t"                          \
+            "beqz  $12, 1f\n\t"                                   \
+            " nop\n\t"                                            \
+            "move  $25, $12\n\t"                                  \
+            "1:\n\t"                                              \
+            "jalr  $0, $25\n\t"                                   \
+            " move $2, $0\n\t"                                    \
+            ".set  pop\n\t"                                       \
+            :                                                     \
+            : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*sizeof(void*)),\
+              [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api))  \
+            : "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9",     \
+              "$10", "$11", "$12", "$25"                          \
         );
 
+    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE
+    #define CALL_GL_API_INTERNAL_DO_RETURN
+
 #elif defined(__mips__)
 
-    #define API_ENTRY(_api) __attribute__((noinline)) _api
+    #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
 
-    #define CALL_GL_API(_api, ...)                               \
-        register unsigned int _t0 asm("$8");                     \
-        register unsigned int _fn asm("$25");                    \
-        register unsigned int _tls asm("$3");                    \
-        register unsigned int _v0 asm("$2");                     \
+    // t0:  $8
+    // fn:  $25
+    // tls: $3
+    // v0:  $2
+    #define CALL_GL_API_INTERNAL_CALL(_api, ...)                 \
         asm volatile(                                            \
             ".set  push\n\t"                                     \
             ".set  noreorder\n\t"                                \
             ".set  mips32r2\n\t"                                 \
-            "rdhwr %[tls], $29\n\t"                              \
-            "lw    %[t0], %[OPENGL_API](%[tls])\n\t"             \
-            "beqz  %[t0], 1f\n\t"                                \
-            " move %[fn],$ra\n\t"                                \
-            "lw    %[t0], %[API](%[t0])\n\t"                     \
-            "beqz  %[t0], 1f\n\t"                                \
+            "rdhwr $3, $29\n\t"                                  \
+            "lw    $3, %[OPENGL_API]($3)\n\t"                    \
+            "beqz  $3, 1f\n\t"                                   \
+            " move $25,$ra\n\t"                                  \
+            "lw    $3, %[API]($3)\n\t"                           \
+            "beqz  $3, 1f\n\t"                                   \
             " nop\n\t"                                           \
-            "move  %[fn], %[t0]\n\t"                             \
+            "move  $25, $3\n\t"                                  \
             "1:\n\t"                                             \
-            "jalr  $0, %[fn]\n\t"                                \
-            " move %[v0], $0\n\t"                                \
+            "jalr  $0, $25\n\t"                                  \
+            " move $2, $0\n\t"                                   \
             ".set  pop\n\t"                                      \
-            : [fn] "=c"(_fn),                                    \
-              [tls] "=&r"(_tls),                                 \
-              [t0] "=&r"(_t0),                                   \
-              [v0] "=&r"(_v0)                                    \
+            :                                                    \
             : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*4),           \
               [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api)) \
-            :                                                    \
-            );
+            : "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$25"    \
+        );
+
+    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE
+    #define CALL_GL_API_INTERNAL_DO_RETURN
 
 #endif
 
+#define CALL_GL_API(_api, ...) \
+    CALL_GL_API_INTERNAL_CALL(_api, __VA_ARGS__) \
+    CALL_GL_API_INTERNAL_DO_RETURN
+
 #define CALL_GL_API_RETURN(_api, ...) \
-    CALL_GL_API(_api, __VA_ARGS__) \
-    return 0;
-
-
+    CALL_GL_API_INTERNAL_CALL(_api, __VA_ARGS__) \
+    CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
+    CALL_GL_API_INTERNAL_DO_RETURN
 
 extern "C" {
 #pragma GCC diagnostic ignored "-Wunused-parameter"
@@ -202,6 +280,9 @@
 
 #undef API_ENTRY
 #undef CALL_GL_API
+#undef CALL_GL_API_INTERNAL_CALL
+#undef CALL_GL_API_INTERNAL_SET_RETURN_VALUE
+#undef CALL_GL_API_INTERNAL_DO_RETURN
 #undef CALL_GL_API_RETURN
 
 /*
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index b1b31f8..8bde4e5 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -90,39 +90,65 @@
 
 #undef API_ENTRY
 #undef CALL_GL_API
+#undef CALL_GL_API_INTERNAL_CALL
+#undef CALL_GL_API_INTERNAL_SET_RETURN_VALUE
+#undef CALL_GL_API_INTERNAL_DO_RETURN
 #undef CALL_GL_API_RETURN
 
 #if USE_SLOW_BINDING
 
     #define API_ENTRY(_api) _api
 
-    #define CALL_GL_API(_api, ...)                                       \
+    #define CALL_GL_API_INTERNAL_CALL(_api, ...)                         \
         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
         if (_c) return _c->_api(__VA_ARGS__);
 
+    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE return 0;
+
+    // This stays blank, since void functions will implicitly return, and
+    // all of the other functions will return 0 based on the previous macro.
+    #define CALL_GL_API_INTERNAL_DO_RETURN
+
 #elif defined(__arm__)
 
     #define GET_TLS(reg) "mrc p15, 0, " #reg ", c13, c0, 3 \n"
 
-    #define API_ENTRY(_api) __attribute__((noinline)) _api
+    #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
 
-    #define CALL_GL_API(_api, ...)                              \
-         asm volatile(                                          \
-            GET_TLS(r12)                                        \
-            "ldr   r12, [r12, %[tls]] \n"                       \
-            "cmp   r12, #0            \n"                       \
-            "ldrne pc,  [r12, %[api]] \n"                       \
-            :                                                   \
-            : [tls] "J"(TLS_SLOT_OPENGL_API*4),                 \
-              [api] "J"(__builtin_offsetof(gl_hooks_t, gl._api))    \
-            : "r12"                                             \
-            );
+    #define CALL_GL_API_INTERNAL_CALL(_api, ...)                 \
+        asm volatile(                                            \
+            GET_TLS(r12)                                         \
+            "ldr   r12, [r12, %[tls]] \n"                        \
+            "cmp   r12, #0            \n"                        \
+            "ldrne pc,  [r12, %[api]] \n"                        \
+            :                                                    \
+            : [tls] "J"(TLS_SLOT_OPENGL_API*4),                  \
+              [api] "J"(__builtin_offsetof(gl_hooks_t, gl._api)) \
+            : "r0", "r1", "r2", "r3", "r12"                      \
+        );
+
+    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
+        asm volatile(                             \
+            "mov r0, #0 \n"                       \
+            :                                     \
+            :                                     \
+            : "r0"                                \
+        );
+
+
+    #define CALL_GL_API_INTERNAL_DO_RETURN \
+        asm volatile(                      \
+            "bx lr \n"                     \
+            :                              \
+            :                              \
+            : "r0"                         \
+        );
 
 #elif defined(__aarch64__)
 
-    #define API_ENTRY(_api) __attribute__((noinline)) _api
+    #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
 
-    #define CALL_GL_API(_api, ...)                                  \
+    #define CALL_GL_API_INTERNAL_CALL(_api, ...)                    \
         asm volatile(                                               \
             "mrs x16, tpidr_el0\n"                                  \
             "ldr x16, [x16, %[tls]]\n"                              \
@@ -133,120 +159,173 @@
             :                                                       \
             : [tls] "i" (TLS_SLOT_OPENGL_API * sizeof(void*)),      \
               [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api))   \
-            : "x16"                                                 \
+            : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x16" \
+        );
+
+    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
+        asm volatile(                             \
+            "mov w0, wzr \n"                      \
+            :                                     \
+            :                                     \
+            : "w0"                                \
+        );
+
+    #define CALL_GL_API_INTERNAL_DO_RETURN \
+        asm volatile(                      \
+            "ret \n"                       \
+            :                              \
+            :                              \
+            :                              \
         );
 
 #elif defined(__i386__)
 
-    #define API_ENTRY(_api) __attribute__((noinline,optimize("omit-frame-pointer"))) _api
+    #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
 
-    #define CALL_GL_API(_api, ...)                                  \
-        register void* fn;                                          \
+    #define CALL_GL_API_INTERNAL_CALL(_api, ...)                    \
         __asm__ volatile(                                           \
-            "mov %%gs:0, %[fn]\n"                                   \
-            "mov %P[tls](%[fn]), %[fn]\n"                           \
-            "test %[fn], %[fn]\n"                                   \
+            "mov %%gs:0, %%eax\n"                                   \
+            "mov %P[tls](%%eax), %%eax\n"                           \
+            "test %%eax, %%eax\n"                                   \
             "je 1f\n"                                               \
-            "jmp *%P[api](%[fn])\n"                                 \
+            "jmp *%P[api](%%eax)\n"                                 \
             "1:\n"                                                  \
-            : [fn] "=r" (fn)                                        \
+            :                                                       \
             : [tls] "i" (TLS_SLOT_OPENGL_API*sizeof(void*)),        \
               [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api))   \
-            : "cc"                                                  \
-            );
+            : "cc", "%eax"                                          \
+        );
+
+    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
+        __asm__ volatile(                         \
+            "xor %%eax, %%eax\n"                  \
+            :                                     \
+            :                                     \
+            : "%eax"                              \
+        );
+
+    #define CALL_GL_API_INTERNAL_DO_RETURN \
+        __asm__ volatile(                  \
+            "ret\n"                        \
+            :                              \
+            :                              \
+            :                              \
+        );
 
 #elif defined(__x86_64__)
 
-    #define API_ENTRY(_api) __attribute__((noinline,optimize("omit-frame-pointer"))) _api
+    #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
 
-    #define CALL_GL_API(_api, ...)                                  \
-         register void** fn;                                        \
-         __asm__ volatile(                                          \
-            "mov %%fs:0, %[fn]\n"                                   \
-            "mov %P[tls](%[fn]), %[fn]\n"                           \
-            "test %[fn], %[fn]\n"                                   \
+    #define CALL_GL_API_INTERNAL_CALL(_api, ...)                    \
+        __asm__ volatile(                                           \
+            "mov %%fs:0, %%rax\n"                                   \
+            "mov %P[tls](%%rax), %%rax\n"                           \
+            "test %%rax, %%rax\n"                                   \
             "je 1f\n"                                               \
-            "jmp *%P[api](%[fn])\n"                                 \
+            "jmp *%P[api](%%rax)\n"                                 \
             "1:\n"                                                  \
-            : [fn] "=r" (fn)                                        \
+            :                                                       \
             : [tls] "i" (TLS_SLOT_OPENGL_API*sizeof(void*)),        \
               [api] "i" (__builtin_offsetof(gl_hooks_t, gl._api))   \
-            : "cc"                                                  \
-            );
+            : "cc", "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9",   \
+              "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", \
+              "%xmm6", "%xmm7"                                      \
+        );
+
+    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
+        __asm__ volatile(                         \
+            "xor %%eax, %%eax\n"                  \
+            :                                     \
+            :                                     \
+            : "%eax"                              \
+        );
+
+    #define CALL_GL_API_INTERNAL_DO_RETURN \
+        __asm__ volatile(                  \
+            "retq\n"                       \
+            :                              \
+            :                              \
+            :                              \
+        );
 
 #elif defined(__mips64)
 
-    #define API_ENTRY(_api) __attribute__((noinline)) _api
+    #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
 
-    #define CALL_GL_API(_api, ...)                            \
-    register unsigned long _t0 asm("$12");                    \
-    register unsigned long _fn asm("$25");                    \
-    register unsigned long _tls asm("$3");                    \
-    register unsigned long _v0 asm("$2");                     \
-    asm volatile(                                             \
-        ".set  push\n\t"                                      \
-        ".set  noreorder\n\t"                                 \
-        "rdhwr %[tls], $29\n\t"                               \
-        "ld    %[t0], %[OPENGL_API](%[tls])\n\t"              \
-        "beqz  %[t0], 1f\n\t"                                 \
-        " move %[fn], $ra\n\t"                                \
-        "ld    %[t0], %[API](%[t0])\n\t"                      \
-        "beqz  %[t0], 1f\n\t"                                 \
-        " nop\n\t"                                            \
-        "move  %[fn], %[t0]\n\t"                              \
-        "1:\n\t"                                              \
-        "jalr  $0, %[fn]\n\t"                                 \
-        " move %[v0], $0\n\t"                                 \
-        ".set  pop\n\t"                                       \
-        : [fn] "=c"(_fn),                                     \
-          [tls] "=&r"(_tls),                                  \
-          [t0] "=&r"(_t0),                                    \
-          [v0] "=&r"(_v0)                                     \
-        : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*sizeof(void*)),\
-          [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api))  \
-        :                                                     \
+    // t0:  $12
+    // fn:  $25
+    // tls: $3
+    // v0:  $2
+    #define CALL_GL_API_INTERNAL_CALL(_api, ...)                  \
+        asm volatile(                                             \
+            ".set  push\n\t"                                      \
+            ".set  noreorder\n\t"                                 \
+            "rdhwr $3, $29\n\t"                                   \
+            "ld    $12, %[OPENGL_API]($3)\n\t"                    \
+            "beqz  $12, 1f\n\t"                                   \
+            " move $25, $ra\n\t"                                  \
+            "ld    $12, %[API]($12)\n\t"                          \
+            "beqz  $12, 1f\n\t"                                   \
+            " nop\n\t"                                            \
+            "move  $25, $12\n\t"                                  \
+            "1:\n\t"                                              \
+            "jalr  $0, $25\n\t"                                   \
+            " move $2, $0\n\t"                                    \
+            ".set  pop\n\t"                                       \
+            :                                                     \
+            : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*sizeof(void*)),\
+              [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api))  \
+            : "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9",     \
+              "$10", "$11", "$12", "$25"                          \
         );
 
+    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE
+    #define CALL_GL_API_INTERNAL_DO_RETURN
+
 #elif defined(__mips__)
 
-    #define API_ENTRY(_api) __attribute__((noinline)) _api
+    #define API_ENTRY(_api) __attribute__((naked,noinline)) _api
 
-    #define CALL_GL_API(_api, ...)                               \
-        register unsigned int _t0 asm("$8");                     \
-        register unsigned int _fn asm("$25");                    \
-        register unsigned int _tls asm("$3");                    \
-        register unsigned int _v0 asm("$2");                     \
+    // t0:  $8
+    // fn:  $25
+    // tls: $3
+    // v0:  $2
+    #define CALL_GL_API_INTERNAL_CALL(_api, ...)                 \
         asm volatile(                                            \
             ".set  push\n\t"                                     \
             ".set  noreorder\n\t"                                \
             ".set  mips32r2\n\t"                                 \
-            "rdhwr %[tls], $29\n\t"                              \
-            "lw    %[t0], %[OPENGL_API](%[tls])\n\t"             \
-            "beqz  %[t0], 1f\n\t"                                \
-            " move %[fn], $ra\n\t"                               \
-            "lw    %[t0], %[API](%[t0])\n\t"                     \
-            "beqz  %[t0], 1f\n\t"                                \
+            "rdhwr $3, $29\n\t"                                  \
+            "lw    $3, %[OPENGL_API]($3)\n\t"                    \
+            "beqz  $3, 1f\n\t"                                   \
+            " move $25,$ra\n\t"                                  \
+            "lw    $3, %[API]($3)\n\t"                           \
+            "beqz  $3, 1f\n\t"                                   \
             " nop\n\t"                                           \
-            "move  %[fn], %[t0]\n\t"                             \
+            "move  $25, $3\n\t"                                  \
             "1:\n\t"                                             \
-            "jalr  $0, %[fn]\n\t"                                \
-            " move %[v0], $0\n\t"                                \
+            "jalr  $0, $25\n\t"                                  \
+            " move $2, $0\n\t"                                   \
             ".set  pop\n\t"                                      \
-            : [fn] "=c"(_fn),                                    \
-              [tls] "=&r"(_tls),                                 \
-              [t0] "=&r"(_t0),                                   \
-              [v0] "=&r"(_v0)                                    \
+            :                                                    \
             : [OPENGL_API] "I"(TLS_SLOT_OPENGL_API*4),           \
               [API] "I"(__builtin_offsetof(gl_hooks_t, gl._api)) \
-            :                                                    \
-            );
+            : "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$25"    \
+        );
+
+    #define CALL_GL_API_INTERNAL_SET_RETURN_VALUE
+    #define CALL_GL_API_INTERNAL_DO_RETURN
 
 #endif
 
-#define CALL_GL_API_RETURN(_api, ...) \
-    CALL_GL_API(_api, __VA_ARGS__) \
-    return 0;
+#define CALL_GL_API(_api, ...) \
+    CALL_GL_API_INTERNAL_CALL(_api, __VA_ARGS__) \
+    CALL_GL_API_INTERNAL_DO_RETURN
 
+#define CALL_GL_API_RETURN(_api, ...) \
+    CALL_GL_API_INTERNAL_CALL(_api, __VA_ARGS__) \
+    CALL_GL_API_INTERNAL_SET_RETURN_VALUE \
+    CALL_GL_API_INTERNAL_DO_RETURN
 
 extern "C" {
 #pragma GCC diagnostic ignored "-Wunused-parameter"
@@ -257,6 +336,9 @@
 
 #undef API_ENTRY
 #undef CALL_GL_API
+#undef CALL_GL_API_INTERNAL_CALL
+#undef CALL_GL_API_INTERNAL_SET_RETURN_VALUE
+#undef CALL_GL_API_INTERNAL_DO_RETURN
 #undef CALL_GL_API_RETURN
 
 /*
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index e14075c..81dbe0e 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -56,8 +56,8 @@
 
 #undef GL_ENTRY
 #undef EGL_ENTRY
-#define GL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__);
-#define EGL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__);
+#define GL_ENTRY(_r, _api, ...) _r (*(_api))(__VA_ARGS__);
+#define EGL_ENTRY(_r, _api, ...) _r (*(_api))(__VA_ARGS__);
 
 struct egl_t {
     #include "EGL/egl_entries.in"
diff --git a/opengl/tests/angeles/demo.c b/opengl/tests/angeles/demo.c
index 802f398..39d871e 100644
--- a/opengl/tests/angeles/demo.c
+++ b/opengl/tests/angeles/demo.c
@@ -666,7 +666,7 @@
         y[2] /= mag;
     }
 
-#define M(row,col)  m[col*4+row]
+#define M(row,col)  m[(col)*4+(row)]
     M(0, 0) = x[0];
     M(0, 1) = x[1];
     M(0, 2) = x[2];
diff --git a/opengl/tests/hwc/hwcColorEquiv.cpp b/opengl/tests/hwc/hwcColorEquiv.cpp
index f1361b8..a9bbcb6 100644
--- a/opengl/tests/hwc/hwcColorEquiv.cpp
+++ b/opengl/tests/hwc/hwcColorEquiv.cpp
@@ -116,7 +116,7 @@
 #define CMD_START_FRAMEWORK  "start 2>&1"
 
 // Macros
-#define NUMA(a) (sizeof(a) / sizeof(a [0])) // Num elements in an array
+#define NUMA(a) (sizeof(a) / sizeof((a)[0])) // Num elements in an array
 #define MEMCLR(addr, size) do { \
         memset((addr), 0, (size)); \
     } while (0)
diff --git a/opengl/tests/hwc/hwcCommit.cpp b/opengl/tests/hwc/hwcCommit.cpp
index 6b287e9..3686dab 100644
--- a/opengl/tests/hwc/hwcCommit.cpp
+++ b/opengl/tests/hwc/hwcCommit.cpp
@@ -156,12 +156,12 @@
 #define CMD_START_FRAMEWORK  "start 2>&1"
 
 // Macros
-#define NUMA(a) (sizeof(a) / sizeof(a [0])) // Num elements in an array
+#define NUMA(a) (sizeof(a) / sizeof((a)[0])) // Num elements in an array
 
 // Local types
 class Rectangle {
 public:
-    Rectangle(uint32_t graphicFormat = defaultFormat,
+    explicit Rectangle(uint32_t graphicFormat = defaultFormat,
               HwcTestDim dfDim = HwcTestDim(1, 1),
               HwcTestDim sDim = HwcTestDim(1, 1));
     void setSourceDim(HwcTestDim dim);
diff --git a/opengl/tests/hwc/hwcRects.cpp b/opengl/tests/hwc/hwcRects.cpp
index 2e2b204..69e56ff 100644
--- a/opengl/tests/hwc/hwcRects.cpp
+++ b/opengl/tests/hwc/hwcRects.cpp
@@ -137,7 +137,7 @@
 #define CMD_START_FRAMEWORK  "start 2>&1"
 
 // Macros
-#define NUMA(a) (sizeof(a) / sizeof(a [0])) // Num elements in an array
+#define NUMA(a) (sizeof(a) / sizeof((a)[0])) // Num elements in an array
 
 // Local types
 class Rectangle {
diff --git a/opengl/tests/hwc/hwcStress.cpp b/opengl/tests/hwc/hwcStress.cpp
index 60c29ef..1469f7c 100644
--- a/opengl/tests/hwc/hwcStress.cpp
+++ b/opengl/tests/hwc/hwcStress.cpp
@@ -162,7 +162,7 @@
 #define CMD_STOP_FRAMEWORK   "stop 2>&1"
 #define CMD_START_FRAMEWORK  "start 2>&1"
 
-#define NUMA(a) (sizeof(a) / sizeof(a [0]))
+#define NUMA(a) (sizeof(a) / sizeof((a)[0]))
 #define MEMCLR(addr, size) do { \
         memset((addr), 0, (size)); \
     } while (0)
diff --git a/services/batteryservice/IBatteryPropertiesListener.cpp b/services/batteryservice/IBatteryPropertiesListener.cpp
index 8aff26c..7555f4b 100644
--- a/services/batteryservice/IBatteryPropertiesListener.cpp
+++ b/services/batteryservice/IBatteryPropertiesListener.cpp
@@ -24,7 +24,7 @@
 class BpBatteryPropertiesListener : public BpInterface<IBatteryPropertiesListener>
 {
 public:
-    BpBatteryPropertiesListener(const sp<IBinder>& impl)
+    explicit BpBatteryPropertiesListener(const sp<IBinder>& impl)
         : BpInterface<IBatteryPropertiesListener>(impl)
     {
     }
diff --git a/services/batteryservice/IBatteryPropertiesRegistrar.cpp b/services/batteryservice/IBatteryPropertiesRegistrar.cpp
index 46934e0..1fdda43 100644
--- a/services/batteryservice/IBatteryPropertiesRegistrar.cpp
+++ b/services/batteryservice/IBatteryPropertiesRegistrar.cpp
@@ -28,7 +28,7 @@
 
 class BpBatteryPropertiesRegistrar : public BpInterface<IBatteryPropertiesRegistrar> {
 public:
-    BpBatteryPropertiesRegistrar(const sp<IBinder>& impl)
+    explicit BpBatteryPropertiesRegistrar(const sp<IBinder>& impl)
         : BpInterface<IBatteryPropertiesRegistrar>(impl) {}
 
         void registerListener(const sp<IBatteryPropertiesListener>& listener) {
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index 2a53dec..d2f8995 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -55,10 +55,10 @@
  * operation with a byte that only has the relevant bit set.
  * eg. to check for the 12th bit, we do (array[1] & 1<<4)
  */
-#define test_bit(bit, array)    (array[bit/8] & (1<<(bit%8)))
+#define test_bit(bit, array)    ((array)[(bit)/8] & (1<<((bit)%8)))
 
 /* this macro computes the number of bytes needed to represent a bit array of the specified size */
-#define sizeof_bit_array(bits)  ((bits + 7) / 8)
+#define sizeof_bit_array(bits)  (((bits) + 7) / 8)
 
 #define INDENT "  "
 #define INDENT2 "    "
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index a7fe69c..f12320d 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -325,7 +325,7 @@
         KeyedVector<int32_t, bool> leds;
         Vector<VirtualKeyDefinition> virtualKeys;
 
-        Device(uint32_t classes) :
+        explicit Device(uint32_t classes) :
                 classes(classes) {
         }
     };
diff --git a/services/nativeperms/.clang-format b/services/nativeperms/.clang-format
new file mode 100644
index 0000000..6006e6f
--- /dev/null
+++ b/services/nativeperms/.clang-format
@@ -0,0 +1,13 @@
+BasedOnStyle: Google
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: true
+AllowShortLoopsOnASingleLine: true
+BinPackArguments: true
+BinPackParameters: true
+ColumnLimit: 80
+CommentPragmas: NOLINT:.*
+ContinuationIndentWidth: 8
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Left
+TabWidth: 4
diff --git a/services/nativeperms/Android.mk b/services/nativeperms/Android.mk
new file mode 100644
index 0000000..34ccd0b
--- /dev/null
+++ b/services/nativeperms/Android.mk
@@ -0,0 +1,31 @@
+# Copyright 2016 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := nativeperms
+LOCAL_SRC_FILES := \
+    nativeperms.cpp \
+    android/os/IPermissionController.aidl
+LOCAL_CFLAGS := -Wall -Werror
+LOCAL_SHARED_LIBRARIES := \
+    libbinder \
+    libbrillo \
+    libbrillo-binder \
+    libchrome \
+    libutils
+LOCAL_INIT_RC := nativeperms.rc
+include $(BUILD_EXECUTABLE)
diff --git a/services/nativeperms/android/os/IPermissionController.aidl b/services/nativeperms/android/os/IPermissionController.aidl
new file mode 100644
index 0000000..89db85c
--- /dev/null
+++ b/services/nativeperms/android/os/IPermissionController.aidl
@@ -0,0 +1,25 @@
+/* //device/java/android/android/os/IPowerManager.aidl
+**
+** Copyright 2007, 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.
+*/
+
+package android.os;
+
+/** @hide */
+interface IPermissionController {
+    boolean checkPermission(String permission, int pid, int uid);
+    String[] getPackagesForUid(int uid);
+    boolean isRuntimePermission(String permission);
+}
diff --git a/services/nativeperms/android/os/README b/services/nativeperms/android/os/README
new file mode 100644
index 0000000..e414499
--- /dev/null
+++ b/services/nativeperms/android/os/README
@@ -0,0 +1,4 @@
+IPermissionController.aidl in this directory is a verbatim copy of
+https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/IPermissionController.aidl,
+because some Brillo manifests do not currently include the frameworks/base repo.
+TODO(jorgelo): Figure out a way to use the .aidl file in frameworks/base.
diff --git a/services/nativeperms/nativeperms.cpp b/services/nativeperms/nativeperms.cpp
new file mode 100644
index 0000000..7f03bed
--- /dev/null
+++ b/services/nativeperms/nativeperms.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#include <base/at_exit.h>
+#include <base/logging.h>
+#include <base/message_loop/message_loop.h>
+#include <binder/IServiceManager.h>
+#include <binder/Status.h>
+#include <brillo/binder_watcher.h>
+#include <brillo/message_loops/base_message_loop.h>
+#include <brillo/syslog_logging.h>
+#include <utils/String16.h>
+
+#include "android/os/BnPermissionController.h"
+
+namespace {
+static android::String16 serviceName("permission");
+}
+
+namespace android {
+
+class PermissionService : public android::os::BnPermissionController {
+   public:
+    ::android::binder::Status checkPermission(
+            const ::android::String16& permission, int32_t pid, int32_t uid,
+            bool* _aidl_return) {
+        (void)permission;
+        (void)pid;
+        (void)uid;
+        *_aidl_return = true;
+        return binder::Status::ok();
+    }
+
+    ::android::binder::Status getPackagesForUid(
+            int32_t uid, ::std::vector<::android::String16>* _aidl_return) {
+        (void)uid;
+        // Brillo doesn't currently have installable packages.
+        if (_aidl_return) {
+            _aidl_return->clear();
+        }
+        return binder::Status::ok();
+    }
+
+    ::android::binder::Status isRuntimePermission(
+            const ::android::String16& permission, bool* _aidl_return) {
+        (void)permission;
+        // Brillo doesn't currently have runtime permissions.
+        *_aidl_return = false;
+        return binder::Status::ok();
+    }
+};
+
+}  // namespace android
+
+int main() {
+    base::AtExitManager atExitManager;
+    brillo::InitLog(brillo::kLogToSyslog);
+    // Register the service with servicemanager.
+    android::status_t status = android::defaultServiceManager()->addService(
+            serviceName, new android::PermissionService());
+    CHECK(status == android::OK) << "Failed to get IPermissionController "
+                                    "binder from servicemanager.";
+
+    // Create a message loop.
+    base::MessageLoopForIO messageLoopForIo;
+    brillo::BaseMessageLoop messageLoop{&messageLoopForIo};
+
+    // Initialize a binder watcher.
+    brillo::BinderWatcher watcher(&messageLoop);
+    watcher.Init();
+
+    // Run the message loop.
+    messageLoop.Run();
+}
diff --git a/services/nativeperms/nativeperms.rc b/services/nativeperms/nativeperms.rc
new file mode 100644
index 0000000..704c0a2
--- /dev/null
+++ b/services/nativeperms/nativeperms.rc
@@ -0,0 +1,4 @@
+service nativeperms /system/bin/nativeperms
+    class main
+    user system
+    group system
diff --git a/services/powermanager/IPowerManager.cpp b/services/powermanager/IPowerManager.cpp
index bff8719..ea3a831 100644
--- a/services/powermanager/IPowerManager.cpp
+++ b/services/powermanager/IPowerManager.cpp
@@ -30,7 +30,7 @@
 class BpPowerManager : public BpInterface<IPowerManager>
 {
 public:
-    BpPowerManager(const sp<IBinder>& impl)
+    explicit BpPowerManager(const sp<IBinder>& impl)
         : BpInterface<IPowerManager>(impl)
     {
     }
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 68d4154..5f743fc 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -49,9 +49,9 @@
 #define IGNORE_HARDWARE_FUSION  false
 #define DEBUG_CONNECTIONS   false
 // Max size is 100 KB which is enough to accept a batch of about 1000 events.
-#define MAX_SOCKET_BUFFER_SIZE_BATCHED 100 * 1024
+#define MAX_SOCKET_BUFFER_SIZE_BATCHED (100 * 1024)
 // For older HALs which don't support batching, use a smaller socket buffer size.
-#define SOCKET_BUFFER_SIZE_NON_BATCHED 4 * 1024
+#define SOCKET_BUFFER_SIZE_NON_BATCHED (4 * 1024)
 
 #define SENSOR_REGISTRATIONS_BUF_SIZE 200
 
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index a67b3ff..5c2c0ad 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -415,6 +415,17 @@
 }
 
 // ----------------------------------------------------------------------------
+#ifdef USE_HWC2
+void DisplayDevice::setActiveColorMode(android_color_mode_t mode) {
+    mActiveColorMode = mode;
+}
+
+android_color_mode_t DisplayDevice::getActiveColorMode() const {
+    return mActiveColorMode;
+}
+#endif
+
+// ----------------------------------------------------------------------------
 
 void DisplayDevice::setLayerStack(uint32_t stack) {
     mLayerStack = stack;
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index dd9b104..105e980 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -182,6 +182,11 @@
     void setPowerMode(int mode);
     bool isDisplayOn() const;
 
+#ifdef USE_HWC2
+    android_color_mode_t getActiveColorMode() const;
+    void setActiveColorMode(android_color_mode_t mode);
+#endif
+
     /* ------------------------------------------------------------------------
      * Display active config management.
      */
@@ -252,6 +257,10 @@
     int mPowerMode;
     // Current active config
     int mActiveConfig;
+#ifdef USE_HWC2
+    // current active color mode
+    android_color_mode_t mActiveColorMode;
+#endif
 };
 
 }; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index ed8cc08..4fe3cfd 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -149,7 +149,12 @@
     }
 
     for (auto element : mDisplays) {
-        auto display = element.second;
+        auto display = element.second.lock();
+        if (!display) {
+            ALOGE("~Device: Found a display (%" PRId64 " that has already been"
+                    " destroyed", element.first);
+            continue;
+        }
 
         DisplayType displayType = HWC2::DisplayType::Invalid;
         auto error = display->getType(&displayType);
@@ -208,6 +213,10 @@
     ALOGI("Created virtual display");
     *format = static_cast<android_pixel_format_t>(intFormat);
     *outDisplay = getDisplayById(displayId);
+    if (!*outDisplay) {
+        ALOGE("Failed to get display by id");
+        return Error::BadDisplay;
+    }
     (*outDisplay)->setVirtual();
     return Error::None;
 }
@@ -289,7 +298,10 @@
 
 std::shared_ptr<Display> Device::getDisplayById(hwc2_display_t id) {
     if (mDisplays.count(id) != 0) {
-        return mDisplays.at(id);
+        auto strongDisplay = mDisplays[id].lock();
+        ALOGE_IF(!strongDisplay, "Display %" PRId64 " is in mDisplays but is no"
+                " longer alive", id);
+        return strongDisplay;
     }
 
     auto display = std::make_shared<Display>(*this, id);
@@ -305,9 +317,12 @@
             "Capability size has changed");
     uint32_t numCapabilities = 0;
     mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, nullptr);
-    mCapabilities.resize(numCapabilities);
-    auto asInt = reinterpret_cast<int32_t*>(mCapabilities.data());
+    std::vector<Capability> capabilities(numCapabilities);
+    auto asInt = reinterpret_cast<int32_t*>(capabilities.data());
     mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, asInt);
+    for (auto capability : capabilities) {
+        mCapabilities.emplace(capability);
+    }
 }
 
 bool Device::hasCapability(HWC2::Capability capability) const
@@ -430,6 +445,7 @@
     auto error = static_cast<Error>(intError);
     ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64 ") failed:"
             " %s (%d)", display, to_string(error).c_str(), intError);
+    mDisplays.erase(display);
 }
 
 // Display methods
@@ -565,7 +581,7 @@
     return Error::None;
 }
 
-Error Display::getColorModes(std::vector<int32_t>* outModes) const
+Error Display::getColorModes(std::vector<android_color_mode_t>* outModes) const
 {
     uint32_t numModes = 0;
     int32_t intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId,
@@ -583,7 +599,10 @@
         return error;
     }
 
-    std::swap(*outModes, modes);
+    outModes->resize(numModes);
+    for (size_t i = 0; i < numModes; i++) {
+        (*outModes)[i] = static_cast<android_color_mode_t>(modes[i]);
+    }
     return Error::None;
 }
 
@@ -789,7 +808,7 @@
     return static_cast<Error>(intError);
 }
 
-Error Display::setColorMode(int32_t mode)
+Error Display::setColorMode(android_color_mode_t mode)
 {
     int32_t intError = mDevice.mSetColorMode(mDevice.mHwcDevice, mId, mode);
     return static_cast<Error>(intError);
@@ -810,6 +829,7 @@
     auto handle = buffer->getNativeBuffer()->handle;
     int32_t intError = mDevice.mSetOutputBuffer(mDevice.mHwcDevice, mId, handle,
             fenceFd);
+    close(fenceFd);
     return static_cast<Error>(intError);
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 8ab61e9..fb04af8 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -33,6 +33,7 @@
 #include <functional>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 namespace android {
@@ -66,7 +67,7 @@
 
     std::string dump() const;
 
-    const std::vector<Capability>& getCapabilities() const {
+    const std::unordered_set<Capability>& getCapabilities() const {
         return mCapabilities;
     };
 
@@ -88,7 +89,8 @@
     // Other Device methods
 
     // This will create a Display if one is not found, but it will not be marked
-    // as connected
+    // as connected. This Display may be null if the display has been torn down
+    // but has not been removed from the map yet.
     std::shared_ptr<Display> getDisplayById(hwc2_display_t id);
 
     bool hasCapability(HWC2::Capability capability) const;
@@ -180,8 +182,8 @@
     HWC2_PFN_SET_LAYER_VISIBLE_REGION mSetLayerVisibleRegion;
     HWC2_PFN_SET_LAYER_Z_ORDER mSetLayerZOrder;
 
-    std::vector<Capability> mCapabilities;
-    std::unordered_map<hwc2_display_t, std::shared_ptr<Display>> mDisplays;
+    std::unordered_set<Capability> mCapabilities;
+    std::unordered_map<hwc2_display_t, std::weak_ptr<Display>> mDisplays;
 
     HotplugCallback mHotplug;
     std::vector<std::pair<std::shared_ptr<Display>, Connection>>
@@ -280,7 +282,7 @@
     [[clang::warn_unused_result]] Error getChangedCompositionTypes(
             std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes);
     [[clang::warn_unused_result]] Error getColorModes(
-            std::vector<int32_t>* outModes) const;
+            std::vector<android_color_mode_t>* outModes) const;
 
     // Doesn't call into the HWC2 device, so no errors are possible
     std::vector<std::shared_ptr<const Config>> getConfigs() const;
@@ -305,7 +307,7 @@
             buffer_handle_t target,
             const android::sp<android::Fence>& acquireFence,
             android_dataspace_t dataspace);
-    [[clang::warn_unused_result]] Error setColorMode(int32_t mode);
+    [[clang::warn_unused_result]] Error setColorMode(android_color_mode_t mode);
     [[clang::warn_unused_result]] Error setColorTransform(
             const android::mat4& matrix, android_color_transform_t hint);
     [[clang::warn_unused_result]] Error setOutputBuffer(
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
index e739ef4..8bcee39 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
@@ -75,7 +75,7 @@
 
 using namespace HWC2;
 
-static constexpr Attribute ColorTransform = static_cast<Attribute>(6);
+static constexpr Attribute ColorMode = static_cast<Attribute>(6);
 
 namespace android {
 
@@ -268,9 +268,7 @@
                     &Display::setClientTarget, buffer_handle_t, int32_t,
                     int32_t, hwc_region_t>);
         case FunctionDescriptor::SetColorMode:
-            return asFP<HWC2_PFN_SET_COLOR_MODE>(
-                    displayHook<decltype(&Display::setColorMode),
-                    &Display::setColorMode, int32_t>);
+            return asFP<HWC2_PFN_SET_COLOR_MODE>(setColorModeHook);
         case FunctionDescriptor::SetColorTransform:
             return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook);
         case FunctionDescriptor::SetOutputBuffer:
@@ -894,7 +892,7 @@
     return Error::None;
 }
 
-Error HWC2On1Adapter::Display::setColorMode(int32_t mode)
+Error HWC2On1Adapter::Display::setColorMode(android_color_mode_t mode)
 {
     std::unique_lock<std::recursive_mutex> lock (mStateMutex);
 
@@ -1198,11 +1196,14 @@
         newConfig->setAttribute(Attribute::DpiY,
                 values[attributeMap[HWC_DISPLAY_DPI_Y]]);
         if (hasColor) {
-            newConfig->setAttribute(ColorTransform,
+            // In HWC1, color modes are referred to as color transforms. To avoid confusion with
+            // the HWC2 concept of color transforms, we internally refer to them as color modes for
+            // both HWC1 and 2.
+            newConfig->setAttribute(ColorMode,
                     values[attributeMap[HWC_DISPLAY_COLOR_TRANSFORM]]);
         }
 
-        // We can only do this after attempting to read the color transform
+        // We can only do this after attempting to read the color mode
         newConfig->setHwc1Id(hwc1ConfigId);
 
         for (auto& existingConfig : mConfigs) {
@@ -1678,8 +1679,8 @@
 
 void HWC2On1Adapter::Display::Config::setHwc1Id(uint32_t id)
 {
-    int32_t colorTransform = getAttribute(ColorTransform);
-    mHwc1Ids.emplace(colorTransform, id);
+    android_color_mode_t colorMode = static_cast<android_color_mode_t>(getAttribute(ColorMode));
+    mHwc1Ids.emplace(colorMode, id);
 }
 
 bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const
@@ -1692,18 +1693,20 @@
     return false;
 }
 
-int32_t HWC2On1Adapter::Display::Config::getColorModeForHwc1Id(
-        uint32_t id) const
+Error HWC2On1Adapter::Display::Config::getColorModeForHwc1Id(
+        uint32_t id, android_color_mode_t* outMode) const
 {
     for (const auto& idPair : mHwc1Ids) {
         if (id == idPair.second) {
-            return idPair.first;
+            *outMode = idPair.first;
+            return Error::None;
         }
     }
-    return -1;
+    ALOGE("Unable to find color mode for HWC ID %" PRIu32 " on config %u", id, mId);
+    return Error::BadParameter;
 }
 
-Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(int32_t mode,
+Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(android_color_mode_t mode,
         uint32_t* outId) const
 {
     for (const auto& idPair : mHwc1Ids) {
@@ -1726,25 +1729,26 @@
             return false;
         }
     }
-    int32_t otherColorTransform = other.getAttribute(ColorTransform);
-    if (mHwc1Ids.count(otherColorTransform) != 0) {
+    android_color_mode_t otherColorMode =
+            static_cast<android_color_mode_t>(other.getAttribute(ColorMode));
+    if (mHwc1Ids.count(otherColorMode) != 0) {
         ALOGE("Attempted to merge two configs (%u and %u) which appear to be "
-                "identical", mHwc1Ids.at(otherColorTransform),
-                other.mHwc1Ids.at(otherColorTransform));
+                "identical", mHwc1Ids.at(otherColorMode),
+                other.mHwc1Ids.at(otherColorMode));
         return false;
     }
-    mHwc1Ids.emplace(otherColorTransform,
-            other.mHwc1Ids.at(otherColorTransform));
+    mHwc1Ids.emplace(otherColorMode,
+            other.mHwc1Ids.at(otherColorMode));
     return true;
 }
 
-std::set<int32_t> HWC2On1Adapter::Display::Config::getColorTransforms() const
+std::set<android_color_mode_t> HWC2On1Adapter::Display::Config::getColorModes() const
 {
-    std::set<int32_t> colorTransforms;
+    std::set<android_color_mode_t> colorModes;
     for (const auto& idPair : mHwc1Ids) {
-        colorTransforms.emplace(idPair.first);
+        colorModes.emplace(idPair.first);
     }
-    return colorTransforms;
+    return colorModes;
 }
 
 std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const
@@ -1787,15 +1791,15 @@
 
 
     for (const auto& id : mHwc1Ids) {
-        int32_t colorTransform = id.first;
+        android_color_mode_t colorMode = id.first;
         uint32_t hwc1Id = id.second;
         std::memset(buffer, 0, BUFFER_SIZE);
-        if (colorTransform == mDisplay.mActiveColorMode) {
+        if (colorMode == mDisplay.mActiveColorMode) {
             writtenBytes = snprintf(buffer, BUFFER_SIZE, " [%u/%d]", hwc1Id,
-                    colorTransform);
+                    colorMode);
         } else {
             writtenBytes = snprintf(buffer, BUFFER_SIZE, " %u/%d", hwc1Id,
-                    colorTransform);
+                    colorMode);
         }
         output.append(buffer, writtenBytes);
     }
@@ -1814,10 +1818,10 @@
 
 void HWC2On1Adapter::Display::populateColorModes()
 {
-    mColorModes = mConfigs[0]->getColorTransforms();
+    mColorModes = mConfigs[0]->getColorModes();
     for (const auto& config : mConfigs) {
-        std::set<int32_t> intersection;
-        auto configModes = config->getColorTransforms();
+        std::set<android_color_mode_t> intersection;
+        auto configModes = config->getColorModes();
         std::set_intersection(mColorModes.cbegin(), mColorModes.cend(),
                 configModes.cbegin(), configModes.cend(),
                 std::inserter(intersection, intersection.begin()));
@@ -1830,7 +1834,7 @@
     if (mDevice.mHwc1Device->getActiveConfig == nullptr) {
         ALOGV("getActiveConfig is null, choosing config 0");
         mActiveConfig = mConfigs[0];
-        mActiveColorMode = -1;
+        mActiveColorMode = HAL_COLOR_MODE_NATIVE;
         return;
     }
 
@@ -1842,7 +1846,13 @@
                 ALOGV("Setting active config to %d for HWC1 config %u",
                         config->getId(), activeConfig);
                 mActiveConfig = config;
-                mActiveColorMode = config->getColorModeForHwc1Id(activeConfig);
+                if (config->getColorModeForHwc1Id(activeConfig, &mActiveColorMode) != Error::None) {
+                    // This should never happen since we checked for the config's presence before
+                    // setting it as active.
+                    ALOGE("Unable to find color mode for active HWC1 config %d",
+                            config->getId());
+                    mActiveColorMode = HAL_COLOR_MODE_NATIVE;
+                }
                 break;
             }
         }
@@ -1850,7 +1860,7 @@
             ALOGV("Unable to find active HWC1 config %u, defaulting to "
                     "config 0", activeConfig);
             mActiveConfig = mConfigs[0];
-            mActiveColorMode = -1;
+            mActiveColorMode = HAL_COLOR_MODE_NATIVE;
         }
     }
 }
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
index dc7c355..bdacc73 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
@@ -213,7 +213,7 @@
             HWC2::Error setClientTarget(buffer_handle_t target,
                     int32_t acquireFence, int32_t dataspace,
                     hwc_region_t damage);
-            HWC2::Error setColorMode(int32_t mode);
+            HWC2::Error setColorMode(android_color_mode_t mode);
             HWC2::Error setColorTransform(android_color_transform_t hint);
             HWC2::Error setOutputBuffer(buffer_handle_t buffer,
                     int32_t releaseFence);
@@ -258,8 +258,9 @@
 
                     void setHwc1Id(uint32_t id);
                     bool hasHwc1Id(uint32_t id) const;
-                    int32_t getColorModeForHwc1Id(uint32_t id) const;
-                    HWC2::Error getHwc1IdForColorMode(int32_t mode,
+                    HWC2::Error getColorModeForHwc1Id(uint32_t id,
+                            android_color_mode_t *outMode) const;
+                    HWC2::Error getHwc1IdForColorMode(android_color_mode_t mode,
                             uint32_t* outId) const;
 
                     void setId(hwc2_config_t id) { mId = id; }
@@ -269,7 +270,7 @@
                     // mode. Returns whether the merge was successful
                     bool merge(const Config& other);
 
-                    std::set<int32_t> getColorTransforms() const;
+                    std::set<android_color_mode_t> getColorModes() const;
 
                     // splitLine divides the output into two lines suitable for
                     // dumpsys SurfaceFlinger
@@ -281,7 +282,7 @@
                     std::unordered_map<HWC2::Attribute, int32_t> mAttributes;
 
                     // Maps from color transform to HWC1 config ID
-                    std::unordered_map<int32_t, uint32_t> mHwc1Ids;
+                    std::unordered_map<android_color_mode_t, uint32_t> mHwc1Ids;
             };
 
             class Changes {
@@ -378,8 +379,8 @@
 
             std::vector<std::shared_ptr<Config>> mConfigs;
             std::shared_ptr<const Config> mActiveConfig;
-            std::set<int32_t> mColorModes;
-            int32_t mActiveColorMode;
+            std::set<android_color_mode_t> mColorModes;
+            android_color_mode_t mActiveColorMode;
             std::string mName;
             HWC2::DisplayType mType;
             HWC2::PowerMode mPowerMode;
@@ -432,6 +433,12 @@
                 hint);
     }
 
+    static int32_t setColorModeHook(hwc2_device_t* device,
+            hwc2_display_t display, int32_t /*android_color_mode_t*/ intMode) {
+        auto mode = static_cast<android_color_mode_t>(intMode);
+        return callDisplayFunction(device, display, &Display::setColorMode, mode);
+    }
+
     static int32_t setPowerModeHook(hwc2_device_t* device,
             hwc2_display_t display, int32_t intMode) {
         auto mode = static_cast<HWC2::PowerMode>(intMode);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 133e5f1..c87ba72 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -144,6 +144,11 @@
     mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
 }
 
+bool HWComposer::hasCapability(HWC2::Capability capability) const
+{
+    return mHwcDevice->getCapabilities().count(capability) > 0;
+}
+
 bool HWComposer::isValidDisplay(int32_t displayId) const {
     return static_cast<size_t>(displayId) < mDisplayData.size() &&
             mDisplayData[displayId].hwcDisplay;
@@ -359,8 +364,8 @@
     return config;
 }
 
-std::vector<int32_t> HWComposer::getColorModes(int32_t displayId) const {
-    std::vector<int32_t> modes;
+std::vector<android_color_mode_t> HWComposer::getColorModes(int32_t displayId) const {
+    std::vector<android_color_mode_t> modes;
 
     if (!isValidDisplay(displayId)) {
         ALOGE("getColorModes: Attempted to access invalid display %d",
@@ -374,12 +379,31 @@
     if (error != HWC2::Error::None) {
         ALOGE("getColorModes failed for display %d: %s (%d)", displayId,
                 to_string(error).c_str(), static_cast<int32_t>(error));
-        return std::vector<int32_t>();
+        return std::vector<android_color_mode_t>();
     }
 
     return modes;
 }
 
+status_t HWComposer::setActiveColorMode(int32_t displayId, android_color_mode_t mode) {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("setActiveColorMode: Display %d is not valid", displayId);
+        return BAD_INDEX;
+    }
+
+    auto& displayData = mDisplayData[displayId];
+    auto error = displayData.hwcDisplay->setColorMode(mode);
+    if (error != HWC2::Error::None) {
+        ALOGE("setActiveConfig: Failed to set color mode %d on display %d: "
+                "%s (%d)", mode, displayId, to_string(error).c_str(),
+                static_cast<int32_t>(error));
+        return UNKNOWN_ERROR;
+    }
+
+    return NO_ERROR;
+}
+
+
 void HWComposer::setVsyncEnabled(int32_t disp, HWC2::Vsync enabled) {
     if (disp < 0 || disp >= HWC_DISPLAY_VIRTUAL) {
         ALOGD("setVsyncEnabled: Ignoring for virtual display %d", disp);
@@ -443,6 +467,10 @@
 
     Mutex::Autolock _l(mDisplayLock);
     auto displayId = displayDevice.getHwcDisplayId();
+    if (displayId == DisplayDevice::DISPLAY_ID_INVALID) {
+        ALOGV("Skipping HWComposer prepare for non-HWC display");
+        return NO_ERROR;
+    }
     if (!isValidDisplay(displayId)) {
         return BAD_INDEX;
     }
@@ -536,6 +564,11 @@
 }
 
 bool HWComposer::hasDeviceComposition(int32_t displayId) const {
+    if (displayId == DisplayDevice::DISPLAY_ID_INVALID) {
+        // Displays without a corresponding HWC display are never composed by
+        // the device
+        return false;
+    }
     if (!isValidDisplay(displayId)) {
         ALOGE("hasDeviceComposition: Invalid display %d", displayId);
         return false;
@@ -544,6 +577,11 @@
 }
 
 bool HWComposer::hasClientComposition(int32_t displayId) const {
+    if (displayId == DisplayDevice::DISPLAY_ID_INVALID) {
+        // Displays without a corresponding HWC display are always composed by
+        // the client
+        return true;
+    }
     if (!isValidDisplay(displayId)) {
         ALOGE("hasClientComposition: Invalid display %d", displayId);
         return true;
@@ -692,6 +730,28 @@
     return NO_ERROR;
 }
 
+status_t HWComposer::setColorTransform(int32_t displayId,
+        const mat4& transform) {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("setColorTransform: Display %d is not valid", displayId);
+        return BAD_INDEX;
+    }
+
+    auto& displayData = mDisplayData[displayId];
+    bool isIdentity = transform == mat4();
+    auto error = displayData.hwcDisplay->setColorTransform(transform,
+            isIdentity ? HAL_COLOR_TRANSFORM_IDENTITY :
+            HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX);
+    if (error != HWC2::Error::None) {
+        ALOGE("setColorTransform: Failed to set transform on display %d: "
+                "%s (%d)", displayId, to_string(error).c_str(),
+                static_cast<int32_t>(error));
+        return UNKNOWN_ERROR;
+    }
+
+    return NO_ERROR;
+}
+
 void HWComposer::disconnectDisplay(int displayId) {
     LOG_ALWAYS_FATAL_IF(displayId < 0);
     auto& displayData = mDisplayData[displayId];
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index aa233df..41671f6 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -81,6 +81,8 @@
 
     void setEventHandler(EventHandler* handler);
 
+    bool hasCapability(HWC2::Capability capability) const;
+
     // Attempts to allocate a virtual display. If the virtual display is created
     // on the HWC device, outId will contain its HWC ID.
     status_t allocateVirtualDisplay(uint32_t width, uint32_t height,
@@ -104,6 +106,9 @@
     // set active config
     status_t setActiveConfig(int32_t displayId, size_t configId);
 
+    // Sets a color transform to be applied to the result of composition
+    status_t setColorTransform(int32_t displayId, const mat4& transform);
+
     // reset state when an external, non-virtual display is disconnected
     void disconnectDisplay(int32_t displayId);
 
@@ -149,7 +154,9 @@
     std::shared_ptr<const HWC2::Display::Config>
             getActiveConfig(int32_t displayId) const;
 
-    std::vector<int32_t> getColorModes(int32_t displayId) const;
+    std::vector<android_color_mode_t> getColorModes(int32_t displayId) const;
+
+    status_t setActiveColorMode(int32_t displayId, android_color_mode_t mode);
 
     // for debugging ----------------------------------------------------------
     void dump(String8& out) const;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
index 4afd8a2..ef41658 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
@@ -42,6 +42,8 @@
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
+#include <system/graphics.h>
+
 #include "HWComposer.h"
 
 #include "../Layer.h"           // needed only for debugging
@@ -403,7 +405,7 @@
                     config.ydpi = values[i] / 1000.0f;
                     break;
                 case HWC_DISPLAY_COLOR_TRANSFORM:
-                    config.colorTransform = values[i];
+                    config.colorMode = static_cast<android_color_mode_t>(values[i]);
                     break;
                 default:
                     ALOG_ASSERT(false, "unknown display attribute[%zu] %#x",
@@ -519,6 +521,11 @@
     return mDisplayData[disp].configs[currentConfig].refresh;
 }
 
+android_color_mode_t HWComposer::getColorMode(int disp) const {
+    size_t currentConfig = mDisplayData[disp].currentConfig;
+    return mDisplayData[disp].configs[currentConfig].colorMode;
+}
+
 const Vector<HWComposer::DisplayConfig>& HWComposer::getConfigs(int disp) const {
     return mDisplayData[disp].configs;
 }
@@ -1182,10 +1189,10 @@
             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 ", colorTransform=%d\n",
+                        ", refresh=%" PRId64 ", colorMode=%d\n",
                         c == disp.currentConfig ? "* " : "", c,
                         config.width, config.height, config.xdpi, config.ydpi,
-                        config.refresh, config.colorTransform);
+                        config.refresh, config.colorMode);
             }
 
             if (disp.list) {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
index c861817..170e382 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
@@ -22,6 +22,8 @@
 
 #include <hardware/hwcomposer_defs.h>
 
+#include <system/graphics.h>
+
 #include <ui/Fence.h>
 
 #include <utils/BitSet.h>
@@ -257,7 +259,15 @@
         float xdpi;
         float ydpi;
         nsecs_t refresh;
-        int colorTransform;
+        android_color_mode_t colorMode;
+        bool operator==(const DisplayConfig& rhs) const {
+            return width == rhs.width &&
+                    height == rhs.height &&
+                    xdpi == rhs.xdpi &&
+                    ydpi == rhs.ydpi &&
+                    refresh == rhs.refresh &&
+                    colorMode == rhs.colorMode;
+        }
     };
 
     // Query display parameters.  Pass in a display index (e.g.
@@ -274,6 +284,7 @@
     float getDpiX(int disp) const;
     float getDpiY(int disp) const;
     nsecs_t getRefreshPeriod(int disp) const;
+    android_color_mode_t getColorMode(int disp) const;
 
     const Vector<DisplayConfig>& getConfigs(int disp) const;
     size_t getCurrentConfig(int disp) const;
diff --git a/services/surfaceflinger/Effects/Daltonizer.cpp b/services/surfaceflinger/Effects/Daltonizer.cpp
index feb8936..a104e8f 100644
--- a/services/surfaceflinger/Effects/Daltonizer.cpp
+++ b/services/surfaceflinger/Effects/Daltonizer.cpp
@@ -19,21 +19,14 @@
 
 namespace android {
 
-Daltonizer::Daltonizer() :
-    mType(deuteranomaly), mMode(simulation), mDirty(true) {
-}
-
-Daltonizer::~Daltonizer() {
-}
-
-void Daltonizer::setType(Daltonizer::ColorBlindnessTypes type) {
+void Daltonizer::setType(ColorBlindnessType type) {
     if (type != mType) {
         mDirty = true;
         mType = type;
     }
 }
 
-void Daltonizer::setMode(Daltonizer::Mode mode) {
+void Daltonizer::setMode(ColorBlindnessMode mode) {
     if (mode != mMode) {
         mDirty = true;
         mMode = mode;
@@ -49,6 +42,11 @@
 }
 
 void Daltonizer::update() {
+    if (mType == ColorBlindnessType::None) {
+        mColorTransform = mat4();
+        return;
+    }
+
     // converts a linear RGB color to the XYZ space
     const mat4 rgb2xyz( 0.4124, 0.2126, 0.0193, 0,
                         0.3576, 0.7152, 0.1192, 0,
@@ -149,24 +147,25 @@
     mat4 correction(0);
 
     switch (mType) {
-        case protanopia:
-        case protanomaly:
+        case ColorBlindnessType::Protanomaly:
             simulation = lms2lmsp;
-            if (mMode == Daltonizer::correction)
+            if (mMode == ColorBlindnessMode::Correction)
                 correction = errp;
             break;
-        case deuteranopia:
-        case deuteranomaly:
+        case ColorBlindnessType::Deuteranomaly:
             simulation = lms2lmsd;
-            if (mMode == Daltonizer::correction)
+            if (mMode == ColorBlindnessMode::Correction)
                 correction = errd;
             break;
-        case tritanopia:
-        case tritanomaly:
+        case ColorBlindnessType::Tritanomaly:
             simulation = lms2lmst;
-            if (mMode == Daltonizer::correction)
+            if (mMode == ColorBlindnessMode::Correction)
                 correction = errt;
             break;
+        case ColorBlindnessType::None:
+            // We already caught this at the beginning of the method, but the
+            // compiler doesn't know that
+            break;
     }
 
     mColorTransform = lms2rgb *
diff --git a/services/surfaceflinger/Effects/Daltonizer.h b/services/surfaceflinger/Effects/Daltonizer.h
index e816437..d21b155 100644
--- a/services/surfaceflinger/Effects/Daltonizer.h
+++ b/services/surfaceflinger/Effects/Daltonizer.h
@@ -21,27 +21,22 @@
 
 namespace android {
 
+enum class ColorBlindnessType {
+    None,               // Disables the Daltonizer
+    Protanomaly,        // L (red) cone deficient
+    Deuteranomaly,      // M (green) cone deficient (most common)
+    Tritanomaly         // S (blue) cone deficient
+};
+
+enum class ColorBlindnessMode {
+    Simulation,
+    Correction
+};
+
 class Daltonizer {
 public:
-    enum ColorBlindnessTypes {
-        protanopia,         // L (red) cone missing
-        deuteranopia,       // M (green) cone missing
-        tritanopia,         // S (blue) cone missing
-        protanomaly,        // L (red) cone deficient
-        deuteranomaly,      // M (green) cone deficient (most common)
-        tritanomaly         // S (blue) cone deficient
-    };
-
-    enum Mode {
-        simulation,
-        correction
-    };
-
-    Daltonizer();
-    ~Daltonizer();
-
-    void setType(ColorBlindnessTypes type);
-    void setMode(Mode mode);
+    void setType(ColorBlindnessType type);
+    void setMode(ColorBlindnessMode mode);
 
     // returns the color transform to apply in the shader
     const mat4& operator()();
@@ -49,9 +44,9 @@
 private:
     void update();
 
-    ColorBlindnessTypes mType;
-    Mode mMode;
-    bool mDirty;
+    ColorBlindnessType mType = ColorBlindnessType::None;
+    ColorBlindnessMode mMode = ColorBlindnessMode::Simulation;
+    bool mDirty = true;
     mat4 mColorTransform;
 };
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 548b048..bfde709 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -51,6 +51,8 @@
 
 #include "RenderEngine/RenderEngine.h"
 
+#include <mutex>
+
 #define DEBUG_RESIZE    0
 
 namespace android {
@@ -161,9 +163,7 @@
     mSurfaceFlingerConsumer->setContentsChangedListener(this);
     mSurfaceFlingerConsumer->setName(mName);
 
-#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
-#warning "disabling triple buffering"
-#else
+#ifndef TARGET_DISABLE_TRIPLE_BUFFERING
     mProducer->setMaxDequeuedBufferCount(2);
 #endif
 
@@ -1056,8 +1056,13 @@
 }
 
 HWC2::Composition Layer::getCompositionType(int32_t hwcId) const {
+    if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) {
+        // If we're querying the composition type for a display that does not
+        // have a HWC counterpart, then it will always be Client
+        return HWC2::Composition::Client;
+    }
     if (mHwcLayers.count(hwcId) == 0) {
-        ALOGE("getCompositionType called without a valid HWC layer");
+        ALOGE("getCompositionType called with an invalid HWC layer");
         return HWC2::Composition::Invalid;
     }
     return mHwcLayers.at(hwcId).compositionType;
@@ -1091,6 +1096,20 @@
     return static_cast<uint32_t>(producerStickyTransform);
 }
 
+bool Layer::latchUnsignaledBuffers() {
+    static bool propertyLoaded = false;
+    static bool latch = false;
+    static std::mutex mutex;
+    std::lock_guard<std::mutex> lock(mutex);
+    if (!propertyLoaded) {
+        char value[PROPERTY_VALUE_MAX] = {};
+        property_get("debug.sf.latch_unsignaled", value, "0");
+        latch = atoi(value);
+        propertyLoaded = true;
+    }
+    return latch;
+}
+
 uint64_t Layer::getHeadFrameNumber() const {
     Mutex::Autolock lock(mQueueItemLock);
     if (!mQueueItems.empty()) {
@@ -1102,6 +1121,10 @@
 
 bool Layer::headFenceHasSignaled() const {
 #ifdef USE_HWC2
+    if (latchUnsignaledBuffers()) {
+        return true;
+    }
+
     Mutex::Autolock lock(mQueueItemLock);
     if (mQueueItems.empty()) {
         return true;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 78a8427..c070539 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -465,6 +465,9 @@
     // Temporary - Used only for LEGACY camera mode.
     uint32_t getProducerStickyTransform() const;
 
+    // Loads the corresponding system property once per process
+    static bool latchUnsignaledBuffers();
+
     // -----------------------------------------------------------------------
 
     class SyncPoint
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e5d5ebe..696b13f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -90,6 +90,19 @@
 
 EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
 
+// Workaround for b/30067360: /proc/self/environ inaccessible in SurfaceFlinger
+// => ASan fails to read ASAN_OPTIONS => alloc-dealloc-mismatch bug is not
+// suppressed and prevents the device from booting.
+#ifndef __has_feature
+#define __has_feature(x) 0
+#endif
+#if __has_feature(address_sanitizer)
+__attribute__((visibility("default")))
+extern "C" const char* __asan_default_options() {
+  return "alloc_dealloc_mismatch=0";
+}
+#endif
+
 namespace android {
 
 // This is the phase offset in nanoseconds of the software vsync event
@@ -152,7 +165,6 @@
         mPrimaryDispSync("PrimaryDispSync"),
         mPrimaryHWVsyncEnabled(false),
         mHWVsyncAvailable(false),
-        mDaltonize(false),
         mHasColorMatrix(false),
         mHasPoweredOff(false),
         mFrameBuckets(),
@@ -180,6 +192,10 @@
     }
     ALOGI_IF(mDebugRegion, "showupdates enabled");
     ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
+
+    property_get("debug.sf.disable_backpressure", value, "0");
+    mPropagateBackpressure = !atoi(value);
+    ALOGI_IF(!mPropagateBackpressure, "Disabling backpressure propagation");
 }
 
 void SurfaceFlinger::onFirstRef()
@@ -632,18 +648,7 @@
         // All non-virtual displays are currently considered secure.
         info.secure = true;
 
-        // DisplayManager expects each color mode to be its own display
-        // info record.
-        std::vector<int32_t> modes = getHwComposer().getColorModes(type);
-
-        if (modes.size() == 0) {
-            info.colorTransform = 0;
-            configs->push_back(info);
-        }
-        for (int32_t mode : modes) {
-            info.colorTransform = mode;
-            configs->push_back(info);
-        }
+        configs->push_back(info);
     }
 
     return NO_ERROR;
@@ -705,6 +710,7 @@
             if (mMode < 0 || mMode >= static_cast<int>(configs.size())) {
                 ALOGE("Attempt to set active config = %d for display with %zu configs",
                         mMode, configs.size());
+                return true;
             }
             sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
             if (hw == NULL) {
@@ -723,6 +729,101 @@
     postMessageSync(msg);
     return NO_ERROR;
 }
+status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& display,
+        Vector<android_color_mode_t>* outColorModes) {
+    if ((outColorModes == nullptr) || (display.get() == nullptr)) {
+        return BAD_VALUE;
+    }
+
+    if (!display.get()) {
+        return NAME_NOT_FOUND;
+    }
+
+    int32_t type = NAME_NOT_FOUND;
+    for (int i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
+        if (display == mBuiltinDisplays[i]) {
+            type = i;
+            break;
+        }
+    }
+
+    if (type < 0) {
+        return type;
+    }
+
+    std::vector<android_color_mode_t> modes = getHwComposer().getColorModes(type);
+    outColorModes->clear();
+    std::copy(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes));
+
+    return NO_ERROR;
+}
+
+android_color_mode_t SurfaceFlinger::getActiveColorMode(const sp<IBinder>& display) {
+    sp<DisplayDevice> device(getDisplayDevice(display));
+    if (device != nullptr) {
+        return device->getActiveColorMode();
+    }
+    return static_cast<android_color_mode_t>(BAD_VALUE);
+}
+
+void SurfaceFlinger::setActiveColorModeInternal(const sp<DisplayDevice>& hw,
+        android_color_mode_t mode) {
+    ALOGD("Set active color mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
+          this);
+    int32_t type = hw->getDisplayType();
+    android_color_mode_t currentMode = hw->getActiveColorMode();
+
+    if (mode == currentMode) {
+        ALOGD("Screen type=%d is already in color mode=%d", hw->getDisplayType(), mode);
+        return;
+    }
+
+    if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
+        ALOGW("Trying to set config for virtual display");
+        return;
+    }
+
+    hw->setActiveColorMode(mode);
+    getHwComposer().setActiveColorMode(type, mode);
+}
+
+
+status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& display,
+        android_color_mode_t colorMode) {
+    class MessageSetActiveColorMode: public MessageBase {
+        SurfaceFlinger& mFlinger;
+        sp<IBinder> mDisplay;
+        android_color_mode_t mMode;
+    public:
+        MessageSetActiveColorMode(SurfaceFlinger& flinger, const sp<IBinder>& disp,
+                               android_color_mode_t mode) :
+            mFlinger(flinger), mDisplay(disp) { mMode = mode; }
+        virtual bool handler() {
+            Vector<android_color_mode_t> modes;
+            mFlinger.getDisplayColorModes(mDisplay, &modes);
+            bool exists = std::find(std::begin(modes), std::end(modes), mMode) != std::end(modes);
+            if (mMode < 0 || !exists) {
+                ALOGE("Attempt to set invalid active color mode = %d for display %p", mMode,
+                        mDisplay.get());
+                return true;
+            }
+            sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
+            if (hw == nullptr) {
+                ALOGE("Attempt to set active color mode = %d for null display %p",
+                        mMode, mDisplay.get());
+            } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
+                ALOGW("Attempt to set active color mode= %d for virtual display",
+                        mMode);
+            } else {
+                mFlinger.setActiveColorModeInternal(hw, mMode);
+            }
+            return true;
+        }
+    };
+    sp<MessageBase> msg = new MessageSetActiveColorMode(*this, display, colorMode);
+    postMessageSync(msg);
+    return NO_ERROR;
+}
 
 status_t SurfaceFlinger::clearAnimationFrameStats() {
     Mutex::Autolock _l(mStateLock);
@@ -925,7 +1026,7 @@
                     mPreviousPresentFence != Fence::NO_FENCE &&
                     mPreviousPresentFence->getSignalTime() == INT64_MAX;
             ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
-            if (frameMissed) {
+            if (mPropagateBackpressure && frameMissed) {
                 signalLayerUpdate();
                 break;
             }
@@ -975,7 +1076,13 @@
     postComposition(refreshStartTime);
 
     mPreviousPresentFence = mHwc->getRetireFence(HWC_DISPLAY_PRIMARY);
-    mHadClientComposition = mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY);
+
+    mHadClientComposition = false;
+    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
+        const sp<DisplayDevice>& displayDevice = mDisplays[displayId];
+        mHadClientComposition = mHadClientComposition ||
+                mHwc->hasClientComposition(displayDevice->getHwcDisplayId());
+    }
 
     // Release any buffers which were replaced this frame
     for (auto& layer : mLayersWithQueuedFrames) {
@@ -1224,8 +1331,7 @@
                     }
 
                     layer->setGeometry(displayDevice);
-                    if (mDebugDisableHWC || mDebugRegion || mDaltonize ||
-                            mHasColorMatrix) {
+                    if (mDebugDisableHWC || mDebugRegion) {
                         layer->forceClientComposition(hwcId);
                     }
                 }
@@ -1233,6 +1339,9 @@
         }
     }
 
+
+    mat4 colorMatrix = mColorMatrix * mDaltonizer();
+
     // Set the per-frame data
     for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
         auto& displayDevice = mDisplays[displayId];
@@ -1240,11 +1349,18 @@
         if (hwcId < 0) {
             continue;
         }
+        if (colorMatrix != mPreviousColorMatrix) {
+            status_t result = mHwc->setColorTransform(hwcId, colorMatrix);
+            ALOGE_IF(result != NO_ERROR, "Failed to set color transform on "
+                    "display %zd: %d", displayId, result);
+        }
         for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
             layer->setPerFrameData(displayDevice);
         }
     }
 
+    mPreviousColorMatrix = colorMatrix;
+
     for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
         auto& displayDevice = mDisplays[displayId];
         if (!displayDevice->isDisplayOn()) {
@@ -1926,18 +2042,7 @@
         }
     }
 
-    if (CC_LIKELY(!mDaltonize && !mHasColorMatrix)) {
-        if (!doComposeSurfaces(hw, dirtyRegion)) return;
-    } else {
-        RenderEngine& engine(getRenderEngine());
-        mat4 colorMatrix = mColorMatrix;
-        if (mDaltonize) {
-            colorMatrix = colorMatrix * mDaltonizer();
-        }
-        mat4 oldMatrix = engine.setupColorTransform(colorMatrix);
-        doComposeSurfaces(hw, dirtyRegion);
-        engine.setupColorTransform(oldMatrix);
-    }
+    if (!doComposeSurfaces(hw, dirtyRegion)) return;
 
     // update the swap region and clear the dirty region
     hw->swapRegion.orSelf(dirtyRegion);
@@ -1952,6 +2057,15 @@
     ALOGV("doComposeSurfaces");
 
     const auto hwcId = displayDevice->getHwcDisplayId();
+
+    mat4 oldColorMatrix;
+    const bool applyColorMatrix = !mHwc->hasDeviceComposition(hwcId) &&
+            !mHwc->hasCapability(HWC2::Capability::SkipClientColorTransform);
+    if (applyColorMatrix) {
+        mat4 colorMatrix = mColorMatrix * mDaltonizer();
+        oldColorMatrix = getRenderEngine().setupColorTransform(colorMatrix);
+    }
+
     bool hasClientComposition = mHwc->hasClientComposition(hwcId);
     if (hasClientComposition) {
         ALOGV("hasClientComposition");
@@ -2069,6 +2183,10 @@
         }
     }
 
+    if (applyColorMatrix) {
+        getRenderEngine().setupColorTransform(oldColorMatrix);
+    }
+
     // disable scissor at the end of the frame
     mRenderEngine->disableScissor();
     return true;
@@ -2944,8 +3062,7 @@
     colorizer.bold(result);
     result.append("h/w composer state:\n");
     colorizer.reset(result);
-    bool hwcDisabled = mDebugDisableHWC || mDebugRegion || mDaltonize ||
-            mHasColorMatrix;
+    bool hwcDisabled = mDebugDisableHWC || mDebugRegion;
     result.appendFormat("  h/w composer %s\n",
             hwcDisabled ? "disabled" : "enabled");
     hwc.dump(result);
@@ -3100,16 +3217,24 @@
                 // daltonize
                 n = data.readInt32();
                 switch (n % 10) {
-                    case 1: mDaltonizer.setType(Daltonizer::protanomaly);   break;
-                    case 2: mDaltonizer.setType(Daltonizer::deuteranomaly); break;
-                    case 3: mDaltonizer.setType(Daltonizer::tritanomaly);   break;
+                    case 1:
+                        mDaltonizer.setType(ColorBlindnessType::Protanomaly);
+                        break;
+                    case 2:
+                        mDaltonizer.setType(ColorBlindnessType::Deuteranomaly);
+                        break;
+                    case 3:
+                        mDaltonizer.setType(ColorBlindnessType::Tritanomaly);
+                        break;
+                    default:
+                        mDaltonizer.setType(ColorBlindnessType::None);
+                        break;
                 }
                 if (n >= 10) {
-                    mDaltonizer.setMode(Daltonizer::correction);
+                    mDaltonizer.setMode(ColorBlindnessMode::Correction);
                 } else {
-                    mDaltonizer.setMode(Daltonizer::simulation);
+                    mDaltonizer.setMode(ColorBlindnessMode::Simulation);
                 }
-                mDaltonize = n > 0;
                 invalidateHwcGeometry();
                 repaintEverything();
                 return NO_ERROR;
@@ -3117,15 +3242,14 @@
             case 1015: {
                 // apply a color matrix
                 n = data.readInt32();
-                mHasColorMatrix = n ? 1 : 0;
                 if (n) {
                     // color matrix is sent as mat3 matrix followed by vec3
                     // offset, then packed into a mat4 where the last row is
                     // the offset and extra values are 0
                     for (size_t i = 0 ; i < 4; i++) {
-                      for (size_t j = 0; j < 4; j++) {
-                          mColorMatrix[i][j] = data.readFloat();
-                      }
+                        for (size_t j = 0; j < 4; j++) {
+                            mColorMatrix[i][j] = data.readFloat();
+                        }
                     }
                 } else {
                     mColorMatrix = mat4();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 0df39a4..f50f9e7 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -46,6 +46,8 @@
 
 #include <hardware/hwcomposer_defs.h>
 
+#include <system/graphics.h>
+
 #include <private/gui/LayerState.h>
 
 #include "Barrier.h"
@@ -222,6 +224,10 @@
     virtual status_t getDisplayConfigs(const sp<IBinder>& display,
             Vector<DisplayInfo>* configs);
     virtual int getActiveConfig(const sp<IBinder>& display);
+    virtual status_t getDisplayColorModes(const sp<IBinder>& display,
+            Vector<android_color_mode_t>* configs);
+    virtual android_color_mode_t getActiveColorMode(const sp<IBinder>& display);
+    virtual status_t setActiveColorMode(const sp<IBinder>& display, android_color_mode_t colorMode);
     virtual void setPowerMode(const sp<IBinder>& display, int mode);
     virtual status_t setActiveConfig(const sp<IBinder>& display, int id);
     virtual status_t clearAnimationFrameStats();
@@ -260,6 +266,9 @@
     // called on the main thread in response to setPowerMode()
     void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode);
 
+    // Called on the main thread in response to setActiveColorMode()
+    void setActiveColorModeInternal(const sp<DisplayDevice>& hw, android_color_mode_t colorMode);
+
     // Returns whether the transaction actually modified any state
     bool handleMessageTransaction();
 
@@ -368,6 +377,16 @@
         return mDisplays.valueFor(dpy);
     }
 
+    int32_t getDisplayType(const sp<IBinder>& display) {
+        if (!display.get()) return NAME_NOT_FOUND;
+        for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) {
+            if (display == mBuiltinDisplays[i]) {
+                return i;
+            }
+        }
+        return NAME_NOT_FOUND;
+    }
+
     // mark a region of a layer stack dirty. this updates the dirty
     // region of all screens presenting this layer stack.
     void invalidateLayerStack(uint32_t layerStack, const Region& dirty);
@@ -507,6 +526,9 @@
     bool mBootFinished;
     bool mForceFullDamage;
     FenceTracker mFenceTracker;
+#ifdef USE_HWC2
+    bool mPropagateBackpressure = true;
+#endif
 
     // these are thread safe
     mutable MessageQueue mEventQueue;
@@ -527,8 +549,11 @@
      */
 
     Daltonizer mDaltonizer;
+#ifndef USE_HWC2
     bool mDaltonize;
+#endif
 
+    mat4 mPreviousColorMatrix;
     mat4 mColorMatrix;
     bool mHasColorMatrix;
 
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 69fb8c5..6fe2358 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -59,6 +59,8 @@
 #include <private/android_filesystem_config.h>
 #include <private/gui/SyncFeatures.h>
 
+#include <set>
+
 #include "Client.h"
 #include "clz.h"
 #include "Colorizer.h"
@@ -574,20 +576,8 @@
         return BAD_VALUE;
     }
 
-    if (!display.get())
-        return NAME_NOT_FOUND;
-
-    int32_t type = NAME_NOT_FOUND;
-    for (int i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
-        if (display == mBuiltinDisplays[i]) {
-            type = i;
-            break;
-        }
-    }
-
-    if (type < 0) {
-        return type;
-    }
+    int32_t type = getDisplayType(display);
+    if (type < 0) return type;
 
     // TODO: Not sure if display density should handled by SF any longer
     class Density {
@@ -649,7 +639,6 @@
         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
@@ -750,6 +739,55 @@
     return NO_ERROR;
 }
 
+status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& display,
+        Vector<android_color_mode_t>* outColorModes) {
+    if (outColorModes == nullptr || display.get() == nullptr) {
+        return BAD_VALUE;
+    }
+
+    int32_t type = getDisplayType(display);
+    if (type < 0) return type;
+
+    std::set<android_color_mode_t> colorModes;
+    for (const HWComposer::DisplayConfig& hwConfig : getHwComposer().getConfigs(type)) {
+        colorModes.insert(hwConfig.colorMode);
+    }
+
+    outColorModes->clear();
+    std::copy(colorModes.cbegin(), colorModes.cend(), std::back_inserter(*outColorModes));
+
+    return NO_ERROR;
+}
+
+android_color_mode_t SurfaceFlinger::getActiveColorMode(const sp<IBinder>& display) {
+    if (display.get() == nullptr) return static_cast<android_color_mode_t>(BAD_VALUE);
+
+    int32_t type = getDisplayType(display);
+    if (type < 0) return static_cast<android_color_mode_t>(type);
+
+    return getHwComposer().getColorMode(type);
+}
+
+status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& display,
+        android_color_mode_t colorMode) {
+    if (display.get() == nullptr || colorMode < 0) {
+        return BAD_VALUE;
+    }
+
+    int32_t type = getDisplayType(display);
+    if (type < 0) return type;
+    const Vector<HWComposer::DisplayConfig>& hwConfigs = getHwComposer().getConfigs(type);
+    HWComposer::DisplayConfig desiredConfig = hwConfigs[getHwComposer().getCurrentConfig(type)];
+    desiredConfig.colorMode = colorMode;
+    for (size_t c = 0; c < hwConfigs.size(); ++c) {
+        const HWComposer::DisplayConfig config = hwConfigs[c];
+        if (config == desiredConfig) {
+            return setActiveConfig(display, c);
+        }
+    }
+    return BAD_VALUE;
+}
+
 status_t SurfaceFlinger::clearAnimationFrameStats() {
     Mutex::Autolock _l(mStateLock);
     mAnimFrameTracker.clearStats();
@@ -3080,14 +3118,20 @@
                 // daltonize
                 n = data.readInt32();
                 switch (n % 10) {
-                    case 1: mDaltonizer.setType(Daltonizer::protanomaly);   break;
-                    case 2: mDaltonizer.setType(Daltonizer::deuteranomaly); break;
-                    case 3: mDaltonizer.setType(Daltonizer::tritanomaly);   break;
+                    case 1:
+                        mDaltonizer.setType(ColorBlindnessType::Protanomaly);
+                        break;
+                    case 2:
+                        mDaltonizer.setType(ColorBlindnessType::Deuteranomaly);
+                        break;
+                    case 3:
+                        mDaltonizer.setType(ColorBlindnessType::Tritanomaly);
+                        break;
                 }
                 if (n >= 10) {
-                    mDaltonizer.setMode(Daltonizer::correction);
+                    mDaltonizer.setMode(ColorBlindnessMode::Correction);
                 } else {
-                    mDaltonizer.setMode(Daltonizer::simulation);
+                    mDaltonizer.setMode(ColorBlindnessMode::Simulation);
                 }
                 mDaltonize = n > 0;
                 invalidateHwcGeometry();
diff --git a/vulkan/libvulkan/Android.mk b/vulkan/libvulkan/Android.mk
index d2e28ff..4d2cffc 100644
--- a/vulkan/libvulkan/Android.mk
+++ b/vulkan/libvulkan/Android.mk
@@ -25,7 +25,9 @@
 	-Weverything -Werror \
 	-Wno-padded \
 	-Wno-switch-enum \
-	-Wno-undef
+	-Wno-undef \
+	-Wno-cast-calling-convention
+
 #LOCAL_CFLAGS += -DLOG_NDEBUG=0
 LOCAL_CPPFLAGS := -std=c++14 \
 	-Wno-c99-extensions \