Merge "atrace: Set saved_cmdline_size to 8192"
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index eff7c92..94c6821 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -183,6 +183,7 @@
     { "binder_driver", "Binder Kernel driver", 0, {
         { REQ,      "events/binder/binder_transaction/enable" },
         { REQ,      "events/binder/binder_transaction_received/enable" },
+        { OPT,      "events/binder/binder_set_priority/enable" },
     } },
     { "binder_lock", "Binder global lock trace", 0, {
         { OPT,      "events/binder/binder_lock/enable" },
diff --git a/cmds/dumpstate/DumpstateInternal.h b/cmds/dumpstate/DumpstateInternal.h
index 2f7704d..10db5d6 100644
--- a/cmds/dumpstate/DumpstateInternal.h
+++ b/cmds/dumpstate/DumpstateInternal.h
@@ -32,6 +32,12 @@
     ALOGI(__VA_ARGS__);
 #endif
 
+#ifndef MYLOGW
+#define MYLOGW(...)               \
+    fprintf(stderr, __VA_ARGS__); \
+    ALOGW(__VA_ARGS__);
+#endif
+
 #ifndef MYLOGE
 #define MYLOGE(...)               \
     fprintf(stderr, __VA_ARGS__); \
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index f84d86d..745361c 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -21,13 +21,9 @@
 #include <fcntl.h>
 #include <libgen.h>
 #include <limits.h>
-#include <memory>
-#include <regex>
-#include <set>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <string>
 #include <string.h>
 #include <sys/prctl.h>
 #include <sys/resource.h>
@@ -35,6 +31,11 @@
 #include <sys/time.h>
 #include <sys/wait.h>
 #include <unistd.h>
+#include <memory>
+#include <regex>
+#include <set>
+#include <string>
+#include <vector>
 
 #include <android-base/file.h>
 #include <android-base/properties.h>
@@ -78,19 +79,29 @@
 #define LOGPERSIST_DATA_DIR "/data/misc/logd"
 #define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
 #define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
-#define TOMBSTONE_DIR "/data/tombstones"
-#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
-/* Can accomodate a tombstone number up to 9999. */
-#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
-#define NUM_TOMBSTONES  10
 #define WLUTIL "/vendor/xbin/wlutil"
 
-typedef struct {
-  char name[TOMBSTONE_MAX_LEN];
-  int fd;
-} tombstone_data_t;
+// TODO(narayan): Since this information has to be kept in sync
+// with tombstoned, we should just put it in a common header.
+//
+// File: system/core/debuggerd/tombstoned/tombstoned.cpp
+static const std::string TOMBSTONE_DIR = "/data/tombstones/";
+static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
+static const std::string ANR_DIR = "/data/anr/";
+static const std::string ANR_FILE_PREFIX = "anr_";
 
-static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
+struct DumpData {
+    std::string name;
+    int fd;
+    time_t mtime;
+};
+
+static bool operator<(const DumpData& d1, const DumpData& d2) {
+    return d1.mtime > d2.mtime;
+}
+
+static std::unique_ptr<std::vector<DumpData>> tombstone_data;
+static std::unique_ptr<std::vector<DumpData>> anr_data;
 
 // TODO: temporary variables and functions used during C++ refactoring
 static Dumpstate& ds = Dumpstate::GetInstance();
@@ -122,23 +133,79 @@
 
 static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
 
-/* gets the tombstone data, according to the bugreport type: if zipped, gets all tombstones;
- * otherwise, gets just those modified in the last half an hour. */
-static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
-    time_t thirty_minutes_ago = ds.now_ - 60 * 30;
-    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
-        snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
-        int fd = TEMP_FAILURE_RETRY(open(data[i].name,
-                                         O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
-        struct stat st;
-        if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) && st.st_size > 0 &&
-            (ds.IsZipping() || st.st_mtime >= thirty_minutes_ago)) {
-            data[i].fd = fd;
-        } else {
-            close(fd);
-            data[i].fd = -1;
+/*
+ * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
+ * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
+ * is set, the vector only contains files that were written in the last 30 minutes.
+ */
+static std::vector<DumpData>* GetDumpFds(const std::string& dir_path,
+                                         const std::string& file_prefix,
+                                         bool limit_by_mtime) {
+    const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
+
+    std::unique_ptr<std::vector<DumpData>> dump_data(new std::vector<DumpData>());
+    std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
+
+    struct dirent* entry = nullptr;
+    while ((entry = readdir(dump_dir.get()))) {
+        if (entry->d_type != DT_REG) {
+            continue;
         }
+
+        const std::string base_name(entry->d_name);
+        if (base_name.find(file_prefix) != 0) {
+            continue;
+        }
+
+        const std::string abs_path = dir_path + base_name;
+        android::base::unique_fd fd(
+            TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
+        if (fd == -1) {
+            MYLOGW("Unable to open dump file: %s %s\n", abs_path.c_str(), strerror(errno));
+            break;
+        }
+
+        struct stat st = {};
+        if (fstat(fd, &st) == -1) {
+            MYLOGW("Unable to stat dump file: %s %s\n", abs_path.c_str(), strerror(errno));
+            continue;
+        }
+
+        if (limit_by_mtime && st.st_mtime >= thirty_minutes_ago) {
+            MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
+            continue;
+        }
+
+        DumpData data = {.name = abs_path, .fd = fd.release(), .mtime = st.st_mtime};
+
+        dump_data->push_back(data);
     }
+
+    std::sort(dump_data->begin(), dump_data->end());
+
+    return dump_data.release();
+}
+
+static bool AddDumps(const std::vector<DumpData>::const_iterator start,
+                     const std::vector<DumpData>::const_iterator end,
+                     const char* type_name, const bool add_to_zip) {
+    bool dumped = false;
+    for (auto it = start; it != end; ++it) {
+        const std::string& name = it->name;
+        const int fd = it->fd;
+        dumped = true;
+        if (ds.IsZipping() && add_to_zip) {
+            if (!ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd)) {
+                MYLOGE("Unable to add %s %s to zip file\n", name.c_str(), type_name);
+            }
+        } else {
+            dump_file_from_fd(type_name, name.c_str(), fd);
+        }
+
+        close(fd);
+    }
+
+    return dumped;
 }
 
 // for_each_pid() callback to get mount info about a process.
@@ -860,11 +927,10 @@
     RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
 }
 
-static void AddAnrTraceFiles() {
-    bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
+static void AddGlobalAnrTraceFile(const bool add_to_zip, const std::string& anr_traces_file,
+                                  const std::string& anr_traces_dir) {
     std::string dump_traces_dir;
 
-    /* show the traces we collected in main(), if that was done */
     if (dump_traces_path != nullptr) {
         if (add_to_zip) {
             dump_traces_dir = dirname(dump_traces_path);
@@ -877,8 +943,6 @@
         }
     }
 
-    std::string anr_traces_path = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
-    std::string anr_traces_dir = dirname(anr_traces_path.c_str());
 
     // Make sure directory is not added twice.
     // TODO: this is an overzealous check because it's relying on dump_traces_path - which is
@@ -888,54 +952,110 @@
     // be revisited.
     bool already_dumped = anr_traces_dir == dump_traces_dir;
 
-    MYLOGD("AddAnrTraceFiles(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
+    MYLOGD("AddGlobalAnrTraceFile(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
            dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped);
 
-    if (anr_traces_path.empty()) {
-        printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
+    int fd = TEMP_FAILURE_RETRY(
+        open(anr_traces_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
+    if (fd < 0) {
+        printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_file.c_str(), strerror(errno));
     } else {
-        int fd = TEMP_FAILURE_RETRY(
-            open(anr_traces_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
-        if (fd < 0) {
-            printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path.c_str(),
-                   strerror(errno));
-        } else {
-            if (add_to_zip) {
-                if (!already_dumped) {
-                    MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n",
-                           anr_traces_dir.c_str());
-                    ds.AddDir(anr_traces_dir, true);
-                    already_dumped = true;
-                }
-            } else {
-                MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
-                       anr_traces_path.c_str());
-                dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path.c_str(), fd);
+        if (add_to_zip) {
+            if (!already_dumped) {
+                MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n",
+                       anr_traces_dir.c_str());
+                ds.AddDir(anr_traces_dir, true);
             }
+        } else {
+            MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
+                   anr_traces_file.c_str());
+            dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_file.c_str(), fd);
+        }
+    }
+}
+
+static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
+    MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
+           anr_traces_dir.c_str());
+
+    // If we're here, dump_traces_path will always be a temporary file
+    // (created with mkostemp or similar) that contains dumps taken earlier
+    // on in the process.
+    if (dump_traces_path != nullptr) {
+        if (add_to_zip) {
+            ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
+        } else {
+            MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
+                   dump_traces_path);
+            ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
+        }
+
+        const int ret = unlink(dump_traces_path);
+        if (ret == -1) {
+            MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
+                   strerror(errno));
         }
     }
 
-    if (add_to_zip && already_dumped) {
-        MYLOGD("Already dumped directory %s to the zip file\n", anr_traces_dir.c_str());
+    // Add a specific message for the first ANR Dump.
+    if (anr_data->size() > 0) {
+        AddDumps(anr_data->begin(), anr_data->begin() + 1,
+                 "VM TRACES AT LAST ANR", add_to_zip);
+
+        if (anr_data->size() > 1) {
+            AddDumps(anr_data->begin() + 1, anr_data->end(),
+                     "HISTORICAL ANR", add_to_zip);
+        }
+    } else {
+        printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
+    }
+}
+
+static void AddAnrTraceFiles() {
+    const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
+
+    std::string anr_traces_file;
+    std::string anr_traces_dir;
+    bool is_global_trace_file = true;
+
+    // First check whether the stack-trace-dir property is set. When it's set,
+    // each ANR trace will be written to a separate file and not to a global
+    // stack trace file.
+    anr_traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
+    if (anr_traces_dir.empty()) {
+        anr_traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
+        if (!anr_traces_file.empty()) {
+            anr_traces_dir = dirname(anr_traces_file.c_str());
+        }
+    } else {
+        is_global_trace_file = false;
+    }
+
+    // We have neither configured a global trace file nor a trace directory,
+    // there will be nothing to dump.
+    if (anr_traces_file.empty() && anr_traces_dir.empty()) {
+        printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
         return;
     }
 
+    if (is_global_trace_file) {
+        AddGlobalAnrTraceFile(add_to_zip, anr_traces_file, anr_traces_dir);
+    } else {
+        AddAnrTraceDir(add_to_zip, anr_traces_dir);
+    }
+
     /* slow traces for slow operations */
     struct stat st;
-    if (!anr_traces_path.empty()) {
-        int tail = anr_traces_path.size() - 1;
-        while (tail > 0 && anr_traces_path.at(tail) != '/') {
-            tail--;
-        }
+    if (!anr_traces_dir.empty()) {
         int i = 0;
-        while (1) {
-            anr_traces_path = anr_traces_path.substr(0, tail + 1) +
-                              android::base::StringPrintf("slow%02d.txt", i);
-            if (stat(anr_traces_path.c_str(), &st)) {
+        while (true) {
+            const std::string slow_trace_path =
+                anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
+            if (stat(slow_trace_path.c_str(), &st)) {
                 // No traces file at this index, done with the files.
                 break;
             }
-            ds.DumpFile("VM TRACES WHEN SLOW", anr_traces_path.c_str());
+            ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
             i++;
         }
     }
@@ -1010,25 +1130,12 @@
 
     AddAnrTraceFiles();
 
-    int dumped = 0;
-    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
-        if (tombstone_data[i].fd != -1) {
-            const char *name = tombstone_data[i].name;
-            int fd = tombstone_data[i].fd;
-            dumped = 1;
-            if (ds.IsZipping()) {
-                if (!ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd)) {
-                    MYLOGE("Unable to add tombstone %s to zip file\n", name);
-                }
-            } else {
-                dump_file_from_fd("TOMBSTONE", name, fd);
-            }
-            close(fd);
-            tombstone_data[i].fd = -1;
-        }
-    }
-    if (!dumped) {
-        printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
+    // NOTE: tombstones are always added as separate entries in the zip archive
+    // and are not interspersed with the main report.
+    const bool tombstones_dumped = AddDumps(tombstone_data->begin(), tombstone_data->end(),
+                                            "TOMBSTONE", true /* add_to_zip */);
+    if (!tombstones_dumped) {
+        printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
     }
 
     DumpFile("NETWORK DEV INFO", "/proc/net/dev");
@@ -1707,7 +1814,9 @@
         dump_traces_path = dump_traces();
 
         /* Run some operations that require root. */
-        get_tombstone_fds(tombstone_data);
+        tombstone_data.reset(GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()));
+        anr_data.reset(GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping()));
+
         ds.AddDir(RECOVERY_DIR, true);
         ds.AddDir(RECOVERY_DATA_DIR, true);
         ds.AddDir(LOGPERSIST_DATA_DIR, false);
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index f649a5e..5698d1b 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -38,6 +38,7 @@
 #include <time.h>
 #include <unistd.h>
 
+#include <memory>
 #include <set>
 #include <string>
 #include <vector>
@@ -46,6 +47,7 @@
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
+#include <android-base/unique_fd.h>
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <cutils/properties.h>
 #include <cutils/sockets.h>
@@ -852,15 +854,143 @@
     return pids; // whether it was okay or not
 }
 
+const char* DumpTraces(const std::string& traces_path);
+const char* DumpTracesTombstoned(const std::string& traces_dir);
+
 /* dump Dalvik and native stack traces, return the trace file location (NULL if none) */
 const char *dump_traces() {
     DurationReporter duration_reporter("DUMP TRACES");
 
-    const char* result = nullptr;
+    const std::string traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
+    if (!traces_dir.empty()) {
+        return DumpTracesTombstoned(traces_dir);
+    }
 
-    std::string traces_path = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
-    if (traces_path.empty()) return nullptr;
+    const std::string traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
+    if (!traces_file.empty()) {
+        return DumpTraces(traces_file);
+    }
 
+    return nullptr;
+}
+
+static bool IsZygote(int pid) {
+    static const std::string kZygotePrefix = "zygote";
+
+    std::string cmdline;
+    if (!android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid),
+                                         &cmdline)) {
+        return true;
+    }
+
+    return (cmdline.find(kZygotePrefix) == 0);
+}
+
+const char* DumpTracesTombstoned(const std::string& traces_dir) {
+    const std::string temp_file_pattern = traces_dir + "/dumptrace_XXXXXX";
+
+    const size_t buf_size = temp_file_pattern.length() + 1;
+    std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
+    memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
+
+    // Create a new, empty file to receive all trace dumps.
+    //
+    // TODO: This can be simplified once we remove support for the old style
+    // dumps. We can have a file descriptor passed in to dump_traces instead
+    // of creating a file, closing it and then reopening it again.
+    android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
+    if (fd < 0) {
+        MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
+        return nullptr;
+    }
+
+    // Nobody should have access to this temporary file except dumpstate, but we
+    // temporarily grant 'read' to 'others' here because this file is created
+    // when tombstoned is still running as root, but dumped after dropping. This
+    // can go away once support for old style dumping has.
+    const int chmod_ret = fchmod(fd, 0666);
+    if (chmod_ret < 0) {
+        MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
+        return nullptr;
+    }
+
+    std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
+    if (proc.get() == nullptr) {
+        MYLOGE("opendir /proc failed: %s\n", strerror(errno));
+        return nullptr;
+    }
+
+    // Number of times process dumping has timed out. If we encounter too many
+    // failures, we'll give up.
+    int timeout_failures = 0;
+    bool dalvik_found = false;
+
+    const std::set<int> hal_pids = get_interesting_hal_pids();
+
+    struct dirent* d;
+    while ((d = readdir(proc.get()))) {
+        int pid = atoi(d->d_name);
+        if (pid <= 0) {
+            continue;
+        }
+
+        const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
+        std::string exe;
+        if (!android::base::Readlink(link_name, &exe)) {
+            continue;
+        }
+
+        bool is_java_process;
+        if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
+            // Don't bother dumping backtraces for the zygote.
+            if (IsZygote(pid)) {
+                continue;
+            }
+
+            dalvik_found = true;
+            is_java_process = true;
+        } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
+            is_java_process = false;
+        } else {
+            // Probably a native process we don't care about, continue.
+            continue;
+        }
+
+        // If 3 backtrace dumps fail in a row, consider debuggerd dead.
+        if (timeout_failures == 3) {
+            dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
+            break;
+        }
+
+        const uint64_t start = Nanotime();
+        const int ret = dump_backtrace_to_file_timeout(
+            pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
+            is_java_process ? 5 : 20, fd);
+
+        if (ret == -1) {
+            dprintf(fd, "dumping failed, likely due to a timeout\n");
+            timeout_failures++;
+            continue;
+        }
+
+        // We've successfully dumped stack traces, reset the failure count
+        // and write a summary of the elapsed time to the file and continue with the
+        // next process.
+        timeout_failures = 0;
+
+        dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
+                pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
+    }
+
+    if (!dalvik_found) {
+        MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
+    }
+
+    return file_name_buf.release();
+}
+
+const char* DumpTraces(const std::string& traces_path) {
+    const char* result = NULL;
     /* move the old traces.txt (if any) out of the way temporarily */
     std::string anrtraces_path = traces_path + ".anr";
     if (rename(traces_path.c_str(), anrtraces_path.c_str()) && errno != ENOENT) {
@@ -973,7 +1103,8 @@
                 /* If 3 backtrace dumps fail in a row, consider debuggerd dead. */
                 if (timeout_failures == 3) {
                     dprintf(fd, "too many stack dump failures, skipping...\n");
-                } else if (dump_backtrace_to_file_timeout(pid, fd, 20) == -1) {
+                } else if (dump_backtrace_to_file_timeout(
+                        pid, kDebuggerdNativeBacktrace, 20, fd) == -1) {
                     dprintf(fd, "dumping failed, likely due to a timeout\n");
                     timeout_failures++;
                 } else {
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index a1fea8d..22ad718 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -915,15 +915,8 @@
     return res;
 }
 
-/* Try to ensure free_size bytes of storage are available.
- * Returns 0 on success.
- * This is rather simple-minded because doing a full LRU would
- * be potentially memory-intensive, and without atime it would
- * also require that apps constantly modify file metadata even
- * when just reading from the cache, which is pretty awful.
- */
 binder::Status InstalldNativeService::freeCache(const std::unique_ptr<std::string>& uuid,
-        int64_t freeStorageSize, int32_t flags) {
+        int64_t targetFreeBytes, int64_t cacheReservedBytes, int32_t flags) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
     std::lock_guard<std::recursive_mutex> lock(mLock);
@@ -938,11 +931,12 @@
         return error("Failed to determine free space for " + data_path);
     }
 
-    int64_t needed = freeStorageSize - free;
+    int64_t cleared = 0;
+    int64_t needed = targetFreeBytes - free;
     LOG(DEBUG) << "Device " << data_path << " has " << free << " free; requested "
-            << freeStorageSize << "; needed " << needed;
+            << targetFreeBytes << "; needed " << needed;
 
-    if (free >= freeStorageSize) {
+    if (free >= targetFreeBytes) {
         return ok();
     }
 
@@ -999,6 +993,7 @@
 
         // 2. Populate tracker stats and insert into priority queue
         ATRACE_BEGIN("populate");
+        int64_t cacheTotal = 0;
         auto cmp = [](std::shared_ptr<CacheTracker> left, std::shared_ptr<CacheTracker> right) {
             return (left->getCacheRatio() < right->getCacheRatio());
         };
@@ -1007,6 +1002,7 @@
         for (const auto& it : trackers) {
             it.second->loadStats();
             queue.push(it.second);
+            cacheTotal += it.second->cacheUsed;
         }
         ATRACE_END();
 
@@ -1023,6 +1019,12 @@
                 break;
             }
 
+            // Only keep clearing when we haven't pushed into reserved area
+            if (cacheReservedBytes > 0 && cleared >= (cacheTotal - cacheReservedBytes)) {
+                LOG(DEBUG) << "Refusing to clear cached data in reserved space";
+                break;
+            }
+
             // Find the best tracker to work with; this might involve swapping
             // if the active tracker is no longer the most over quota
             bool nextBetter = active && !queue.empty()
@@ -1052,13 +1054,14 @@
                 }
                 active->cacheUsed -= item->size;
                 needed -= item->size;
+                cleared += item->size;
             }
 
             // Verify that we're actually done before bailing, since sneaky
             // apps might be using hardlinks
             if (needed <= 0) {
                 free = data_disk_free(data_path);
-                needed = freeStorageSize - free;
+                needed = targetFreeBytes - free;
                 if (needed <= 0) {
                     break;
                 } else {
@@ -1073,11 +1076,11 @@
     }
 
     free = data_disk_free(data_path);
-    if (free >= freeStorageSize) {
+    if (free >= targetFreeBytes) {
         return ok();
     } else {
         return error(StringPrintf("Failed to free up %" PRId64 " on %s; final free space %" PRId64,
-                freeStorageSize, data_path.c_str(), free));
+                targetFreeBytes, data_path.c_str(), free));
     }
 }
 
@@ -2256,13 +2259,13 @@
 }
 
 binder::Status InstalldNativeService::deleteOdex(const std::string& apkPath,
-        const std::string& instructionSet, const std::string& outputPath) {
+        const std::string& instructionSet, const std::unique_ptr<std::string>& outputPath) {
     ENFORCE_UID(AID_SYSTEM);
     std::lock_guard<std::recursive_mutex> lock(mLock);
 
     const char* apk_path = apkPath.c_str();
     const char* instruction_set = instructionSet.c_str();
-    const char* oat_dir = outputPath.c_str();
+    const char* oat_dir = outputPath ? outputPath->c_str() : nullptr;
 
     bool res = delete_odex(apk_path, instruction_set, oat_dir);
     return res ? ok() : error();
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index a94223c..5756b82 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -101,8 +101,8 @@
     binder::Status removeIdmap(const std::string& overlayApkPath);
     binder::Status rmPackageDir(const std::string& packageDir);
     binder::Status markBootComplete(const std::string& instructionSet);
-    binder::Status freeCache(const std::unique_ptr<std::string>& uuid, int64_t freeStorageSize,
-            int32_t flags);
+    binder::Status freeCache(const std::unique_ptr<std::string>& uuid, int64_t targetFreeBytes,
+            int64_t cacheReservedBytes, int32_t flags);
     binder::Status linkNativeLibraryDirectory(const std::unique_ptr<std::string>& uuid,
             const std::string& packageName, const std::string& nativeLibPath32, int32_t userId);
     binder::Status createOatDir(const std::string& oatDir, const std::string& instructionSet);
@@ -111,7 +111,7 @@
     binder::Status moveAb(const std::string& apkPath, const std::string& instructionSet,
             const std::string& outputPath);
     binder::Status deleteOdex(const std::string& apkPath, const std::string& instructionSet,
-            const std::string& outputPath);
+            const std::unique_ptr<std::string>& outputPath);
     binder::Status reconcileSecondaryDexFile(const std::string& dexPath,
         const std::string& packageName, int32_t uid, const std::vector<std::string>& isa,
         const std::unique_ptr<std::string>& volumeUuid, int32_t storage_flag, bool* _aidl_return);
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index efcae4f..c8e76b0 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -66,7 +66,8 @@
     void removeIdmap(@utf8InCpp String overlayApkPath);
     void rmPackageDir(@utf8InCpp String packageDir);
     void markBootComplete(@utf8InCpp String instructionSet);
-    void freeCache(@nullable @utf8InCpp String uuid, long freeStorageSize, int flags);
+    void freeCache(@nullable @utf8InCpp String uuid, long targetFreeBytes,
+            long cacheReservedBytes, int flags);
     void linkNativeLibraryDirectory(@nullable @utf8InCpp String uuid,
             @utf8InCpp String packageName, @utf8InCpp String nativeLibPath32, int userId);
     void createOatDir(@utf8InCpp String oatDir, @utf8InCpp String instructionSet);
@@ -75,7 +76,7 @@
     void moveAb(@utf8InCpp String apkPath, @utf8InCpp String instructionSet,
             @utf8InCpp String outputPath);
     void deleteOdex(@utf8InCpp String apkPath, @utf8InCpp String instructionSet,
-            @utf8InCpp String outputPath);
+            @nullable @utf8InCpp String outputPath);
 
     boolean reconcileSecondaryDexFile(@utf8InCpp String dexPath, @utf8InCpp String pkgName,
         int uid, in @utf8InCpp String[] isas, @nullable @utf8InCpp String volume_uuid,
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 7419eb4..af78bfb 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1242,13 +1242,7 @@
             ALOGE("installd cannot compute input vdex location for '%s'\n", path);
             return false;
         }
-        if (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE) {
-            // When we dex2oat because of boot image change, we are going to update
-            // in-place the vdex file.
-            in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDWR, 0));
-        } else {
-            in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
-        }
+        in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
     }
 
     // Infer the name of the output VDEX and create it.
@@ -1257,27 +1251,12 @@
         return false;
     }
 
-    // If we are compiling because the boot image is out of date, we do not
-    // need to recreate a vdex, and can use the same existing one.
-    if (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE &&
-            in_vdex_wrapper_fd->get() != -1 &&
-            in_vdex_path_str == out_vdex_path_str) {
-        // We unlink the file in case the invocation of dex2oat fails, to ensure we don't
-        // have bogus stale vdex files.
-        out_vdex_wrapper_fd->reset(
-              in_vdex_wrapper_fd->get(),
-              [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
-        // Disable auto close for the in wrapper fd (it will be done when destructing the out
-        // wrapper).
-        in_vdex_wrapper_fd->DisableAutoClose();
-    } else {
-        out_vdex_wrapper_fd->reset(
-              open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
-              [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
-        if (out_vdex_wrapper_fd->get() < 0) {
-            ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
-            return false;
-        }
+    out_vdex_wrapper_fd->reset(
+          open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
+          [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
+    if (out_vdex_wrapper_fd->get() < 0) {
+        ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
+        return false;
     }
     if (!set_permissions_and_ownership(out_vdex_wrapper_fd->get(), is_public, uid,
             out_vdex_path_str.c_str(), is_secondary_dex)) {
@@ -1940,8 +1919,11 @@
     // Derive and delete the app image.
     bool return_value_art = unlink_and_check(create_image_filename(out_path).c_str());
 
+    // Derive and delete the vdex file.
+    bool return_value_vdex = unlink_and_check(create_vdex_filename(out_path).c_str());
+
     // Report success.
-    return return_value_oat && return_value_art;
+    return return_value_oat && return_value_art && return_value_vdex;
 }
 
 }  // namespace installd
diff --git a/cmds/installd/tests/installd_cache_test.cpp b/cmds/installd/tests/installd_cache_test.cpp
index 174ce77..aed068c 100644
--- a/cmds/installd/tests/installd_cache_test.cpp
+++ b/cmds/installd/tests/installd_cache_test.cpp
@@ -146,7 +146,7 @@
     EXPECT_EQ(0, exists("com.example/cache/foo/one"));
     EXPECT_EQ(0, exists("com.example/cache/foo/two"));
 
-    service->freeCache(testUuid, kTbInBytes,
+    service->freeCache(testUuid, kTbInBytes, 0,
             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
 
     EXPECT_EQ(0, exists("com.example/normal"));
@@ -163,13 +163,13 @@
     touch("com.example/cache/foo/one", kMbInBytes, 60);
     touch("com.example/cache/foo/two", kMbInBytes, 120);
 
-    service->freeCache(testUuid, free() + kKbInBytes,
+    service->freeCache(testUuid, free() + kKbInBytes, 0,
             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
 
     EXPECT_EQ(-1, exists("com.example/cache/foo/one"));
     EXPECT_EQ(0, exists("com.example/cache/foo/two"));
 
-    service->freeCache(testUuid, free() + kKbInBytes,
+    service->freeCache(testUuid, free() + kKbInBytes, 0,
             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
 
     EXPECT_EQ(-1, exists("com.example/cache/foo/one"));
@@ -197,7 +197,7 @@
     EXPECT_EQ(2 * kMbInBytes, size("com.example/cache/bar/bar1"));
     EXPECT_EQ(2 * kMbInBytes, size("com.example/cache/bar/bar2"));
 
-    service->freeCache(testUuid, kTbInBytes,
+    service->freeCache(testUuid, kTbInBytes, 0,
             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
 
     EXPECT_EQ(-1, exists("com.example/cache/foo/foo1"));
@@ -219,7 +219,7 @@
 
     setxattr("com.example/cache/foo", "user.cache_group");
 
-    service->freeCache(testUuid, free() + kKbInBytes,
+    service->freeCache(testUuid, free() + kKbInBytes, 0,
             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
 
     EXPECT_EQ(-1, exists("com.example/cache/foo/foo1"));
@@ -264,7 +264,7 @@
     setxattr("com.example/cache/tomb", "user.cache_tombstone");
     setxattr("com.example/cache/tomb/group", "user.cache_group");
 
-    service->freeCache(testUuid, free() + kKbInBytes,
+    service->freeCache(testUuid, free() + kKbInBytes, 0,
             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
 
     EXPECT_EQ(kMbInBytes, size("com.example/cache/group/file1"));
@@ -285,7 +285,7 @@
     EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file1"));
     EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file2"));
 
-    service->freeCache(testUuid, free() + kKbInBytes,
+    service->freeCache(testUuid, free() + kKbInBytes, 0,
             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
 
     EXPECT_EQ(-1, size("com.example/cache/group/file1"));
@@ -306,7 +306,7 @@
     EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file1"));
     EXPECT_EQ(0, size("com.example/cache/tomb/group/dir/file2"));
 
-    service->freeCache(testUuid, kTbInBytes,
+    service->freeCache(testUuid, kTbInBytes, 0,
             FLAG_FREE_CACHE_V2 | FLAG_FREE_CACHE_V2_DEFY_QUOTA);
 
     EXPECT_EQ(-1, size("com.example/cache/group/file1"));
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index 2eb58ae..87b9104 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -467,7 +467,8 @@
     using namespace ::android::hardware;
     using namespace ::android::hidl::manager::V1_0;
     using namespace ::android::hidl::base::V1_0;
-    auto ret = timeoutIPC(manager, &IServiceManager::debugDump, [&] (const auto &infos) {
+    using std::literals::chrono_literals::operator""s;
+    auto ret = timeoutIPC(2s, manager, &IServiceManager::debugDump, [&] (const auto &infos) {
         std::map<std::string, TableEntry> entries;
         for (const auto &info : infos) {
             std::string interfaceName = std::string{info.interfaceName.c_str()} + "/" +
@@ -477,7 +478,7 @@
                 .transport = "passthrough",
                 .serverPid = NO_PID,
                 .serverObjectAddress = NO_PTR,
-                .clientPids = {},
+                .clientPids = info.clientPids,
                 .arch = ARCH_UNKNOWN
             }).first->second.arch |= fromBaseArchitecture(info.arch);
         }
diff --git a/cmds/lshal/Timeout.h b/cmds/lshal/Timeout.h
index ca477bf..c940404 100644
--- a/cmds/lshal/Timeout.h
+++ b/cmds/lshal/Timeout.h
@@ -77,14 +77,15 @@
     return success;
 }
 
-template<class Function, class I, class... Args>
+template<class R, class P, class Function, class I, class... Args>
 typename std::result_of<Function(I *, Args...)>::type
-timeoutIPC(const sp<I> &interfaceObject, Function &&func, Args &&... args) {
+timeoutIPC(std::chrono::duration<R, P> wait, const sp<I> &interfaceObject, Function &&func,
+           Args &&... args) {
     using ::android::hardware::Status;
     typename std::result_of<Function(I *, Args...)>::type ret{Status::ok()};
     auto boundFunc = std::bind(std::forward<Function>(func),
             interfaceObject.get(), std::forward<Args>(args)...);
-    bool success = timeout(IPC_CALL_WAIT, [&ret, &boundFunc] {
+    bool success = timeout(wait, [&ret, &boundFunc] {
         ret = std::move(boundFunc());
     });
     if (!success) {
@@ -93,5 +94,12 @@
     return ret;
 }
 
+template<class Function, class I, class... Args>
+typename std::result_of<Function(I *, Args...)>::type
+timeoutIPC(const sp<I> &interfaceObject, Function &&func, Args &&... args) {
+    return timeoutIPC(IPC_CALL_WAIT, interfaceObject, func, args...);
+}
+
+
 }  // namespace lshal
 }  // namespace android
diff --git a/include/audiomanager/AudioManager.h b/include/audiomanager/AudioManager.h
index 834dcbd..009dc52 100644
--- a/include/audiomanager/AudioManager.h
+++ b/include/audiomanager/AudioManager.h
@@ -26,6 +26,9 @@
 typedef enum {
     PLAYER_TYPE_SLES_AUDIOPLAYER_BUFFERQUEUE = 11,
     PLAYER_TYPE_SLES_AUDIOPLAYER_URI_FD = 12,
+    PLAYER_TYPE_AAUDIO = 13,
+    PLAYER_TYPE_HW_SOURCE = 14,
+    PLAYER_TYPE_EXTERNAL_PROXY = 15,
 } player_type_t;
 
 typedef enum {
diff --git a/include/gui/BufferQueueConsumer.h b/include/gui/BufferQueueConsumer.h
index f194bdf..d108120 100644
--- a/include/gui/BufferQueueConsumer.h
+++ b/include/gui/BufferQueueConsumer.h
@@ -121,13 +121,12 @@
     // GraphicBuffers of a defaultDataSpace if no data space is specified
     // in queueBuffer.
     // The initial default is HAL_DATASPACE_UNKNOWN
-    virtual status_t setDefaultBufferDataSpace(
-            android_dataspace defaultDataSpace);
+    virtual status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace);
 
     // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer.
     // These are merged with the bits passed to dequeueBuffer.  The values are
     // enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0.
-    virtual status_t setConsumerUsageBits(uint32_t usage);
+    virtual status_t setConsumerUsageBits(uint64_t usage) override;
 
     // setConsumerIsProtected will turn on an internal bit that indicates whether
     // the consumer can handle protected gralloc buffers (i.e. with
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index dd8b992..537c957 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -170,7 +170,7 @@
 
     // mConsumerUsageBits contains flags that the consumer wants for
     // GraphicBuffers.
-    uint32_t mConsumerUsageBits;
+    uint64_t mConsumerUsageBits;
 
     // mConsumerIsProtected indicates the consumer is ready to handle protected
     // buffer.
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index 87bc800..0f8917a 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -80,9 +80,9 @@
     //
     // In both cases, the producer will need to call requestBuffer to get a
     // GraphicBuffer handle for the returned slot.
-    status_t dequeueBuffer(int *outSlot, sp<Fence>* outFence,
+    virtual status_t dequeueBuffer(int *outSlot, sp<Fence>* outFence,
             uint32_t width, uint32_t height, PixelFormat format,
-            uint32_t usage, FrameEventHistoryDelta* outTimestamps) override;
+            uint64_t usage, FrameEventHistoryDelta* outTimestamps) override;
 
     // See IGraphicBufferProducer::detachBuffer
     virtual status_t detachBuffer(int slot);
@@ -152,7 +152,7 @@
 
     // See IGraphicBufferProducer::allocateBuffers
     virtual void allocateBuffers(uint32_t width, uint32_t height,
-            PixelFormat format, uint32_t usage);
+            PixelFormat format, uint64_t usage) override;
 
     // See IGraphicBufferProducer::allowAllocation
     virtual status_t allowAllocation(bool allow);
diff --git a/include/gui/IGraphicBufferConsumer.h b/include/gui/IGraphicBufferConsumer.h
index 57cce16..90de114 100644
--- a/include/gui/IGraphicBufferConsumer.h
+++ b/include/gui/IGraphicBufferConsumer.h
@@ -241,7 +241,7 @@
     // e.g. GRALLOC_USAGE_HW_RENDER; the default is 0.
     //
     // Return of a value other than NO_ERROR means an unknown error has occurred.
-    virtual status_t setConsumerUsageBits(uint32_t usage) = 0;
+    virtual status_t setConsumerUsageBits(uint64_t usage) = 0;
 
     // setConsumerIsProtected will turn on an internal bit that indicates whether
     // the consumer can handle protected gralloc buffers (i.e. with
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 9250806..6d16e74 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -195,7 +195,7 @@
     // All other negative values are an unknown error returned downstream
     // from the graphics allocator (typically errno).
     virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
-            uint32_t h, PixelFormat format, uint32_t usage,
+            uint32_t h, PixelFormat format, uint64_t usage,
             FrameEventHistoryDelta* outTimestamps) = 0;
 
     // detachBuffer attempts to remove all ownership of the buffer in the given
@@ -517,7 +517,7 @@
     // dequeueBuffer. If there are already the maximum number of buffers
     // allocated, this function has no effect.
     virtual void allocateBuffers(uint32_t width, uint32_t height,
-            PixelFormat format, uint32_t usage) = 0;
+            PixelFormat format, uint64_t usage) = 0;
 
     // Sets whether dequeueBuffer is allowed to allocate new buffers.
     //
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index c8c6e99..0f7e12a 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -160,6 +160,9 @@
 
     status_t getUniqueId(uint64_t* outId) const;
 
+    // Returns the CLOCK_MONOTONIC start time of the last dequeueBuffer call
+    nsecs_t getLastDequeueStartTime() const;
+
 protected:
     virtual ~Surface();
 
@@ -204,8 +207,8 @@
     int dispatchSetBuffersStickyTransform(va_list args);
     int dispatchSetBuffersTimestamp(va_list args);
     int dispatchSetCrop(va_list args);
-    int dispatchSetPostTransformCrop(va_list args);
     int dispatchSetUsage(va_list args);
+    int dispatchSetUsage64(va_list args);
     int dispatchLock(va_list args);
     int dispatchUnlockAndPost(va_list args);
     int dispatchSetSidebandStream(va_list args);
@@ -239,7 +242,7 @@
     virtual int setBuffersTimestamp(int64_t timestamp);
     virtual int setBuffersDataSpace(android_dataspace dataSpace);
     virtual int setCrop(Rect const* rect);
-    virtual int setUsage(uint32_t reqUsage);
+    virtual int setUsage(uint64_t reqUsage);
     virtual void setSurfaceDamage(android_native_rect_t* rects, size_t numRects);
 
 public:
@@ -318,7 +321,7 @@
 
     // mReqUsage is the set of buffer usage flags that will be requested
     // at the next deuque operation. It is initialized to 0.
-    uint32_t mReqUsage;
+    uint64_t mReqUsage;
 
     // mTimestamp is the timestamp that will be used for the next buffer queue
     // operation. It defaults to NATIVE_WINDOW_TIMESTAMP_AUTO, which means that
@@ -421,6 +424,9 @@
     nsecs_t mLastDequeueDuration = 0;
     nsecs_t mLastQueueDuration = 0;
 
+    // Stores the time right before we call IGBP::dequeueBuffer
+    nsecs_t mLastDequeueStartTime = 0;
+
     Condition mQueueBufferCondition;
 
     uint64_t mNextFrameNumber = 1;
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index ec310cf..145c059 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -271,6 +271,7 @@
     uint32_t getStride() const;
     // size of allocated memory in bytes
     size_t getSize() const;
+    android_dataspace getDataSpace() const;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h b/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
index 93c452a..c3a9d44 100644
--- a/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
+++ b/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
@@ -65,7 +65,7 @@
     status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) override;
     status_t setAsyncMode(bool async) override;
     status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
-            uint32_t h, ::android::PixelFormat format, uint32_t usage,
+            uint32_t h, ::android::PixelFormat format, uint64_t usage,
             FrameEventHistoryDelta* outTimestamps) override;
     status_t detachBuffer(int slot) override;
     status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence)
@@ -83,7 +83,7 @@
             override;
     status_t setSidebandStream(const sp<NativeHandle>& stream) override;
     void allocateBuffers(uint32_t width, uint32_t height,
-            ::android::PixelFormat format, uint32_t usage) override;
+            ::android::PixelFormat format, uint64_t usage) override;
     status_t allowAllocation(bool allow) override;
     status_t setGenerationNumber(uint32_t generationNumber) override;
     String8 getConsumerName() const override;
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index be754c2..168d355 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -703,9 +703,9 @@
     return NO_ERROR;
 }
 
-status_t BufferQueueConsumer::setConsumerUsageBits(uint32_t usage) {
+status_t BufferQueueConsumer::setConsumerUsageBits(uint64_t usage) {
     ATRACE_CALL();
-    BQ_LOGV("setConsumerUsageBits: %#x", usage);
+    BQ_LOGV("setConsumerUsageBits: %#" PRIx64, usage);
     Mutex::Autolock lock(mCore->mMutex);
     mCore->mConsumerUsageBits = usage;
     return NO_ERROR;
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 7510069..b39ecc5 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -349,7 +349,7 @@
 
 status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
         sp<android::Fence> *outFence, uint32_t width, uint32_t height,
-        PixelFormat format, uint32_t usage,
+        PixelFormat format, uint64_t usage,
         FrameEventHistoryDelta* outTimestamps) {
     ATRACE_CALL();
     { // Autolock scope
@@ -367,8 +367,7 @@
         }
     } // Autolock scope
 
-    BQ_LOGV("dequeueBuffer: w=%u h=%u format=%#x, usage=%#x", width, height,
-            format, usage);
+    BQ_LOGV("dequeueBuffer: w=%u h=%u format=%#x, usage=%#" PRIx64, width, height, format, usage);
 
     if ((width && !height) || (!width && height)) {
         BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
@@ -418,11 +417,9 @@
             // buffer. If this buffer would require reallocation to meet the
             // requested attributes, we free it and attempt to get another one.
             if (!mCore->mAllowAllocation) {
-                if (buffer->needsReallocation(width, height, format,
-                        BQ_LAYER_COUNT, usage)) {
+                if (buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) {
                     if (mCore->mSharedBufferSlot == found) {
-                        BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
-                                "buffer");
+                        BQ_LOGE("dequeueBuffer: cannot re-allocate a sharedbuffer");
                         return BAD_VALUE;
                     }
                     mCore->mFreeSlots.insert(found);
@@ -435,8 +432,7 @@
 
         const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
         if (mCore->mSharedBufferSlot == found &&
-                buffer->needsReallocation(width, height, format,
-                        BQ_LAYER_COUNT, usage)) {
+                buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) {
             BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
                     "buffer");
 
@@ -470,8 +466,7 @@
         } else {
             // We add 1 because that will be the frame number when this buffer
             // is queued
-            mCore->mBufferAge =
-                    mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;
+            mCore->mBufferAge = mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;
         }
 
         BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64,
@@ -1313,14 +1308,14 @@
 }
 
 void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
-        PixelFormat format, uint32_t usage) {
+        PixelFormat format, uint64_t usage) {
     ATRACE_CALL();
     while (true) {
         size_t newBufferCount = 0;
         uint32_t allocWidth = 0;
         uint32_t allocHeight = 0;
         PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN;
-        uint32_t allocUsage = 0;
+        uint64_t allocUsage = 0;
         { // Autolock scope
             Mutex::Autolock lock(mCore->mMutex);
             mCore->waitWhileAllocatingLocked();
@@ -1354,7 +1349,7 @@
 
             if (result != NO_ERROR) {
                 BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
-                        " %u, usage %u)", width, height, format, usage);
+                        " %u, usage %#" PRIx64 ")", width, height, format, usage);
                 Mutex::Autolock lock(mCore->mMutex);
                 mCore->mIsAllocating = false;
                 mCore->mIsAllocatingCondition.broadcast();
@@ -1369,7 +1364,7 @@
             uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
             PixelFormat checkFormat = format != 0 ?
                     format : mCore->mDefaultBufferFormat;
-            uint32_t checkUsage = usage | mCore->mConsumerUsageBits;
+            uint64_t checkUsage = usage | mCore->mConsumerUsageBits;
             if (checkWidth != allocWidth || checkHeight != allocHeight ||
                 checkFormat != allocFormat || checkUsage != allocUsage) {
                 // Something changed while we released the lock. Retry.
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index c654f08..34c9d78 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -21,6 +21,8 @@
 #define GL_GLEXT_PROTOTYPES
 #define EGL_EGLEXT_PROTOTYPES
 
+#include <inttypes.h>
+
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 #include <GLES2/gl2.h>
@@ -1219,7 +1221,7 @@
         mEglDisplay = EGL_NO_DISPLAY;
         mCropRect.makeInvalid();
         const sp<GraphicBuffer>& buffer = mGraphicBuffer;
-        ALOGE("Failed to create image. size=%ux%u st=%u usage=0x%x fmt=%d",
+        ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
             buffer->getWidth(), buffer->getHeight(), buffer->getStride(),
             buffer->getUsage(), buffer->getPixelFormat());
         return UNKNOWN_ERROR;
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index a573bee..c705d39 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -132,7 +132,7 @@
         return callRemote<Signature>(Tag::SET_DEFAULT_BUFFER_DATA_SPACE, defaultDataSpace);
     }
 
-    status_t setConsumerUsageBits(uint32_t usage) override {
+    status_t setConsumerUsageBits(uint64_t usage) override {
         using Signature = decltype(&IGraphicBufferConsumer::setConsumerUsageBits);
         return callRemote<Signature>(Tag::SET_CONSUMER_USAGE_BITS, usage);
     }
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 8481b50..1b0fe06 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -125,7 +125,7 @@
     }
 
     virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, uint32_t width,
-            uint32_t height, PixelFormat format, uint32_t usage,
+            uint32_t height, PixelFormat format, uint64_t usage,
             FrameEventHistoryDelta* outTimestamps) {
         Parcel data, reply;
         bool getFrameTimestamps = (outTimestamps != nullptr);
@@ -134,7 +134,7 @@
         data.writeUint32(width);
         data.writeUint32(height);
         data.writeInt32(static_cast<int32_t>(format));
-        data.writeUint32(usage);
+        data.writeUint64(usage);
         data.writeBool(getFrameTimestamps);
 
         status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
@@ -333,13 +333,13 @@
     }
 
     virtual void allocateBuffers(uint32_t width, uint32_t height,
-            PixelFormat format, uint32_t usage) {
+            PixelFormat format, uint64_t usage) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
         data.writeUint32(width);
         data.writeUint32(height);
         data.writeInt32(static_cast<int32_t>(format));
-        data.writeUint32(usage);
+        data.writeUint64(usage);
         status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply);
         if (result != NO_ERROR) {
             ALOGE("allocateBuffers failed to transact: %d", result);
@@ -517,7 +517,7 @@
     }
 
     status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h,
-            PixelFormat format, uint32_t usage,
+            PixelFormat format, uint64_t usage,
             FrameEventHistoryDelta* outTimestamps) override {
         return mBase->dequeueBuffer(
                 slot, fence, w, h, format, usage, outTimestamps);
@@ -569,7 +569,7 @@
     }
 
     void allocateBuffers(uint32_t width, uint32_t height,
-            PixelFormat format, uint32_t usage) override {
+            PixelFormat format, uint64_t usage) override {
         return mBase->allocateBuffers(width, height, format, usage);
     }
 
@@ -654,7 +654,7 @@
             uint32_t width = data.readUint32();
             uint32_t height = data.readUint32();
             PixelFormat format = static_cast<PixelFormat>(data.readInt32());
-            uint32_t usage = data.readUint32();
+            uint64_t usage = data.readUint64();
             bool getTimestamps = data.readBool();
 
             int buf = 0;
@@ -777,7 +777,7 @@
             uint32_t width = data.readUint32();
             uint32_t height = data.readUint32();
             PixelFormat format = static_cast<PixelFormat>(data.readInt32());
-            uint32_t usage = data.readUint32();
+            uint64_t usage = data.readUint64();
             allocateBuffers(width, height, format, usage);
             return NO_ERROR;
         }
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 83ebbe8..409a3cb 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -20,6 +20,8 @@
 
 #include <gui/Surface.h>
 
+#include <inttypes.h>
+
 #include <android/native_window.h>
 
 #include <utils/Log.h>
@@ -471,7 +473,7 @@
     uint32_t reqWidth;
     uint32_t reqHeight;
     PixelFormat reqFormat;
-    uint32_t reqUsage;
+    uint64_t reqUsage;
     bool enableFrameTimestamps;
 
     {
@@ -501,18 +503,18 @@
 
     int buf = -1;
     sp<Fence> fence;
-    nsecs_t now = systemTime();
+    nsecs_t startTime = systemTime();
 
     FrameEventHistoryDelta frameTimestamps;
     status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
             reqWidth, reqHeight, reqFormat, reqUsage,
             enableFrameTimestamps ? &frameTimestamps : nullptr);
-    mLastDequeueDuration = systemTime() - now;
+    mLastDequeueDuration = systemTime() - startTime;
 
     if (result < 0) {
         ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer"
-                "(%d, %d, %d, %d) failed: %d", reqWidth, reqHeight, reqFormat,
-                reqUsage, result);
+                "(%d, %d, %d, %#" PRIx64 ") failed: %d",
+                reqWidth, reqHeight, reqFormat, reqUsage, result);
         return result;
     }
 
@@ -524,6 +526,9 @@
 
     Mutex::Autolock lock(mMutex);
 
+    // Write this while holding the mutex
+    mLastDequeueStartTime = startTime;
+
     sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
 
     // this should never happen
@@ -959,6 +964,9 @@
     case NATIVE_WINDOW_GET_HDR_SUPPORT:
         res = dispatchGetHdrSupport(args);
         break;
+    case NATIVE_WINDOW_SET_USAGE64:
+        res = dispatchSetUsage64(args);
+        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -977,8 +985,13 @@
 }
 
 int Surface::dispatchSetUsage(va_list args) {
-    int usage = va_arg(args, int);
-    return setUsage(static_cast<uint32_t>(usage));
+    uint64_t usage = va_arg(args, uint32_t);
+    return setUsage(usage);
+}
+
+int Surface::dispatchSetUsage64(va_list args) {
+    uint64_t usage = va_arg(args, uint64_t);
+    return setUsage(usage);
 }
 
 int Surface::dispatchSetCrop(va_list args) {
@@ -1256,8 +1269,7 @@
     uint32_t priorGeneration = graphicBuffer->mGenerationNumber;
     graphicBuffer->mGenerationNumber = mGenerationNumber;
     int32_t attachedSlot = -1;
-    status_t result = mGraphicBufferProducer->attachBuffer(
-            &attachedSlot, graphicBuffer);
+    status_t result = mGraphicBufferProducer->attachBuffer(&attachedSlot, graphicBuffer);
     if (result != NO_ERROR) {
         ALOGE("attachBuffer: IGraphicBufferProducer call failed (%d)", result);
         graphicBuffer->mGenerationNumber = priorGeneration;
@@ -1271,7 +1283,7 @@
     return NO_ERROR;
 }
 
-int Surface::setUsage(uint32_t reqUsage)
+int Surface::setUsage(uint64_t reqUsage)
 {
     ALOGV("Surface::setUsage");
     Mutex::Autolock lock(mMutex);
@@ -1702,6 +1714,11 @@
     return mGraphicBufferProducer->getUniqueId(outId);
 }
 
+nsecs_t Surface::getLastDequeueStartTime() const {
+    Mutex::Autolock lock(mMutex);
+    return mLastDequeueStartTime;
+}
+
 status_t Surface::getAndFlushRemovedBuffers(std::vector<sp<GraphicBuffer>>* out) {
     if (out == nullptr) {
         ALOGE("%s: out must not be null!", __FUNCTION__);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 8c83843..7ae2672 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1080,5 +1080,9 @@
     return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format);
 }
 
+android_dataspace ScreenshotClient::getDataSpace() const {
+    return mBuffer.dataSpace;
+}
+
 // ----------------------------------------------------------------------------
 }; // namespace android
diff --git a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
index fda5b94..7c0552e 100644
--- a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
+++ b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
@@ -125,7 +125,7 @@
     t->attr.stride = l.getStride();
     t->attr.format = static_cast<PixelFormat>(l.getPixelFormat());
     t->attr.layerCount = l.getLayerCount();
-    t->attr.usage = l.getUsage();
+    t->attr.usage = uint32_t(l.getUsage());     // FIXME: need 64-bits usage version
     t->attr.id = l.getId();
     t->attr.generationNumber = l.getGenerationNumber();
     t->nativeHandle = hidl_handle(l.handle);
@@ -988,14 +988,15 @@
     return toStatusT(mBase->setAsyncMode(async));
 }
 
+// FIXME: usage bits truncated -- needs a 64-bits usage version
 status_t H2BGraphicBufferProducer::dequeueBuffer(
         int* slot, sp<Fence>* fence,
         uint32_t w, uint32_t h, ::android::PixelFormat format,
-        uint32_t usage, FrameEventHistoryDelta* outTimestamps) {
+        uint64_t usage, FrameEventHistoryDelta* outTimestamps) {
     *fence = new Fence();
     status_t fnStatus;
     status_t transStatus = toStatusT(mBase->dequeueBuffer(
-            w, h, static_cast<PixelFormat>(format), usage,
+            w, h, static_cast<PixelFormat>(format), uint32_t(usage),
             outTimestamps != nullptr,
             [&fnStatus, slot, fence, outTimestamps] (
                     Status status,
@@ -1144,10 +1145,11 @@
     return toStatusT(mBase->setSidebandStream(stream == nullptr ? nullptr : stream->handle()));
 }
 
+// FIXME: usage bits truncated -- needs a 64-bits usage version
 void H2BGraphicBufferProducer::allocateBuffers(uint32_t width, uint32_t height,
-        ::android::PixelFormat format, uint32_t usage) {
+        ::android::PixelFormat format, uint64_t usage) {
     mBase->allocateBuffers(
-            width, height, static_cast<PixelFormat>(format), usage);
+            width, height, static_cast<PixelFormat>(format), uint32_t(usage));
 }
 
 status_t H2BGraphicBufferProducer::allowAllocation(bool allow) {
diff --git a/libs/gui/tests/Malicious.cpp b/libs/gui/tests/Malicious.cpp
index 7ecf08c..6bc3ccf 100644
--- a/libs/gui/tests/Malicious.cpp
+++ b/libs/gui/tests/Malicious.cpp
@@ -38,7 +38,7 @@
     }
     status_t setAsyncMode(bool async) override { return mProducer->setAsyncMode(async); }
     status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h, PixelFormat format,
-                           uint32_t usage, FrameEventHistoryDelta* outTimestamps) override {
+                           uint64_t usage, FrameEventHistoryDelta* outTimestamps) override {
         return mProducer->dequeueBuffer(slot, fence, w, h, format, usage, outTimestamps);
     }
     status_t detachBuffer(int slot) override { return mProducer->detachBuffer(slot); }
@@ -67,7 +67,7 @@
         return mProducer->setSidebandStream(stream);
     }
     void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format,
-                         uint32_t usage) override {
+                         uint64_t usage) override {
         mProducer->allocateBuffers(width, height, format, usage);
     }
     status_t allowAllocation(bool allow) override { return mProducer->allowAllocation(allow); }
@@ -105,7 +105,7 @@
 
     // Override dequeueBuffer, optionally corrupting the returned slot number
     status_t dequeueBuffer(int* buf, sp<Fence>* fence, uint32_t width, uint32_t height,
-                           PixelFormat format, uint32_t usage,
+                           PixelFormat format, uint64_t usage,
                            FrameEventHistoryDelta* outTimestamps) override {
         EXPECT_EQ(BUFFER_NEEDS_REALLOCATION,
                   mProducer->dequeueBuffer(buf, fence, width, height, format, usage,
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index fcaa23a..81820de 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -393,6 +393,22 @@
     ASSERT_LE(removedBuffers.size(), 1u);
 }
 
+TEST_F(SurfaceTest, TestGetLastDequeueStartTime) {
+    sp<ANativeWindow> anw(mSurface);
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(), NATIVE_WINDOW_API_CPU));
+
+    ANativeWindowBuffer* buffer = nullptr;
+    int32_t fenceFd = -1;
+
+    nsecs_t before = systemTime(CLOCK_MONOTONIC);
+    anw->dequeueBuffer(anw.get(), &buffer, &fenceFd);
+    nsecs_t after = systemTime(CLOCK_MONOTONIC);
+
+    nsecs_t lastDequeueTime = mSurface->getLastDequeueStartTime();
+    ASSERT_LE(before, lastDequeueTime);
+    ASSERT_GE(after, lastDequeueTime);
+}
+
 class FakeConsumer : public BnConsumerListener {
 public:
     void onFrameAvailable(const BufferItem& /*item*/) override {}
@@ -1568,4 +1584,4 @@
     EXPECT_EQ(-1, outDisplayPresentTime);
 }
 
-}
+} // namespace android
diff --git a/libs/math/include/math/TMatHelpers.h b/libs/math/include/math/TMatHelpers.h
index 5cb725d..1423ade 100644
--- a/libs/math/include/math/TMatHelpers.h
+++ b/libs/math/include/math/TMatHelpers.h
@@ -342,9 +342,9 @@
 template <typename MATRIX>
 String8 asString(const MATRIX& m) {
     String8 s;
-    for (size_t c = 0; c < MATRIX::col_size(); c++) {
+    for (size_t c = 0; c < MATRIX::COL_SIZE; c++) {
         s.append("|  ");
-        for (size_t r = 0; r < MATRIX::row_size(); r++) {
+        for (size_t r = 0; r < MATRIX::ROW_SIZE; r++) {
             s.appendFormat("%7.2f  ", m[r][c]);
         }
         s.append("|\n");
diff --git a/libs/nativebase/include/nativebase/nativebase.h b/libs/nativebase/include/nativebase/nativebase.h
index 90afb3f..7ecdfbd 100644
--- a/libs/nativebase/include/nativebase/nativebase.h
+++ b/libs/nativebase/include/nativebase/nativebase.h
@@ -88,14 +88,18 @@
     int height;
     int stride;
     int format;
-    int usage;
+    int usage_deprecated;
     uintptr_t layerCount;
 
     void* reserved[1];
 
     const native_handle_t* handle;
+    uint64_t usage;
 
-    void* reserved_proc[8];
+    // we needed extra space for storing the 64-bits usage flags
+    // the number of slots to use from reserved_proc depends on the
+    // architecture.
+    void* reserved_proc[8 - (sizeof(uint64_t) / sizeof(void*))];
 } ANativeWindowBuffer_t;
 
 typedef struct ANativeWindowBuffer ANativeWindowBuffer;
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index 9224df6..c6994c3 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -190,8 +190,7 @@
 }
 
 int ANativeWindow_setUsage(ANativeWindow* window, uint64_t usage) {
-    usage = AHardwareBuffer_convertToGrallocUsageBits(usage);
-    return native_window_set_usage(window, (uint32_t)usage); // FIXME: we need a 64-bits version
+    return native_window_set_usage(window, usage);
 }
 
 int ANativeWindow_setBufferCount(ANativeWindow* window, size_t bufferCount) {
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 6429c52..3df97a1 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -193,36 +193,37 @@
  */
 enum {
 // clang-format off
-    NATIVE_WINDOW_SET_USAGE                 =  0,
-    NATIVE_WINDOW_CONNECT                   =  1,   /* deprecated */
-    NATIVE_WINDOW_DISCONNECT                =  2,   /* deprecated */
-    NATIVE_WINDOW_SET_CROP                  =  3,   /* private */
-    NATIVE_WINDOW_SET_BUFFER_COUNT          =  4,
-    NATIVE_WINDOW_SET_BUFFERS_GEOMETRY      =  5,   /* deprecated */
-    NATIVE_WINDOW_SET_BUFFERS_TRANSFORM     =  6,
-    NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP     =  7,
-    NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS    =  8,
-    NATIVE_WINDOW_SET_BUFFERS_FORMAT        =  9,
-    NATIVE_WINDOW_SET_SCALING_MODE          = 10,   /* private */
-    NATIVE_WINDOW_LOCK                      = 11,   /* private */
-    NATIVE_WINDOW_UNLOCK_AND_POST           = 12,   /* private */
-    NATIVE_WINDOW_API_CONNECT               = 13,   /* private */
-    NATIVE_WINDOW_API_DISCONNECT            = 14,   /* private */
-    NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS = 15, /* private */
-    NATIVE_WINDOW_SET_POST_TRANSFORM_CROP   = 16,   /* private */
-    NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM = 17,/* private */
-    NATIVE_WINDOW_SET_SIDEBAND_STREAM       = 18,
-    NATIVE_WINDOW_SET_BUFFERS_DATASPACE     = 19,
-    NATIVE_WINDOW_SET_SURFACE_DAMAGE        = 20,   /* private */
-    NATIVE_WINDOW_SET_SHARED_BUFFER_MODE    = 21,
-    NATIVE_WINDOW_SET_AUTO_REFRESH          = 22,
-    NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION= 23,
-    NATIVE_WINDOW_GET_NEXT_FRAME_ID         = 24,
-    NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS   = 25,
-    NATIVE_WINDOW_GET_COMPOSITOR_TIMING     = 26,
-    NATIVE_WINDOW_GET_FRAME_TIMESTAMPS      = 27,
-    NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT    = 28,
-    NATIVE_WINDOW_GET_HDR_SUPPORT           = 29,
+    NATIVE_WINDOW_SET_USAGE                     =  0,   /* deprecated */
+    NATIVE_WINDOW_CONNECT                       =  1,   /* deprecated */
+    NATIVE_WINDOW_DISCONNECT                    =  2,   /* deprecated */
+    NATIVE_WINDOW_SET_CROP                      =  3,   /* private */
+    NATIVE_WINDOW_SET_BUFFER_COUNT              =  4,
+    NATIVE_WINDOW_SET_BUFFERS_GEOMETRY          =  5,   /* deprecated */
+    NATIVE_WINDOW_SET_BUFFERS_TRANSFORM         =  6,
+    NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP         =  7,
+    NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS        =  8,
+    NATIVE_WINDOW_SET_BUFFERS_FORMAT            =  9,
+    NATIVE_WINDOW_SET_SCALING_MODE              = 10,   /* private */
+    NATIVE_WINDOW_LOCK                          = 11,   /* private */
+    NATIVE_WINDOW_UNLOCK_AND_POST               = 12,   /* private */
+    NATIVE_WINDOW_API_CONNECT                   = 13,   /* private */
+    NATIVE_WINDOW_API_DISCONNECT                = 14,   /* private */
+    NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS   = 15,   /* private */
+    NATIVE_WINDOW_SET_POST_TRANSFORM_CROP       = 16,   /* deprecated, unimplemented */
+    NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM  = 17,   /* private */
+    NATIVE_WINDOW_SET_SIDEBAND_STREAM           = 18,
+    NATIVE_WINDOW_SET_BUFFERS_DATASPACE         = 19,
+    NATIVE_WINDOW_SET_SURFACE_DAMAGE            = 20,   /* private */
+    NATIVE_WINDOW_SET_SHARED_BUFFER_MODE        = 21,
+    NATIVE_WINDOW_SET_AUTO_REFRESH              = 22,
+    NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION    = 23,
+    NATIVE_WINDOW_GET_NEXT_FRAME_ID             = 24,
+    NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS       = 25,
+    NATIVE_WINDOW_GET_COMPOSITOR_TIMING         = 26,
+    NATIVE_WINDOW_GET_FRAME_TIMESTAMPS          = 27,
+    NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT        = 28,
+    NATIVE_WINDOW_GET_HDR_SUPPORT               = 29,
+    NATIVE_WINDOW_SET_USAGE64                   = 30,
 // clang-format on
 };
 
@@ -533,20 +534,18 @@
 typedef struct ANativeWindow android_native_window_t __deprecated;
 
 /*
- *  native_window_set_usage(..., usage)
+ *  native_window_set_usage64(..., usage)
  *  Sets the intended usage flags for the next buffers
  *  acquired with (*lockBuffer)() and on.
- *  By default (if this function is never called), a usage of
- *      GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE
- *  is assumed.
+ *
+ *  Valid usage flags are defined in android/hardware_buffer.h
+ *  All AHARDWAREBUFFER_USAGE_* flags can be specified as needed.
+ *
  *  Calling this function will usually cause following buffers to be
  *  reallocated.
  */
-
-static inline int native_window_set_usage(
-        struct ANativeWindow* window, int usage)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_USAGE, usage);
+static inline int native_window_set_usage(struct ANativeWindow* window, uint64_t usage) {
+    return window->perform(window, NATIVE_WINDOW_SET_USAGE64, usage);
 }
 
 /* deprecated. Always returns 0. Don't call. */
@@ -589,45 +588,6 @@
 }
 
 /*
- * native_window_set_post_transform_crop(..., crop)
- * Sets which region of the next queued buffers needs to be considered.
- * Depending on the scaling mode, a buffer's crop region is scaled and/or
- * cropped to match the surface's size.  This function sets the crop in
- * post-transformed pixel coordinates.
- *
- * The specified crop region applies to all buffers queued after it is called.
- *
- * If 'crop' is NULL, subsequently queued buffers won't be cropped.
- *
- * An error is returned if for instance the crop region is invalid, out of the
- * buffer's bound or if the window is invalid.
- */
-static inline int native_window_set_post_transform_crop(
-        struct ANativeWindow* window,
-        android_native_rect_t const * crop)
-{
-    return window->perform(window, NATIVE_WINDOW_SET_POST_TRANSFORM_CROP, crop);
-}
-
-/*
- * native_window_set_active_rect(..., active_rect)
- *
- * This function is deprecated and will be removed soon.  For now it simply
- * sets the post-transform crop for compatibility while multi-project commits
- * get checked.
- */
-static inline int native_window_set_active_rect(
-        struct ANativeWindow* window,
-        android_native_rect_t const * active_rect) __deprecated;
-
-static inline int native_window_set_active_rect(
-        struct ANativeWindow* window,
-        android_native_rect_t const * active_rect)
-{
-    return native_window_set_post_transform_crop(window, active_rect);
-}
-
-/*
  * native_window_set_buffer_count(..., count)
  * Sets the number of buffers associated with this native window.
  */
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index ee85c9b..c880500 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -51,6 +51,7 @@
     height =
     stride =
     format =
+    usage_deprecated = 0;
     usage  = 0;
     layerCount = 0;
     handle = NULL;
@@ -59,14 +60,12 @@
 // deprecated
 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
         PixelFormat inFormat, uint32_t inUsage, std::string requestorName)
-    : GraphicBuffer(inWidth, inHeight, inFormat, 1, static_cast<uint64_t>(inUsage),
-            requestorName)
+    : GraphicBuffer(inWidth, inHeight, inFormat, 1, static_cast<uint64_t>(inUsage), requestorName)
 {
 }
 
 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
-        PixelFormat inFormat, uint32_t inLayerCount, uint64_t usage,
-        std::string requestorName)
+        PixelFormat inFormat, uint32_t inLayerCount, uint64_t usage, std::string requestorName)
     : GraphicBuffer()
 {
     mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount,
@@ -139,7 +138,7 @@
             static_cast<int>(inHeight) == height &&
             inFormat == format &&
             inLayerCount == layerCount &&
-            static_cast<int>(inUsage) == usage)
+            inUsage == usage)
         return NO_ERROR;
 
     if (handle) {
@@ -147,8 +146,7 @@
         allocator.free(handle);
         handle = 0;
     }
-    return initWithSize(inWidth, inHeight, inFormat, inLayerCount,
-            inUsage, "[Reallocation]");
+    return initWithSize(inWidth, inHeight, inFormat, inLayerCount, inUsage, "[Reallocation]");
 }
 
 bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight,
@@ -158,7 +156,7 @@
     if (static_cast<int>(inHeight) != height) return true;
     if (inFormat != format) return true;
     if (inLayerCount != layerCount) return true;
-    if ((static_cast<uint32_t>(usage) & inUsage) != inUsage) return true;
+    if ((usage & inUsage) != inUsage) return true;
     return false;
 }
 
@@ -176,7 +174,8 @@
         height = static_cast<int>(inHeight);
         format = inFormat;
         layerCount = inLayerCount;
-        usage = static_cast<int>(inUsage);
+        usage = inUsage;
+        usage_deprecated = int(usage);
         stride = static_cast<int>(outStride);
     }
     return err;
@@ -191,7 +190,8 @@
     ANativeWindowBuffer::height = static_cast<int>(height);
     ANativeWindowBuffer::stride = static_cast<int>(stride);
     ANativeWindowBuffer::format = format;
-    ANativeWindowBuffer::usage  = static_cast<int>(usage);
+    ANativeWindowBuffer::usage  = usage;
+    ANativeWindowBuffer::usage_deprecated = int(usage);
 
     ANativeWindowBuffer::layerCount = layerCount;
 
@@ -312,8 +312,7 @@
                 width, height);
         return BAD_VALUE;
     }
-    status_t res = getBufferMapper().lockAsyncYCbCr(handle, inUsage, rect,
-            ycbcr, fenceFd);
+    status_t res = getBufferMapper().lockAsyncYCbCr(handle, inUsage, rect, ycbcr, fenceFd);
     return res;
 }
 
@@ -324,7 +323,7 @@
 }
 
 size_t GraphicBuffer::getFlattenedSize() const {
-    return static_cast<size_t>(12 + (handle ? handle->numInts : 0)) * sizeof(int);
+    return static_cast<size_t>(13 + (handle ? handle->numInts : 0)) * sizeof(int);
 }
 
 size_t GraphicBuffer::getFdCount() const {
@@ -339,25 +338,25 @@
     if (count < fdCountNeeded) return NO_MEMORY;
 
     int32_t* buf = static_cast<int32_t*>(buffer);
-    buf[0] = 'GBFR';
+    buf[0] = 'GB01';
     buf[1] = width;
     buf[2] = height;
     buf[3] = stride;
     buf[4] = format;
     buf[5] = static_cast<int32_t>(layerCount);
-    buf[6] = usage;
+    buf[6] = int(usage); // low 32-bits
     buf[7] = static_cast<int32_t>(mId >> 32);
     buf[8] = static_cast<int32_t>(mId & 0xFFFFFFFFull);
     buf[9] = static_cast<int32_t>(mGenerationNumber);
     buf[10] = 0;
     buf[11] = 0;
+    buf[12] = int(usage >> 32); // high 32-bits
 
     if (handle) {
         buf[10] = handle->numFds;
         buf[11] = handle->numInts;
-        memcpy(fds, handle->data,
-                static_cast<size_t>(handle->numFds) * sizeof(int));
-        memcpy(&buf[12], handle->data + handle->numFds,
+        memcpy(fds, handle->data, static_cast<size_t>(handle->numFds) * sizeof(int));
+        memcpy(buf + 13, handle->data + handle->numFds,
                 static_cast<size_t>(handle->numInts) * sizeof(int));
     }
 
@@ -373,10 +372,21 @@
 
 status_t GraphicBuffer::unflatten(
         void const*& buffer, size_t& size, int const*& fds, size_t& count) {
-    if (size < 12 * sizeof(int)) return NO_MEMORY;
 
     int const* buf = static_cast<int const*>(buffer);
-    if (buf[0] != 'GBFR') return BAD_TYPE;
+
+    // NOTE: it turns out that some media code generates a flattened GraphicBuffer manually!!!!!
+    // see H2BGraphicBufferProducer.cpp
+    uint32_t flattenWordCount = 0;
+    if (buf[0] == 'GB01') {
+        // new version with 64-bits usage bits
+        flattenWordCount = 13;
+    } else if (buf[0] == 'GBFR') {
+        // old version, when usage bits were 32-bits
+        flattenWordCount = 12;
+    } else {
+        return BAD_TYPE;
+    }
 
     const size_t numFds  = static_cast<size_t>(buf[10]);
     const size_t numInts = static_cast<size_t>(buf[11]);
@@ -386,15 +396,16 @@
     // chosen to be high enough to not cause issues and low enough to prevent
     // overflow problems.
     const size_t maxNumber = 4096;
-    if (numFds >= maxNumber || numInts >= (maxNumber - 12)) {
-        width = height = stride = format = layerCount = usage = 0;
+    if (numFds >= maxNumber || numInts >= (maxNumber - flattenWordCount)) {
+        width = height = stride = format = usage_deprecated = 0;
+        layerCount = 0;
+        usage = 0;
         handle = NULL;
-        ALOGE("unflatten: numFds or numInts is too large: %zd, %zd",
-                numFds, numInts);
+        ALOGE("unflatten: numFds or numInts is too large: %zd, %zd", numFds, numInts);
         return BAD_VALUE;
     }
 
-    const size_t sizeNeeded = (12 + numInts) * sizeof(int);
+    const size_t sizeNeeded = (flattenWordCount + numInts) * sizeof(int);
     if (size < sizeNeeded) return NO_MEMORY;
 
     size_t fdCountNeeded = numFds;
@@ -411,20 +422,29 @@
         stride = buf[3];
         format = buf[4];
         layerCount = static_cast<uintptr_t>(buf[5]);
-        usage  = buf[6];
+        usage_deprecated = buf[6];
+        if (flattenWordCount == 13) {
+            usage = (uint64_t(buf[12]) << 32) | uint32_t(buf[6]);
+        } else {
+            usage = uint64_t(usage_deprecated);
+        }
         native_handle* h = native_handle_create(
                 static_cast<int>(numFds), static_cast<int>(numInts));
         if (!h) {
-            width = height = stride = format = layerCount = usage = 0;
+            width = height = stride = format = usage_deprecated = 0;
+            layerCount = 0;
+            usage = 0;
             handle = NULL;
             ALOGE("unflatten: native_handle_create failed");
             return NO_MEMORY;
         }
         memcpy(h->data, fds, numFds * sizeof(int));
-        memcpy(h->data + numFds, &buf[12], numInts * sizeof(int));
+        memcpy(h->data + numFds, buf + flattenWordCount, numInts * sizeof(int));
         handle = h;
     } else {
-        width = height = stride = format = layerCount = usage = 0;
+        width = height = stride = format = usage_deprecated = 0;
+        layerCount = 0;
+        usage = 0;
         handle = NULL;
     }
 
@@ -439,10 +459,11 @@
         buffer_handle_t importedHandle;
         status_t err = mBufferMapper.importBuffer(handle, &importedHandle);
         if (err != NO_ERROR) {
-            width = height = stride = format = layerCount = usage = 0;
+            width = height = stride = format = usage_deprecated = 0;
+            layerCount = 0;
+            usage = 0;
             handle = NULL;
-            ALOGE("unflatten: registerBuffer failed: %s (%d)",
-                    strerror(-err), err);
+            ALOGE("unflatten: registerBuffer failed: %s (%d)", strerror(-err), err);
             return err;
         }
 
diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
index 9a5aa69..95c2d22 100644
--- a/libs/ui/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -141,7 +141,7 @@
     uint32_t getWidth() const           { return static_cast<uint32_t>(width); }
     uint32_t getHeight() const          { return static_cast<uint32_t>(height); }
     uint32_t getStride() const          { return static_cast<uint32_t>(stride); }
-    uint32_t getUsage() const           { return static_cast<uint32_t>(usage); }
+    uint64_t getUsage() const           { return usage; }
     PixelFormat getPixelFormat() const  { return format; }
     uint32_t getLayerCount() const      { return static_cast<uint32_t>(layerCount); }
     Rect getBounds() const              { return Rect(width, height); }
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index 7dd076a..fca5eca 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -131,9 +131,9 @@
 
 status_t BufferHubQueueProducer::dequeueBuffer(
     int* out_slot, sp<Fence>* out_fence, uint32_t width, uint32_t height,
-    PixelFormat format, uint32_t usage,
+    PixelFormat format, uint64_t usage,
     FrameEventHistoryDelta* /* out_timestamps */) {
-  ALOGD_IF(TRACE, "dequeueBuffer: w=%u, h=%u, format=%d, usage=%u", width,
+  ALOGD_IF(TRACE, "dequeueBuffer: w=%u, h=%u, format=%d, usage=%llu", width,
            height, format, usage);
 
   status_t ret;
@@ -532,7 +532,7 @@
 void BufferHubQueueProducer::allocateBuffers(uint32_t /* width */,
                                              uint32_t /* height */,
                                              PixelFormat /* format */,
-                                             uint32_t /* usage */) {
+                                             uint64_t /* usage */) {
   // TODO(jwcai) |allocateBuffers| aims to preallocate up to the maximum number
   // of buffers permitted by the current BufferQueue configuration (aka
   // |max_buffer_count_|).
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
index 7890176..638a56c 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_producer.h
@@ -42,7 +42,7 @@
 
   // See |IGraphicBufferProducer::dequeueBuffer|
   status_t dequeueBuffer(int* out_slot, sp<Fence>* out_fence, uint32_t width,
-                         uint32_t height, PixelFormat format, uint32_t usage,
+                         uint32_t height, PixelFormat format, uint64_t usage,
                          FrameEventHistoryDelta* outTimestamps) override;
 
   // See |IGraphicBufferProducer::detachBuffer|
@@ -80,7 +80,7 @@
 
   // See |IGraphicBufferProducer::allocateBuffers|
   void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format,
-                       uint32_t usage) override;
+                       uint64_t usage) override;
 
   // See |IGraphicBufferProducer::allowAllocation|
   status_t allowAllocation(bool allow) override;
diff --git a/libs/vr/libdvr/dvr_buffer.cpp b/libs/vr/libdvr/dvr_buffer.cpp
index 82469b8..4d9b215 100644
--- a/libs/vr/libdvr/dvr_buffer.cpp
+++ b/libs/vr/libdvr/dvr_buffer.cpp
@@ -1,6 +1,7 @@
 #include "include/dvr/dvr_buffer.h"
 
 #include <android/hardware_buffer.h>
+#include <dvr/dvr_shared_buffers.h>
 #include <private/dvr/buffer_hub_client.h>
 #include <ui/GraphicBuffer.h>
 
@@ -176,6 +177,11 @@
                                   hardware_buffer);
 }
 
+// Retrieve the shared buffer layout version defined in dvr_shared_buffers.h.
+int dvrBufferGlobalLayoutVersionGet() {
+  return android::dvr::kSharedBufferLayoutVersion;
+}
+
 const struct native_handle* dvrWriteBufferGetNativeHandle(
     DvrWriteBuffer* write_buffer) {
   if (!write_buffer || !write_buffer->write_buffer)
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index 2affacd..0f4749d 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -171,8 +171,6 @@
 
   auto status = client->GetGlobalBuffer(key);
   if (!status) {
-    ALOGE("dvrGetGlobalBuffer: Failed to find named buffer key=%d: %s", key,
-          status.GetErrorMessage().c_str());
     return -status.error();
   }
   *out_buffer = CreateDvrBufferFromIonBuffer(status.take());
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 47a2a60..17b29d4 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -145,6 +145,7 @@
 typedef void (*DvrBufferDestroyPtr)(DvrBuffer* buffer);
 typedef int (*DvrBufferGetAHardwareBufferPtr)(
     DvrBuffer* buffer, AHardwareBuffer** hardware_buffer);
+typedef int (*DvrBufferGlobalLayoutVersionGetPtr)();
 typedef const struct native_handle* (*DvrBufferGetNativeHandlePtr)(
     DvrBuffer* buffer);
 
@@ -211,7 +212,7 @@
                                              uint32_t* next_vsync_count);
 
 // libs/vr/libvrsensor/include/dvr/pose_client.h
-typedef DvrPoseClient* (*DvrPoseClientCreatePtr)(void);
+typedef DvrPoseClient* (*DvrPoseClientCreatePtr)();
 typedef void (*DvrPoseClientDestroyPtr)(DvrPoseClient* client);
 typedef int (*DvrPoseClientGetPtr)(DvrPoseClient* client, uint32_t vsync_count,
                                    DvrPoseAsync* out_pose);
@@ -222,7 +223,13 @@
                                              DvrPoseAsync* out_pose);
 
 // services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
-typedef DvrVirtualTouchpad* (*DvrVirtualTouchpadCreatePtr)(void);
+
+// Touchpad IDs for *Touch*() and *ButtonState*() calls.
+enum {
+  DVR_VIRTUAL_TOUCHPAD_PRIMARY = 0,
+  DVR_VIRTUAL_TOUCHPAD_VIRTUAL = 1,
+};
+typedef DvrVirtualTouchpad* (*DvrVirtualTouchpadCreatePtr)();
 typedef void (*DvrVirtualTouchpadDestroyPtr)(DvrVirtualTouchpad* client);
 typedef int (*DvrVirtualTouchpadAttachPtr)(DvrVirtualTouchpad* client);
 typedef int (*DvrVirtualTouchpadDetachPtr)(DvrVirtualTouchpad* client);
diff --git a/libs/vr/libdvr/include/dvr/dvr_api_entries.h b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
index 8cdad7d..802a0f7 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api_entries.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
@@ -60,6 +60,7 @@
 DVR_V1_API_ENTRY(BufferDestroy);
 DVR_V1_API_ENTRY(BufferGetAHardwareBuffer);
 DVR_V1_API_ENTRY(BufferGetNativeHandle);
+DVR_V1_API_ENTRY(BufferGlobalLayoutVersionGet);
 
 // Write buffer queue
 DVR_V1_API_ENTRY(WriteBufferQueueDestroy);
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer.h b/libs/vr/libdvr/include/dvr/dvr_buffer.h
index af55698..935a7b2 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer.h
@@ -95,6 +95,9 @@
 int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
                                 AHardwareBuffer** hardware_buffer);
 
+// Retrieve the shared buffer layout version defined in dvr_shared_buffers.h.
+int dvrBufferGlobalLayoutVersionGet();
+
 // TODO(eieio): Switch to return int and take an out parameter for the native
 // handle.
 const struct native_handle* dvrBufferGetNativeHandle(DvrBuffer* buffer);
diff --git a/libs/vr/libdvr/include/dvr/dvr_vrflinger_config.h b/libs/vr/libdvr/include/dvr/dvr_config.h
similarity index 74%
rename from libs/vr/libdvr/include/dvr/dvr_vrflinger_config.h
rename to libs/vr/libdvr/include/dvr/dvr_config.h
index cfe9d62..3d2c066 100644
--- a/libs/vr/libdvr/include/dvr/dvr_vrflinger_config.h
+++ b/libs/vr/libdvr/include/dvr/dvr_config.h
@@ -1,17 +1,18 @@
-#ifndef ANDROID_DVR_VRFLINGER_CONFIG_H
-#define ANDROID_DVR_VRFLINGER_CONFIG_H
+#ifndef ANDROID_DVR_CONFIG_H
+#define ANDROID_DVR_CONFIG_H
 
 // This header is shared by VrCore and Android and must be kept in sync.
 
+#include <stdint.h>
 #include <sys/cdefs.h>
 
 __BEGIN_DECLS
 
 // This is a shared memory buffer for passing config data from VrCore to
 // libvrflinger in SurfaceFlinger.
-struct DvrVrFlingerConfig {
+struct __attribute__((packed, aligned(16))) DvrConfig {
   // Offset before vsync to submit frames to hardware composer.
-  int frame_post_offset_ns{4000000};
+  int32_t frame_post_offset_ns{4000000};
 
   // If the number of pending fences goes over this count at the point when we
   // are about to submit a new frame to HWC, we will drop the frame. This
@@ -20,11 +21,14 @@
   // the next vsync, at the point when the DMA to the display completes.
   // Currently we use a smart display and the EDS timing coincides with zero
   // pending fences, so this is 0.
-  size_t allowed_pending_fence_count{0};
+  int32_t allowed_pending_fence_count{0};
 
   // New fields should always be added to the end for backwards compat.
+
+  // Reserved padding to 16 bytes.
+  uint8_t pad[8];
 };
 
 __END_DECLS
 
-#endif  // ANDROID_DVR_VRFLINGER_CONFIG_H
+#endif  // ANDROID_DVR_CONFIG_H
diff --git a/libs/vr/libdvr/include/dvr/dvr_display_manager.h b/libs/vr/libdvr/include/dvr/dvr_display_manager.h
index 4bb0a2f..26f85a0 100644
--- a/libs/vr/libdvr/include/dvr/dvr_display_manager.h
+++ b/libs/vr/libdvr/include/dvr/dvr_display_manager.h
@@ -84,7 +84,7 @@
                                    size_t* count_out);
 
 // Returns the update flags for the surface at |surface_index| in the state
-// object. The flags may be used to determine what changes, if any, occured to
+// object. The flags may be used to determine what changes, if any, occurred to
 // the surface since the last state update.
 // @return 0 on success. Otherwise returns a negative error value.
 int dvrSurfaceStateGetUpdateFlags(DvrSurfaceState* surface_state,
diff --git a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
index 60e22de..0ba76e2 100644
--- a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
+++ b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
@@ -24,37 +24,73 @@
 DvrHwcClient* dvrHwcClientCreate(DvrHwcOnFrameCallback callback,
                                  void* client_state);
 
+// Called to free the DvrHwcClient pointer.
 void dvrHwcClientDestroy(DvrHwcClient* client);
 
 // Called to free the frame information.
+// @param frame Pointer for the valid frame used for the query.
 void dvrHwcFrameDestroy(DvrHwcFrame* frame);
 
+// @param frame Pointer for the valid frame used for the query.
+// @return Identifier for the display associated by the frame.
 DvrHwcDisplay dvrHwcFrameGetDisplayId(DvrHwcFrame* frame);
 
+// @param frame Pointer for the valid frame used for the query.
+// @return width of the physical display associated with |frame|. This does not
+// take into account any orientation changes.
 int32_t dvrHwcFrameGetDisplayWidth(DvrHwcFrame* frame);
 
+// @param frame Pointer for the valid frame used for the query.
+// @return height of the physical display associated with |frame|. This does not
+// take into account any orientation changes.
 int32_t dvrHwcFrameGetDisplayHeight(DvrHwcFrame* frame);
 
+// @param frame Pointer for the valid frame used for the query.
 // @return True if the display has been removed. In this case the current frame
 // does not contain any valid layers to display. It is a signal to clean up any
 // display related state.
 bool dvrHwcFrameGetDisplayRemoved(DvrHwcFrame* frame);
 
+// @param frame Pointer for the valid frame used for the query.
 // @return Number of layers in the frame.
 size_t dvrHwcFrameGetLayerCount(DvrHwcFrame* frame);
 
+// @param frame Pointer for the valid frame used for the query.
+// @return The ID of the currently active display configuration.
 uint32_t dvrHwcFrameGetActiveConfig(DvrHwcFrame* frame);
+
+// @param frame Pointer for the valid frame used for the query.
+// @return The ID of the current color mode. See HAL_COLOR_MODE_* for valid
+// values.
 uint32_t dvrHwcFrameGetColorMode(DvrHwcFrame* frame);
+
+// @param frame Pointer for the valid frame used for the query.
+// @param out_matrix Output parameter for a float[16] array which will be filled
+// with the color transform matrix.
+// @param out_hint Output parameter which will contain the color transform hint.
+// See HAL_COLOR_TRANSFORM_* for valid values.
 void dvrHwcFrameGetColorTransform(DvrHwcFrame* frame, float* out_matrix,
                                   int32_t* out_hint);
+
+// @param frame Pointer for the valid frame used for the query.
+// @return The current power mode for the display. See HWC2_POWER_MODE_* for
+// valid values.
 uint32_t dvrHwcFrameGetPowerMode(DvrHwcFrame* frame);
+
+// @param frame Pointer for the valid frame used for the query.
+// @return The current state of vsync. See HWC2_VSYNC_* for valid values.
 uint32_t dvrHwcFrameGetVsyncEnabled(DvrHwcFrame* frame);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return A unique ID for the layer.
 DvrHwcLayer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index);
 
 // Return the graphic buffer associated with the layer at |layer_index| in
 // |frame|.
 //
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
 // @return Graphic buffer. Caller owns the buffer and is responsible for freeing
 // it. (see AHardwareBuffer_release())
 AHardwareBuffer* dvrHwcFrameGetLayerBuffer(DvrHwcFrame* frame,
@@ -62,42 +98,98 @@
 
 // Returns the fence FD for the layer at index |layer_index| in |frame|.
 //
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
 // @return Fence FD. Caller owns the FD and is responsible for closing it.
 int dvrHwcFrameGetLayerFence(DvrHwcFrame* frame, size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return describing the portion of the display covered by the layer. Will
+// not exceed the display dimensions.
 DvrHwcRecti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame,
                                             size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return describing the portion of the layer that will fill the display
+// frame. Will not exceed the layer dimensions.
 DvrHwcRectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The blend mode of the layer.
 DvrHwcBlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame,
                                              size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The alpha value to be applied to the whole layer. Will be in the
+// [0.0, 1.0] range.
 float dvrHwcFrameGetLayerAlpha(DvrHwcFrame* frame, size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The type of the layer assigned by the window manager.
 uint32_t dvrHwcFrameGetLayerType(DvrHwcFrame* frame, size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The application id the layer belongs to.
 uint32_t dvrHwcFrameGetLayerApplicationId(DvrHwcFrame* frame,
                                           size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The z-order for the layer.
 uint32_t dvrHwcFrameGetLayerZOrder(DvrHwcFrame* frame, size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @param out_x Output parameter for the x coordinate of the cursor location.
+// @param out_y Output parameter for the y coordinate of the cursor location.
 void dvrHwcFrameGetLayerCursor(DvrHwcFrame* frame, size_t layer_index,
                                int32_t* out_x, int32_t* out_y);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The transformation that needs to be applied to the layer before
+// presenting it. See DVR_HWC_TRANSFORM_* for valid values.
 uint32_t dvrHwcFrameGetLayerTransform(DvrHwcFrame* frame, size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The dataspace which represents how the pixel values should be
+// interpreted. See HAL_DATASPACE_* for valid values.
 uint32_t dvrHwcFrameGetLayerDataspace(DvrHwcFrame* frame, size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The color of the layer if layer composition is SOLID_COLOR.
 uint32_t dvrHwcFrameGetLayerColor(DvrHwcFrame* frame, size_t layer_index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The number of visible regions.
 uint32_t dvrHwcFrameGetLayerNumVisibleRegions(DvrHwcFrame* frame,
                                               size_t layer_index);
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @param index The index of the visible region for the layer.
+// @return The rectangle describing the visible region.
 DvrHwcRecti dvrHwcFrameGetLayerVisibleRegion(DvrHwcFrame* frame,
                                              size_t layer_index, size_t index);
 
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @return The number of damanged regions.
 uint32_t dvrHwcFrameGetLayerNumDamagedRegions(DvrHwcFrame* frame,
                                               size_t layer_index);
+
+// @param frame Pointer for the valid frame used for the query.
+// @param layer_index The index of the layer in the frame.
+// @param index The index of the damanged region for the layer.
+// @return The rectangle describing the damaged region.
 DvrHwcRecti dvrHwcFrameGetLayerDamagedRegion(DvrHwcFrame* frame,
                                              size_t layer_index, size_t index);
 #ifdef __cplusplus
diff --git a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_types.h b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_types.h
index 36c30f9..1d5eda6 100644
--- a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_types.h
+++ b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_types.h
@@ -26,6 +26,15 @@
   DVR_HWC_COMPOSITION_SIDEBAND = 5,
 };
 
+enum DvrHwcTransform {
+  DVR_HWC_TRANSFORM_NONE = 0,
+  DVR_HWC_TRANSFORM_FLIP_H = 1,
+  DVR_HWC_TRANSFORM_FLIP_V = 2,
+  DVR_HWC_TRANSFORM_ROT_90 = 4,
+  DVR_HWC_TRANSFORM_ROT_180 = 3,
+  DVR_HWC_TRANSFORM_ROT_270 = 7,
+};
+
 typedef uint64_t DvrHwcDisplay;
 typedef uint64_t DvrHwcLayer;
 
diff --git a/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h b/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h
index ce17f0c..096f800 100644
--- a/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h
+++ b/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h
@@ -1,8 +1,8 @@
 #ifndef ANDROID_DVR_SHARED_BUFFERS_H_
 #define ANDROID_DVR_SHARED_BUFFERS_H_
 
+#include <dvr/dvr_config.h>
 #include <dvr/dvr_pose.h>
-#include <dvr/dvr_vrflinger_config.h>
 #include <dvr/dvr_vsync.h>
 #include <libbroadcastring/broadcast_ring.h>
 
@@ -11,7 +11,7 @@
 namespace dvr {
 
 // Increment when the layout for the buffers change.
-constexpr uint32_t kSharedBufferLayoutVersion = 1;
+enum : uint32_t { kSharedBufferLayoutVersion = 1 };
 
 // Note: These buffers will be mapped from various system processes as well
 // as VrCore and the application processes in a r/w manner.
@@ -26,6 +26,7 @@
 static_assert(sizeof(DvrPoseAsync) == 128, "Unexpected size for DvrPoseAsync");
 static_assert(sizeof(DvrPose) == 96, "Unexpected size for DvrPose");
 static_assert(sizeof(DvrVsync) == 32, "Unexpected size for DvrVsync");
+static_assert(sizeof(DvrConfig) == 16, "Unexpected size for DvrConfig");
 
 // A helper class that provides compile time sized traits for the BroadcastRing.
 template <class DvrType, size_t StaticCount>
@@ -41,13 +42,12 @@
 // Traits classes.
 using DvrPoseTraits = DvrRingBufferTraits<DvrPose, 0>;
 using DvrVsyncTraits = DvrRingBufferTraits<DvrVsync, 2>;
-using DvrVrFlingerConfigTraits = DvrRingBufferTraits<DvrVrFlingerConfig, 2>;
+using DvrConfigTraits = DvrRingBufferTraits<DvrConfig, 2>;
 
 // The broadcast ring classes that will expose the data.
 using DvrPoseRing = BroadcastRing<DvrPose, DvrPoseTraits>;
 using DvrVsyncRing = BroadcastRing<DvrVsync, DvrVsyncTraits>;
-using DvrVrFlingerConfigRing =
-    BroadcastRing<DvrVrFlingerConfig, DvrVrFlingerConfigTraits>;
+using DvrConfigRing = BroadcastRing<DvrConfig, DvrConfigTraits>;
 
 // This is a shared memory buffer for passing pose data estimated at vsyncs.
 //
diff --git a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
index 419083f..566f9de 100644
--- a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
@@ -1,9 +1,9 @@
 #include <android/hardware_buffer.h>
 #include <dvr/dvr_buffer.h>
+#include <dvr/dvr_config.h>
 #include <dvr/dvr_display_manager.h>
 #include <dvr/dvr_shared_buffers.h>
 #include <dvr/dvr_surface.h>
-#include <dvr/dvr_vrflinger_config.h>
 #include <system/graphics.h>
 
 #include <base/logging.h>
@@ -285,8 +285,8 @@
   const uint64_t usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN |
                          AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
 
-  size_t correct_size = DvrVrFlingerConfigRing::MemorySize();
-  size_t wrong_size = DvrVrFlingerConfigRing::MemorySize(0);
+  size_t correct_size = DvrConfigRing::MemorySize();
+  size_t wrong_size = DvrConfigRing::MemorySize(0);
 
   // Setup an invalid config buffer (too small) and assert that it fails.
   DvrBuffer* setup_buffer = nullptr;
diff --git a/libs/vr/libpdx/Android.bp b/libs/vr/libpdx/Android.bp
index 69300d6..f55e994 100644
--- a/libs/vr/libpdx/Android.bp
+++ b/libs/vr/libpdx/Android.bp
@@ -37,6 +37,7 @@
         "libpdx",
         "liblog",
         "libutils",
+        "libvndksupport",
     ],
 }
 
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 7a78d1f..c18ae82 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -481,9 +481,9 @@
 
 int HardwareComposer::MapConfigBuffer(IonBuffer& ion_buffer) {
   std::lock_guard<std::mutex> lock(shared_config_mutex_);
-  shared_config_ring_ = DvrVrFlingerConfigRing();
+  shared_config_ring_ = DvrConfigRing();
 
-  if (ion_buffer.width() < DvrVrFlingerConfigRing::MemorySize()) {
+  if (ion_buffer.width() < DvrConfigRing::MemorySize()) {
     ALOGE("HardwareComposer::MapConfigBuffer: invalid buffer size.");
     return -EINVAL;
   }
@@ -497,8 +497,7 @@
     return -EPERM;
   }
 
-  shared_config_ring_ =
-      DvrVrFlingerConfigRing::Create(buffer_base, ion_buffer.width());
+  shared_config_ring_ = DvrConfigRing::Create(buffer_base, ion_buffer.width());
   ion_buffer.Unlock();
 
   return 0;
@@ -506,7 +505,7 @@
 
 void HardwareComposer::ConfigBufferDeleted() {
   std::lock_guard<std::mutex> lock(shared_config_mutex_);
-  shared_config_ring_ = DvrVrFlingerConfigRing();
+  shared_config_ring_ = DvrConfigRing();
 }
 
 void HardwareComposer::UpdateConfigBuffer() {
@@ -514,7 +513,7 @@
   if (!shared_config_ring_.is_valid())
     return;
   // Copy from latest record in shared_config_ring_ to local copy.
-  DvrVrFlingerConfig record;
+  DvrConfig record;
   if (shared_config_ring_.GetNewest(&shared_config_ring_sequence_, &record)) {
     post_thread_config_ = record;
   }
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index de6f9ff..98e8905 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -17,7 +17,7 @@
 #include <tuple>
 #include <vector>
 
-#include <dvr/dvr_vrflinger_config.h>
+#include <dvr/dvr_config.h>
 #include <dvr/dvr_vsync.h>
 #include <pdx/file_handle.h>
 #include <pdx/rpc/variant.h>
@@ -452,10 +452,10 @@
   std::unique_ptr<CPUMappedBroadcastRing<DvrVsyncRing>> vsync_ring_;
 
   // Broadcast ring for receiving config data from the DisplayManager.
-  DvrVrFlingerConfigRing shared_config_ring_;
+  DvrConfigRing shared_config_ring_;
   uint32_t shared_config_ring_sequence_{0};
   // Config buffer for reading from the post thread.
-  DvrVrFlingerConfig post_thread_config_;
+  DvrConfig post_thread_config_;
   std::mutex shared_config_mutex_;
 
   static constexpr int kPostThreadInterrupted = 1;
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index bff80cd..4e275db 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -111,6 +111,7 @@
         "EGL/Loader.cpp",
         "EGL/BlobCache.cpp",
     ],
+    shared_libs: ["libvndksupport"],
     static_libs: ["libEGL_getProcAddress"],
     ldflags: ["-Wl,--exclude-libs=ALL"],
     export_include_dirs: ["EGL/include"],
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 1116400..6e5c510 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -29,6 +29,7 @@
 #include <log/log.h>
 
 #include <graphicsenv/GraphicsEnv.h>
+#include <vndksupport/linker.h>
 
 #include "egl_trace.h"
 #include "egldefs.h"
@@ -115,6 +116,11 @@
     return android_dlopen_ext(path, mode, info);
 }
 
+static void* do_android_load_sphal_library(const char* path, int mode) {
+    ATRACE_CALL();
+    return android_load_sphal_library(path, mode);
+}
+
 // ----------------------------------------------------------------------------
 
 Loader::driver_t::driver_t(void* gles)
@@ -424,27 +430,11 @@
     const char* const driver_absolute_path = absolutePath.c_str();
 
     // Try to load drivers from the 'sphal' namespace, if it exist. Fall back to
-    // the original routine when the namespace does not exist or the load from
-    // the namespace fails.
+    // the original routine when the namespace does not exist.
     // See /system/core/rootdir/etc/ld.config.txt for the configuration of the
     // sphal namespace.
-    android_namespace_t* sphal_namespace = android_get_exported_namespace("sphal");
-    if (sphal_namespace != NULL) {
-        const android_dlextinfo dlextinfo = {
-            .flags = ANDROID_DLEXT_USE_NAMESPACE,
-            .library_namespace = sphal_namespace,
-        };
-        void* dso = do_android_dlopen_ext(driver_absolute_path, RTLD_LOCAL | RTLD_NOW, &dlextinfo);
-        if (dso) {
-            ALOGD("loaded %s from sphal namespace", driver_absolute_path);
-            return dso;
-        }
-        else {
-            ALOGW("failed to load %s from sphal namespace: %s", driver_absolute_path, dlerror());
-        }
-    }
-
-    void* dso = do_dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
+    void* dso = do_android_load_sphal_library(driver_absolute_path,
+                                              RTLD_NOW | RTLD_LOCAL);
     if (dso == 0) {
         const char* err = dlerror();
         ALOGE("load_driver(%s): %s", driver_absolute_path, err ? err : "unknown");
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 6bff38a..835e72b 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -897,19 +897,15 @@
             egl_tls_t::setContext(EGL_NO_CONTEXT);
         }
     } else {
-        // Force return to current context for drivers that cannot handle errors
-        EGLBoolean restore_result = EGL_FALSE;
 
-        // get a reference to the old current objects
-        ContextRef _c2(dp.get(), cur_c);
-        SurfaceRef _d2(dp.get(), cur_c->draw);
-        SurfaceRef _r2(dp.get(), cur_c->read);
+        if (cur_c != NULL) {
+            // Force return to current context for drivers that cannot handle errors
+            EGLBoolean restore_result = EGL_FALSE;
+            // get a reference to the old current objects
+            ContextRef _c2(dp.get(), cur_c);
+            SurfaceRef _d2(dp.get(), cur_c->draw);
+            SurfaceRef _r2(dp.get(), cur_c->read);
 
-        if (cur_c == NULL) {
-            restore_result = dp->makeCurrent(c, cur_c,
-                    EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT,
-                    EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-        } else {
             c = cur_c;
             impl_ctx = c->context;
             impl_draw = EGL_NO_SURFACE;
@@ -925,13 +921,13 @@
             restore_result = dp->makeCurrent(c, cur_c,
                     cur_c->draw, cur_c->read, cur_c->context,
                     impl_draw, impl_read, impl_ctx);
-        }
-        if (restore_result == EGL_TRUE) {
-            _c2.acquire();
-            _r2.acquire();
-            _d2.acquire();
-        } else {
-            ALOGE("Could not restore original EGL context");
+            if (restore_result == EGL_TRUE) {
+                _c2.acquire();
+                _r2.acquire();
+                _d2.acquire();
+            } else {
+                ALOGE("Could not restore original EGL context");
+            }
         }
         // this will ALOGE the error
         egl_connection_t* const cnx = &gEGLImpl;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 0366630..263ff00 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -856,6 +856,10 @@
 
 Error Layer::setDataspace(android_dataspace_t dataspace)
 {
+    if (dataspace == mDataSpace) {
+        return Error::None;
+    }
+    mDataSpace = dataspace;
     auto intDataspace = static_cast<Hwc2::Dataspace>(dataspace);
     auto intError = mDevice.mComposer->setLayerDataspace(mDisplayId,
             mId, intDataspace);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 97582a7..15a43df 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -326,6 +326,7 @@
     hwc2_display_t mDisplayId;
     Device& mDevice;
     hwc2_layer_t mId;
+    android_dataspace mDataSpace = HAL_DATASPACE_UNKNOWN;
 };
 
 } // namespace HWC2
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 6e843d9..c129ae5 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -16,6 +16,9 @@
 
 // #define LOG_NDEBUG 0
 #include "VirtualDisplaySurface.h"
+
+#include <inttypes.h>
+
 #include "HWComposer.h"
 #include "SurfaceFlinger.h"
 
@@ -339,7 +342,7 @@
 }
 
 status_t VirtualDisplaySurface::dequeueBuffer(Source source,
-        PixelFormat format, uint32_t usage, int* sslot, sp<Fence>* fence) {
+        PixelFormat format, uint64_t usage, int* sslot, sp<Fence>* fence) {
     LOG_FATAL_IF(mDisplayId < 0, "mDisplayId=%d but should not be < 0.", mDisplayId);
 
     status_t result = mSource[source]->dequeueBuffer(sslot, fence,
@@ -372,7 +375,7 @@
             mSource[source]->cancelBuffer(*sslot, *fence);
             return result;
         }
-        VDS_LOGV("dequeueBuffer(%s): buffers[%d]=%p fmt=%d usage=%#x",
+        VDS_LOGV("dequeueBuffer(%s): buffers[%d]=%p fmt=%d usage=%#" PRIx64,
                 dbgSourceStr(source), pslot, mProducerBuffers[pslot].get(),
                 mProducerBuffers[pslot]->getPixelFormat(),
                 mProducerBuffers[pslot]->getUsage());
@@ -382,7 +385,7 @@
 }
 
 status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence,
-        uint32_t w, uint32_t h, PixelFormat format, uint32_t usage,
+        uint32_t w, uint32_t h, PixelFormat format, uint64_t usage,
         FrameEventHistoryDelta* outTimestamps) {
     if (mDisplayId < 0) {
         return mSource[SOURCE_SINK]->dequeueBuffer(
@@ -393,7 +396,7 @@
             "Unexpected dequeueBuffer() in %s state", dbgStateStr());
     mDbgState = DBG_STATE_GLES;
 
-    VDS_LOGV("dequeueBuffer %dx%d fmt=%d usage=%#x", w, h, format, usage);
+    VDS_LOGV("dequeueBuffer %dx%d fmt=%d usage=%#" PRIx64, w, h, format, usage);
 
     status_t result = NO_ERROR;
     Source source = fbSourceForCompositionType(mCompositionType);
@@ -423,8 +426,8 @@
                 (w != 0 && w != mSinkBufferWidth) ||
                 (h != 0 && h != mSinkBufferHeight)) {
             VDS_LOGV("dequeueBuffer: dequeueing new output buffer: "
-                    "want %dx%d fmt=%d use=%#x, "
-                    "have %dx%d fmt=%d use=%#x",
+                    "want %dx%d fmt=%d use=%#" PRIx64 ", "
+                    "have %dx%d fmt=%d use=%#" PRIx64,
                     w, h, format, usage,
                     mSinkBufferWidth, mSinkBufferHeight,
                     buf->getPixelFormat(), buf->getUsage());
@@ -575,7 +578,7 @@
 }
 
 void VirtualDisplaySurface::allocateBuffers(uint32_t /* width */,
-        uint32_t /* height */, PixelFormat /* format */, uint32_t /* usage */) {
+        uint32_t /* height */, PixelFormat /* format */, uint64_t /* usage */) {
     // TODO: Should we actually allocate buffers for a virtual display?
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 5c0e084..7f8b39b 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -105,7 +105,7 @@
     virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
     virtual status_t setAsyncMode(bool async);
     virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, uint32_t w,
-            uint32_t h, PixelFormat format, uint32_t usage,
+            uint32_t h, PixelFormat format, uint64_t usage,
             FrameEventHistoryDelta *outTimestamps);
     virtual status_t detachBuffer(int slot);
     virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
@@ -120,7 +120,7 @@
     virtual status_t disconnect(int api, DisconnectMode mode);
     virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
     virtual void allocateBuffers(uint32_t width, uint32_t height,
-            PixelFormat format, uint32_t usage);
+            PixelFormat format, uint64_t usage);
     virtual status_t allowAllocation(bool allow);
     virtual status_t setGenerationNumber(uint32_t generationNumber);
     virtual String8 getConsumerName() const override;
@@ -135,7 +135,7 @@
     // Utility methods
     //
     static Source fbSourceForCompositionType(CompositionType type);
-    status_t dequeueBuffer(Source source, PixelFormat format, uint32_t usage,
+    status_t dequeueBuffer(Source source, PixelFormat format, uint64_t usage,
             int* sslot, sp<Fence>* fence);
     void updateQueueBufferOutput(QueueBufferOutput&& qbo);
     void resetPerFrameState();
@@ -168,7 +168,7 @@
     // the composition type changes or the GLES driver starts requesting
     // different usage/format, we'll get a new buffer.
     uint32_t mOutputFormat;
-    uint32_t mOutputUsage;
+    uint64_t mOutputUsage;
 
     // Since we present a single producer interface to the GLES driver, but
     // are internally muxing between the sink and scratch producers, we have
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index d19f964..9e139f2 100755
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2531,6 +2531,14 @@
     return mSurfaceFlingerConsumer->getTransformToDisplayInverse();
 }
 
+size_t Layer::getChildrenCount() const {
+    size_t count = 0;
+    for (const sp<Layer>& child : mCurrentChildren) {
+        count += 1 + child->getChildrenCount();
+    }
+    return count;
+}
+
 void Layer::addChild(const sp<Layer>& layer) {
     mCurrentChildren.add(layer);
     layer->setParent(this);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index c9ebf99..6955d73 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -518,6 +518,7 @@
                                  const LayerVector::Visitor& visitor);
     void traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor);
 
+    size_t getChildrenCount() const;
     void addChild(const sp<Layer>& layer);
     // Returns index if removed, or negative value otherwise
     // for symmetry with Vector::remove
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index 2ba1b33..e717632 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -69,7 +69,7 @@
 }
 
 status_t MonitoredProducer::dequeueBuffer(int* slot, sp<Fence>* fence,
-        uint32_t w, uint32_t h, PixelFormat format, uint32_t usage,
+        uint32_t w, uint32_t h, PixelFormat format, uint64_t usage,
         FrameEventHistoryDelta* outTimestamps) {
     return mProducer->dequeueBuffer(
             slot, fence, w, h, format, usage, outTimestamps);
@@ -116,7 +116,7 @@
 }
 
 void MonitoredProducer::allocateBuffers(uint32_t width, uint32_t height,
-        PixelFormat format, uint32_t usage) {
+        PixelFormat format, uint64_t usage) {
     mProducer->allocateBuffers(width, height, format, usage);
 }
 
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index a3ec29d..58b9bc4 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -40,7 +40,7 @@
     virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
     virtual status_t setAsyncMode(bool async);
     virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
-            uint32_t h, PixelFormat format, uint32_t usage,
+            uint32_t h, PixelFormat format, uint64_t usage,
             FrameEventHistoryDelta* outTimestamps);
     virtual status_t detachBuffer(int slot);
     virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
@@ -56,7 +56,7 @@
     virtual status_t disconnect(int api, DisconnectMode mode);
     virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
     virtual void allocateBuffers(uint32_t width, uint32_t height,
-            PixelFormat format, uint32_t usage);
+            PixelFormat format, uint64_t usage);
     virtual status_t allowAllocation(bool allow);
     virtual status_t setGenerationNumber(uint32_t generationNumber);
     virtual String8 getConsumerName() const override;
diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp
index 0dab872..effd319 100644
--- a/services/surfaceflinger/RenderEngine/Description.cpp
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -26,8 +26,7 @@
 
 namespace android {
 
-Description::Description() :
-    mUniformsDirty(true) {
+Description::Description() {
     mPlaneAlpha = 1.0f;
     mPremultipliedAlpha = false;
     mOpaque = true;
@@ -41,28 +40,20 @@
 }
 
 void Description::setPlaneAlpha(GLclampf planeAlpha) {
-    if (planeAlpha != mPlaneAlpha) {
-        mUniformsDirty = true;
-        mPlaneAlpha = planeAlpha;
-    }
+    mPlaneAlpha = planeAlpha;
 }
 
 void Description::setPremultipliedAlpha(bool premultipliedAlpha) {
-    if (premultipliedAlpha != mPremultipliedAlpha) {
-        mPremultipliedAlpha = premultipliedAlpha;
-    }
+    mPremultipliedAlpha = premultipliedAlpha;
 }
 
 void Description::setOpaque(bool opaque) {
-    if (opaque != mOpaque) {
-        mOpaque = opaque;
-    }
+    mOpaque = opaque;
 }
 
 void Description::setTexture(const Texture& texture) {
     mTexture = texture;
     mTextureEnabled = true;
-    mUniformsDirty = true;
 }
 
 void Description::disableTexture() {
@@ -74,12 +65,10 @@
     mColor[1] = green;
     mColor[2] = blue;
     mColor[3] = alpha;
-    mUniformsDirty = true;
 }
 
 void Description::setProjectionMatrix(const mat4& mtx) {
     mProjectionMatrix = mtx;
-    mUniformsDirty = true;
 }
 
 void Description::setColorMatrix(const mat4& mtx) {
@@ -92,5 +81,8 @@
     return mColorMatrix;
 }
 
+void Description::setWideGamut(bool wideGamut) {
+    mIsWideGamut = wideGamut;
+}
 
 } /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h
index 8a3447c..3beffdf 100644
--- a/services/surfaceflinger/RenderEngine/Description.h
+++ b/services/surfaceflinger/RenderEngine/Description.h
@@ -54,6 +54,8 @@
     bool mColorMatrixEnabled;
     mat4 mColorMatrix;
 
+    bool mIsWideGamut;
+
 public:
     Description();
     ~Description();
@@ -67,9 +69,7 @@
     void setProjectionMatrix(const mat4& mtx);
     void setColorMatrix(const mat4& mtx);
     const mat4& getColorMatrix() const;
-
-private:
-    bool mUniformsDirty;
+    void setWideGamut(bool wideGamut);
 };
 
 } /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 18b2e1b..37a530b 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -40,9 +40,7 @@
 #include "Mesh.h"
 #include "Texture.h"
 
-#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
-#include <configstore/Utils.h>
-
+#include <sstream>
 #include <fstream>
 
 // ---------------------------------------------------------------------------
@@ -111,8 +109,10 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-GLES20RenderEngine::GLES20RenderEngine() :
-        mVpWidth(0), mVpHeight(0) {
+GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags) :
+         mVpWidth(0),
+         mVpHeight(0),
+         mPlatformHasWideColor((featureFlags & WIDE_COLOR_SUPPORT) != 0) {
 
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
     glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
@@ -133,23 +133,16 @@
     //mColorBlindnessCorrection = M;
 
 #ifdef USE_HWC2
-    // retrieve wide-color and hdr settings from configstore
-    using namespace android::hardware::configstore;
-    using namespace android::hardware::configstore::V1_0;
-
-    mPlatformHasWideColor =
-            getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
     if (mPlatformHasWideColor) {
         // Compute sRGB to DisplayP3 color transform
         // NOTE: For now, we are limiting wide-color support to
         // Display-P3 only.
         mat3 srgbToP3 = ColorSpaceConnector(ColorSpace::sRGB(), ColorSpace::DisplayP3()).getTransform();
 
-        // color transform needs to be transposed and expanded to 4x4
-        // to be what the shader wants
+        // color transform needs to be expanded to 4x4 to be what the shader wants
         // mat has an initializer that expands mat3 to mat4, but
         // not an assignment operator
-        mat4 gamutTransform(transpose(srgbToP3));
+        mat4 gamutTransform(srgbToP3);
         mSrgbToDisplayP3 = gamutTransform;
     }
 #endif
@@ -392,6 +385,7 @@
         Description wideColorState = mState;
         if (mDataSpace != HAL_DATASPACE_DISPLAY_P3) {
             wideColorState.setColorMatrix(mState.getColorMatrix() * mSrgbToDisplayP3);
+            wideColorState.setWideGamut(true);
             ALOGV("drawMesh: gamut transform applied");
         }
         ProgramCache::getInstance().useProgram(wideColorState);
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index 19cbb60..eaf94af 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -59,7 +59,7 @@
     virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName);
 
 public:
-    GLES20RenderEngine();
+    GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag
 
 protected:
     virtual ~GLES20RenderEngine();
@@ -86,7 +86,6 @@
     android_dataspace mDataSpace = HAL_DATASPACE_V0_SRGB;
 
     // Indicate if wide-color mode is needed or not
-    bool mPlatformHasWideColor = false;
     bool mDisplayHasWideColor = false;
     bool mUseWideColor = false;
     uint64_t mWideColorFrameCount = 0;
@@ -98,6 +97,8 @@
             int alpha);
     virtual void setupDimLayerBlending(int alpha);
 #endif
+    bool mPlatformHasWideColor = false;
+
     virtual void setupLayerTexturing(const Texture& texture);
     virtual void setupLayerBlackedOut();
     virtual void setupFillWithColor(float r, float g, float b, float a);
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index ba11259..06b2252 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -129,7 +129,9 @@
     .set(Key::OPACITY_MASK,
             description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT)
     .set(Key::COLOR_MATRIX_MASK,
-            description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON :  Key::COLOR_MATRIX_OFF);
+            description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON :  Key::COLOR_MATRIX_OFF)
+    .set(Key::WIDE_GAMUT_MASK,
+            description.mIsWideGamut ? Key::WIDE_GAMUT_ON : Key::WIDE_GAMUT_OFF);
     return needs;
 }
 
@@ -175,6 +177,50 @@
     if (needs.hasColorMatrix()) {
         fs << "uniform mat4 colorMatrix;";
     }
+    if (needs.hasColorMatrix()) {
+        // When in wide gamut mode, the color matrix will contain a color space
+        // conversion matrix that needs to be applied in linear space
+        // When not in wide gamut, we can simply no-op the transfer functions
+        // and let the shader compiler get rid of them
+        if (needs.isWideGamut()) {
+            fs << R"__SHADER__(
+                  float OETF_sRGB(const float linear) {
+                      return linear <= 0.0031308 ?
+                              linear * 12.92 : (pow(linear, 1.0 / 2.4) * 1.055) - 0.055;
+                  }
+
+                  vec3 OETF_sRGB(const vec3 linear) {
+                      return vec3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
+                  }
+
+                  vec3 OETF_scRGB(const vec3 linear) {
+                      return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb));
+                  }
+
+                  float EOTF_sRGB(float srgb) {
+                      return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4);
+                  }
+
+                  vec3 EOTF_sRGB(const vec3 srgb) {
+                      return vec3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b));
+                  }
+
+                  vec3 EOTF_scRGB(const vec3 srgb) {
+                      return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb));
+                  }
+            )__SHADER__";
+        } else {
+            fs << R"__SHADER__(
+                  vec3 OETF_scRGB(const vec3 linear) {
+                      return linear;
+                  }
+
+                  vec3 EOTF_scRGB(const vec3 srgb) {
+                      return srgb;
+                  }
+            )__SHADER__";
+        }
+    }
     fs << "void main(void) {" << indent;
     if (needs.isTexturing()) {
         fs << "gl_FragColor = texture2D(sampler, outTexCoords);";
@@ -197,13 +243,15 @@
     if (needs.hasColorMatrix()) {
         if (!needs.isOpaque() && needs.isPremultiplied()) {
             // un-premultiply if needed before linearization
-            fs << "gl_FragColor.rgb = gl_FragColor.rgb/gl_FragColor.a;";
+            // avoid divide by 0 by adding 0.5/256 to the alpha channel
+            fs << "gl_FragColor.rgb = gl_FragColor.rgb / (gl_FragColor.a + 0.0019);";
         }
-        fs << "vec4 transformed = colorMatrix * vec4(gl_FragColor.rgb, 1);";
-        fs << "gl_FragColor.rgb = transformed.rgb/transformed.a;";
+        fs << "vec4 transformed = colorMatrix * vec4(EOTF_scRGB(gl_FragColor.rgb), 1);";
+        // We assume the last row is always {0,0,0,1} and we skip the division by w
+        fs << "gl_FragColor.rgb = OETF_scRGB(transformed.rgb);";
         if (!needs.isOpaque() && needs.isPremultiplied()) {
             // and re-premultiply if needed after gamma correction
-            fs << "gl_FragColor.rgb = gl_FragColor.rgb*gl_FragColor.a;";
+            fs << "gl_FragColor.rgb = gl_FragColor.rgb * (gl_FragColor.a + 0.0019);";
         }
     }
 
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/ProgramCache.h
index 1fa53d3..5b0fbcd 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.h
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.h
@@ -69,6 +69,10 @@
             COLOR_MATRIX_OFF        =       0x00000000,
             COLOR_MATRIX_ON         =       0x00000020,
             COLOR_MATRIX_MASK       =       0x00000020,
+
+            WIDE_GAMUT_OFF          =       0x00000000,
+            WIDE_GAMUT_ON           =       0x00000040,
+            WIDE_GAMUT_MASK         =       0x00000040,
         };
 
         inline Key() : mKey(0) { }
@@ -97,10 +101,13 @@
         inline bool hasColorMatrix() const {
             return (mKey & COLOR_MATRIX_MASK) == COLOR_MATRIX_ON;
         }
+        inline bool isWideGamut() const {
+            return (mKey & WIDE_GAMUT_MASK) == WIDE_GAMUT_ON;
+        }
 
         // this is the definition of a friend function -- not a method of class Needs
         friend inline int strictly_order_type(const Key& lhs, const Key& rhs) {
-            return  (lhs.mKey < rhs.mKey) ? 1 : 0;
+            return (lhs.mKey < rhs.mKey) ? 1 : 0;
         }
     };
 
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index f8785db..ac2d8b2 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -47,7 +47,7 @@
     return false;
 }
 
-RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) {
+RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat, uint32_t featureFlags) {
     // EGL_ANDROIDX_no_config_context is an experimental extension with no
     // written specification. It will be replaced by something more formal.
     // SurfaceFlinger is using it to allow a single EGLContext to render to
@@ -135,7 +135,7 @@
         break;
     case GLES_VERSION_2_0:
     case GLES_VERSION_3_0:
-        engine = new GLES20RenderEngine();
+        engine = new GLES20RenderEngine(featureFlags);
         break;
     }
     engine->setEGLHandles(config, ctxt);
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 8b031bc..56f5827 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -59,7 +59,10 @@
     virtual ~RenderEngine() = 0;
 
 public:
-    static RenderEngine* create(EGLDisplay display, int hwcFormat);
+    enum FeatureFlag {
+        WIDE_COLOR_SUPPORT = 1 << 0 // Platform has a wide color display
+    };
+    static RenderEngine* create(EGLDisplay display, int hwcFormat, uint32_t featureFlags);
 
     static EGLConfig chooseEglConfig(EGLDisplay display, int format);
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 12afdf7..edc0140 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -19,6 +19,7 @@
 
 #include <stdint.h>
 #include <sys/types.h>
+#include <algorithm>
 #include <errno.h>
 #include <math.h>
 #include <mutex>
@@ -560,7 +561,8 @@
 
         // Get a RenderEngine for the given display / config (can't fail)
         mRenderEngine = RenderEngine::create(mEGLDisplay,
-                HAL_PIXEL_FORMAT_RGBA_8888);
+                HAL_PIXEL_FORMAT_RGBA_8888,
+                hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0);
     }
 
     // Drop the state lock while we initialize the hardware composer. We drop
@@ -1674,9 +1676,25 @@
     }
 }
 
+mat4 SurfaceFlinger::computeSaturationMatrix() const {
+    if (mSaturation == 1.0f) {
+        return mat4();
+    }
+
+    // Rec.709 luma coefficients
+    float3 luminance{0.213f, 0.715f, 0.072f};
+    luminance *= 1.0f - mSaturation;
+    return mat4(
+        vec4{luminance.r + mSaturation, luminance.r, luminance.r, 0.0f},
+        vec4{luminance.g, luminance.g + mSaturation, luminance.g, 0.0f},
+        vec4{luminance.b, luminance.b, luminance.b + mSaturation, 0.0f},
+        vec4{0.0f, 0.0f, 0.0f, 1.0f}
+    );
+}
+
 // pickColorMode translates a given dataspace into the best available color mode.
 // Currently only support sRGB and Display-P3.
-android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) {
+android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) const {
     switch (dataSpace) {
         // treat Unknown as regular SRGB buffer, since that's what the rest of the
         // system expects.
@@ -1699,11 +1717,19 @@
     }
 }
 
-android_dataspace SurfaceFlinger::bestTargetDataSpace(android_dataspace a, android_dataspace b) {
+android_dataspace SurfaceFlinger::bestTargetDataSpace(
+        android_dataspace a, android_dataspace b) const {
     // Only support sRGB and Display-P3 right now.
     if (a == HAL_DATASPACE_DISPLAY_P3 || b == HAL_DATASPACE_DISPLAY_P3) {
         return HAL_DATASPACE_DISPLAY_P3;
     }
+    if (a == HAL_DATASPACE_V0_SCRGB_LINEAR || b == HAL_DATASPACE_V0_SCRGB_LINEAR) {
+        return HAL_DATASPACE_DISPLAY_P3;
+    }
+    if (a == HAL_DATASPACE_V0_SCRGB || b == HAL_DATASPACE_V0_SCRGB) {
+        return HAL_DATASPACE_DISPLAY_P3;
+    }
+
     return HAL_DATASPACE_V0_SRGB;
 }
 
@@ -1771,7 +1797,7 @@
     }
 
 
-    mat4 colorMatrix = mColorMatrix * mDaltonizer();
+    mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer();
 
     // Set the per-frame data
     for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
@@ -2507,8 +2533,8 @@
         ALOGV("hasClientComposition");
 
 #ifdef USE_HWC2
-        mRenderEngine->setColorMode(displayDevice->getActiveColorMode());
         mRenderEngine->setWideColor(displayDevice->getWideColorSupport());
+        mRenderEngine->setColorMode(displayDevice->getActiveColorMode());
 #endif
         if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) {
             ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
@@ -2658,8 +2684,13 @@
         if (parent == nullptr) {
             mCurrentState.layersSortedByZ.add(lbc);
         } else {
+            if (mCurrentState.layersSortedByZ.indexOf(parent) < 0) {
+                ALOGE("addClientLayer called with a removed parent");
+                return NAME_NOT_FOUND;
+            }
             parent->addChild(lbc);
         }
+
         mGraphicBufferProducerList.add(IInterface::asBinder(gbc));
         mLayersAdded = true;
         mNumLayers++;
@@ -2678,6 +2709,17 @@
     const ssize_t index = (p != nullptr) ? p->removeChild(layer) :
         mCurrentState.layersSortedByZ.remove(layer);
 
+    if (p != nullptr) {
+        sp<Layer> ancestor = p;
+        while (ancestor->getParent() != nullptr) {
+            ancestor = ancestor->getParent();
+        }
+        if (mCurrentState.layersSortedByZ.indexOf(ancestor) < 0) {
+            ALOGE("removeLayer called with a layer whose parent has been removed");
+            return NAME_NOT_FOUND;
+        }
+    }
+
     // As a matter of normal operation, the LayerCleaner will produce a second
     // attempt to remove the surface. The Layer will be kept alive in mDrawingState
     // so we will succeed in promoting it, but it's already been removed
@@ -2694,7 +2736,7 @@
 
     mLayersPendingRemoval.add(layer);
     mLayersRemoved = true;
-    mNumLayers--;
+    mNumLayers -= 1 + layer->getChildrenCount();
     setTransactionFlags(eTransactionNeeded);
     return NO_ERROR;
 }
@@ -3892,9 +3934,7 @@
                 // apply a color matrix
                 n = data.readInt32();
                 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
+                    // color matrix is sent as a column-major mat4 matrix
                     for (size_t i = 0 ; i < 4; i++) {
                         for (size_t j = 0; j < 4; j++) {
                             mColorMatrix[i][j] = data.readFloat();
@@ -3903,6 +3943,14 @@
                 } else {
                     mColorMatrix = mat4();
                 }
+
+                // Check that supplied matrix's last row is {0,0,0,1} so we can avoid
+                // the division by w in the fragment shader
+                float4 lastRow(transpose(mColorMatrix)[3]);
+                if (any(greaterThan(abs(lastRow - float4{0, 0, 0, 1}), float4{1e-4f}))) {
+                    ALOGE("The color transform's last row must be (0, 0, 0, 1)");
+                }
+
                 invalidateHwcGeometry();
                 repaintEverything();
                 return NO_ERROR;
@@ -3946,6 +3994,13 @@
                 mUseHwcVirtualDisplays = !n;
                 return NO_ERROR;
             }
+            case 1022: { // Set saturation boost
+                mSaturation = std::max(0.0f, std::min(data.readFloat(), 2.0f));
+
+                invalidateHwcGeometry();
+                repaintEverything();
+                return NO_ERROR;
+            }
         }
     }
     return err;
@@ -4209,6 +4264,11 @@
         ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, hw_h);
     }
 
+#ifdef USE_HWC2
+     engine.setWideColor(hw->getWideColorSupport());
+     engine.setColorMode(hw->getActiveColorMode());
+#endif
+
     // make sure to clear all GL error flags
     engine.checkErrors();
 
@@ -4338,6 +4398,14 @@
                             hw, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, true,
                             useIdentityTransform, rotation);
 
+#ifdef USE_HWC2
+                        if (hasWideColorDisplay) {
+                            native_window_set_buffers_data_space(window,
+                                getRenderEngine().usesWideColor() ?
+                                    HAL_DATASPACE_DISPLAY_P3 : HAL_DATASPACE_V0_SRGB);
+                        }
+#endif
+
                         // Attempt to create a sync khr object that can produce a sync point. If that
                         // isn't available, create a non-dupable sync object in the fallback path and
                         // wait on it directly.
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 1bc689d..68a088a 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -511,8 +511,10 @@
 
     // Given a dataSpace, returns the appropriate color_mode to use
     // to display that dataSpace.
-    android_color_mode pickColorMode(android_dataspace dataSpace);
-    android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b);
+    android_color_mode pickColorMode(android_dataspace dataSpace) const;
+    android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b) const;
+
+    mat4 computeSaturationMatrix() const;
 
     void setUpHWComposer();
     void doComposition();
@@ -747,7 +749,9 @@
     std::atomic<bool> mVrFlingerRequestsDisplay;
     static bool useVrFlinger;
 #endif
-    };
+
+    float mSaturation = 1.0f;
+};
 }; // namespace android
 
 #endif // ANDROID_SURFACE_FLINGER_H
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index f6ee660..0b3a0d0 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -536,7 +536,8 @@
             *static_cast<HWComposer::EventHandler *>(this));
 
     // get a RenderEngine for the given display / config (can't fail)
-    mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());
+    mRenderEngine = RenderEngine::create(mEGLDisplay,
+            mHwc->getVisualID(), 0);
 
     // retrieve the EGL context that was selected/created
     mEGLContext = mRenderEngine->getEGLContext();
diff --git a/services/vr/virtual_touchpad/Android.bp b/services/vr/virtual_touchpad/Android.bp
index 3d5dfb2..b9aa8fe 100644
--- a/services/vr/virtual_touchpad/Android.bp
+++ b/services/vr/virtual_touchpad/Android.bp
@@ -13,10 +13,15 @@
     "libutils",
 ]
 
+header_libraries = [
+    "libdvr_headers"
+]
+
 cc_library {
     srcs: src,
     export_include_dirs: ["include"],
     shared_libs: shared_libs,
+    header_libs: header_libraries,
     cppflags: ["-std=c++11"],
     cflags: ["-DLOG_TAG=\"VrVirtualTouchpad\""],
     name: "libvirtualtouchpad",
@@ -42,6 +47,7 @@
     srcs: test_src_files,
     static_libs: test_static_libs,
     shared_libs: test_shared_libs,
+    header_libs: header_libraries,
     cppflags = [
         "-std=c++11",
     ],
@@ -77,6 +83,7 @@
     srcs: service_src,
     static_libs: service_static_libs,
     shared_libs: service_shared_libs,
+    header_libs: header_libraries,
     cppflags: ["-std=c++11"],
     cflags: [
         "-DLOG_TAG=\"VrVirtualTouchpad\"",
@@ -107,6 +114,7 @@
 cc_library {
     srcs: client_src,
     shared_libs: client_shared_libs,
+    header_libs: header_libraries,
     cppflags: ["-std=c++11"],
     cflags: ["-DLOG_TAG=\"VirtualTouchpadClient\""],
     host_ldlibs: ["-llog"],
diff --git a/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-1.idc b/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-1.idc
new file mode 100644
index 0000000..3728ef0
--- /dev/null
+++ b/services/vr/virtual_touchpad/idc/vr-virtual-touchpad-1.idc
@@ -0,0 +1,24 @@
+# Copyright (C) 2017 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.
+
+#
+# Virtual touchpad for the VR virtual display
+device.internal = 1
+
+touch.deviceType = touchScreen
+
+# This displayID matches the unique ID of the virtual display created for VR.
+# This will indicate to input flinger than it should link this input device
+# with the virtual display.
+touch.displayId = virtual:android:277f1a09-b88d-4d1e-8716-796f114d080b
diff --git a/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h b/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
index 08cca1b..15e6687 100644
--- a/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
+++ b/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
@@ -1,17 +1,14 @@
 #ifndef ANDROID_DVR_VIRTUAL_TOUCHPAD_C_CLIENT_H
 #define ANDROID_DVR_VIRTUAL_TOUCHPAD_C_CLIENT_H
 
+#include <dvr/dvr_api.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 typedef struct DvrVirtualTouchpad DvrVirtualTouchpad;
 
-enum {
-  DVR_VIRTUAL_TOUCHPAD_PRIMARY = 0,
-  DVR_VIRTUAL_TOUCHPAD_VIRTUAL = 1,
-};
-
 // Creates a new virtual touchpad client.
 //
 // @return Pointer to the created virtual touchpad client; nullptr on failure.
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index cb893aa..ded9549 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1015,7 +1015,7 @@
             return VK_ERROR_SURFACE_LOST_KHR;
         }
     }
-    err = native_window_set_usage(surface.window.get(), gralloc_usage);
+    err = native_window_set_usage(surface.window.get(), uint64_t(gralloc_usage));
     if (err != 0) {
         // TODO(jessehall): Improve error reporting. Can we enumerate possible
         // errors and translate them to valid Vulkan result codes?
@@ -1092,7 +1092,7 @@
         image_native_buffer.handle = img.buffer->handle;
         image_native_buffer.stride = img.buffer->stride;
         image_native_buffer.format = img.buffer->format;
-        image_native_buffer.usage = img.buffer->usage;
+        image_native_buffer.usage = int(img.buffer->usage);
         // TODO: Adjust once ANativeWindowBuffer supports gralloc1-style usage.
         // For now, this is the same translation Gralloc1On0Adapter does.
         image_native_buffer.usage2.consumer =