Merge "installd create_data_user_ce_path uses dir instead of symlink"
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp
index c89e3b1..a2560e3 100644
--- a/cmds/atrace/Android.bp
+++ b/cmds/atrace/Android.bp
@@ -7,7 +7,6 @@
     shared_libs: [
         "libbinder",
         "libhwbinder",
-        "android.hidl.manager@1.0",
         "libhidlbase",
         "libhidltransport",
         "liblog",
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index acf63c3..add5285 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -26,7 +26,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/sendfile.h>
 #include <time.h>
 #include <unistd.h>
 #include <zlib.h>
@@ -974,11 +973,16 @@
             fprintf(stderr, "error cleaning up zlib: %d\n", result);
         }
     } else {
-        ssize_t sent = 0;
-        while ((sent = sendfile(outFd, traceFD, NULL, 64*1024*1024)) > 0);
-        if (sent == -1) {
-            fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno),
-                    errno);
+        char buf[4096];
+        ssize_t rc;
+        while ((rc = TEMP_FAILURE_RETRY(read(traceFD, buf, sizeof(buf)))) > 0) {
+            if (!android::base::WriteFully(outFd, buf, rc)) {
+                fprintf(stderr, "error writing trace: %s\n", strerror(errno));
+                break;
+            }
+        }
+        if (rc == -1) {
+            fprintf(stderr, "error dumping trace: %s\n", strerror(errno));
         }
     }
 
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index fc4977c..b6aacb5 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -6,7 +6,7 @@
 
 LOCAL_MODULE := dumpstate
 
-LOCAL_SHARED_LIBRARIES := libcutils libdebuggerd_client liblog libselinux libbase libhardware_legacy
+LOCAL_SHARED_LIBRARIES := libcutils libdebuggerd_client liblog libselinux libbase
 # ZipArchive support, the order matters here to get all symbols.
 LOCAL_STATIC_LIBRARIES := libziparchive libz libcrypto_static
 LOCAL_HAL_STATIC_LIBRARIES := libdumpstate
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index b1205fe..bb56984 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -23,7 +23,6 @@
 #include <memory>
 #include <regex>
 #include <set>
-#include <signal.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -36,11 +35,11 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
-#include <android-base/stringprintf.h>
-#include <android-base/unique_fd.h>
 #include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
 #include <cutils/properties.h>
-#include <hardware_legacy/power.h>
 
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
@@ -83,7 +82,6 @@
 #define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
 #define NUM_TOMBSTONES  10
 #define WLUTIL "/vendor/xbin/wlutil"
-#define WAKE_LOCK_NAME "dumpstate_wakelock"
 
 typedef struct {
   char name[TOMBSTONE_MAX_LEN];
@@ -152,7 +150,7 @@
 }
 
 void add_mountinfo() {
-    if (!zip_writer) return;
+    if (!is_zipping()) return;
     const char *title = "MOUNT INFO";
     mount_points.clear();
     DurationReporter duration_reporter(title, NULL);
@@ -313,8 +311,8 @@
 }
 
 static void dump_systrace() {
-    if (!zip_writer) {
-        MYLOGD("Not dumping systrace because zip_writer is not set\n");
+    if (!is_zipping()) {
+        MYLOGD("Not dumping systrace because dumpstate is not zipping\n");
         return;
     }
     std::string systrace_path = bugreport_dir + "/systrace-" + suffix + ".txt";
@@ -370,7 +368,7 @@
         return;
     }
 
-    if (!zip_writer) {
+    if (!is_zipping()) {
         // Write compressed and encoded raft logs to stdout if not zip_writer.
         run_command("RAFT LOGS", 600, "logcompressor", "-r", RAFT_DIR, NULL);
         return;
@@ -387,6 +385,83 @@
     }
 }
 
+/**
+ * Finds the last modified file in the directory dir whose name starts with file_prefix
+ * Function returns empty string when it does not find a file
+ */
+static std::string get_last_modified_file_matching_prefix(const std::string& dir,
+                                                          const std::string& file_prefix) {
+    std::unique_ptr<DIR, decltype(&closedir)> d(opendir(dir.c_str()), closedir);
+    if (d == nullptr) {
+        MYLOGD("Error %d opening %s\n", errno, dir.c_str());
+        return "";
+    }
+
+    // Find the newest file matching the file_prefix in dir
+    struct dirent *de;
+    time_t last_modified = 0;
+    std::string last_modified_file = "";
+    struct stat s;
+
+    while ((de = readdir(d.get()))) {
+        std::string file = std::string(de->d_name);
+        if (!file_prefix.empty()) {
+            if (!android::base::StartsWith(file, file_prefix.c_str())) continue;
+        }
+        file = dir + "/" + file;
+        int ret = stat(file.c_str(), &s);
+
+        if ((ret == 0) && (s.st_mtime > last_modified)) {
+            last_modified_file = file;
+            last_modified = s.st_mtime;
+        }
+    }
+
+    return last_modified_file;
+}
+
+void dump_modem_logs() {
+    DurationReporter duration_reporter("dump_modem_logs");
+    if (is_user_build()) {
+        return;
+    }
+
+    if (!is_zipping()) {
+        MYLOGD("Not dumping modem logs. dumpstate is not generating a zipping bugreport\n");
+        return;
+    }
+
+    char property[PROPERTY_VALUE_MAX];
+    property_get("ro.radio.log_prefix", property, "");
+    std::string file_prefix = std::string(property);
+    if(file_prefix.empty()) {
+        MYLOGD("No modem log : file_prefix is empty\n");
+        return;
+    }
+
+    MYLOGD("dump_modem_logs: directory is %s and file_prefix is %s\n",
+           bugreport_dir.c_str(), file_prefix.c_str());
+
+    std::string modem_log_file =
+        get_last_modified_file_matching_prefix(bugreport_dir, file_prefix);
+
+    struct stat s;
+    if (modem_log_file.empty() || stat(modem_log_file.c_str(), &s) != 0) {
+        MYLOGD("Modem log %s does not exist\n", modem_log_file.c_str());
+        return;
+    }
+
+    std::string filename = basename(modem_log_file.c_str());
+    if (!add_zip_entry(filename, modem_log_file)) {
+        MYLOGE("Unable to add modem log %s to zip file\n", modem_log_file.c_str());
+    } else {
+        MYLOGD("Modem Log %s is added to zip\n", modem_log_file.c_str());
+        if (remove(modem_log_file.c_str())) {
+            MYLOGE("Error removing modem log %s\n", modem_log_file.c_str());
+        }
+    }
+}
+
 static bool skip_not_stat(const char *path) {
     static const char stat[] = "/stat";
     size_t len = strlen(path);
@@ -620,8 +695,8 @@
 };
 
 bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
-    if (!zip_writer) {
-        MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n",
+    if (!is_zipping()) {
+        MYLOGD("Not adding entry %s from fd because dumpstate is not zipping\n",
                 entry_name.c_str());
         return false;
     }
@@ -691,8 +766,8 @@
 
 // TODO: move to util.cpp
 void add_dir(const char *dir, bool recursive) {
-    if (!zip_writer) {
-        MYLOGD("Not adding dir %s because zip_writer is not set\n", dir);
+    if (!is_zipping()) {
+        MYLOGD("Not adding dir %s because dumpstate is not zipping\n", dir);
         return;
     }
     MYLOGD("Adding dir %s (recursive: %d)\n", dir, recursive);
@@ -700,10 +775,14 @@
     dump_files(NULL, dir, recursive ? skip_none : is_dir, _add_file_from_fd);
 }
 
+bool is_zipping() {
+    return zip_writer != nullptr;
+}
+
 /* adds a text entry entry to the existing zip file. */
 static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) {
-    if (!zip_writer) {
-        MYLOGD("Not adding text zip entry %s because zip_writer is not set\n", entry_name.c_str());
+    if (!is_zipping()) {
+        MYLOGD("Not adding text entry %s because dumpstate is not zipping\n", entry_name.c_str());
         return false;
     }
     MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
@@ -741,9 +820,63 @@
     run_command("IP6TABLES RAW", 10, "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
 }
 
+static void do_kmsg() {
+    struct stat st;
+    if (!stat(PSTORE_LAST_KMSG, &st)) {
+        /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
+        dump_file("LAST KMSG", PSTORE_LAST_KMSG);
+    } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
+        dump_file("LAST KMSG", ALT_PSTORE_LAST_KMSG);
+    } else {
+        /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
+        dump_file("LAST KMSG", "/proc/last_kmsg");
+    }
+}
+
+static void do_logcat() {
+    unsigned long timeout;
+    // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
+    // calculate timeout
+    timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
+    if (timeout < 20000) {
+        timeout = 20000;
+    }
+    run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime",
+                                                        "-v", "printable",
+                                                        "-d",
+                                                        "*:v", NULL);
+    timeout = logcat_timeout("events");
+    if (timeout < 20000) {
+        timeout = 20000;
+    }
+    run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events",
+                                                       "-v", "threadtime",
+                                                       "-v", "printable",
+                                                       "-d",
+                                                       "*:v", NULL);
+    timeout = logcat_timeout("radio");
+    if (timeout < 20000) {
+        timeout = 20000;
+    }
+    run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio",
+                                                       "-v", "threadtime",
+                                                       "-v", "printable",
+                                                       "-d",
+                                                       "*:v", NULL);
+
+    run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
+
+    /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
+    run_command("LAST LOGCAT", 10, "logcat", "-L",
+                                             "-b", "all",
+                                             "-v", "threadtime",
+                                             "-v", "printable",
+                                             "-d",
+                                             "*:v", NULL);
+}
+
 static void dumpstate(const std::string& screenshot_path, const std::string& version) {
     DurationReporter duration_reporter("DUMPSTATE");
-    unsigned long timeout;
 
     dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
     run_command("UPTIME", 10, "uptime", NULL);
@@ -789,36 +922,7 @@
         MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
     }
 
-    // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
-    // calculate timeout
-    timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
-    if (timeout < 20000) {
-        timeout = 20000;
-    }
-    run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime",
-                                                        "-v", "printable",
-                                                        "-d",
-                                                        "*:v", NULL);
-    timeout = logcat_timeout("events");
-    if (timeout < 20000) {
-        timeout = 20000;
-    }
-    run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events",
-                                                       "-v", "threadtime",
-                                                       "-v", "printable",
-                                                       "-d",
-                                                       "*:v", NULL);
-    timeout = logcat_timeout("radio");
-    if (timeout < 20000) {
-        timeout = 20000;
-    }
-    run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio",
-                                                       "-v", "threadtime",
-                                                       "-v", "printable",
-                                                       "-d",
-                                                       "*:v", NULL);
-
-    run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
+    do_logcat();
 
     /* show the traces we collected in main(), if that was done */
     if (dump_traces_path != NULL) {
@@ -886,23 +990,7 @@
     dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
     dump_file("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
 
-    if (!stat(PSTORE_LAST_KMSG, &st)) {
-        /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
-        dump_file("LAST KMSG", PSTORE_LAST_KMSG);
-    } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
-        dump_file("LAST KMSG", ALT_PSTORE_LAST_KMSG);
-    } else {
-        /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
-        dump_file("LAST KMSG", "/proc/last_kmsg");
-    }
-
-    /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
-    run_command("LAST LOGCAT", 10, "logcat", "-L",
-                                             "-b", "all",
-                                             "-v", "threadtime",
-                                             "-v", "printable",
-                                             "-d",
-                                             "*:v", NULL);
+    do_kmsg();
 
     /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
 
@@ -1014,6 +1102,10 @@
 
     run_command("APP PROVIDERS", 30, "dumpsys", "-t", "30", "activity", "provider", "all", NULL);
 
+    // dump_modem_logs adds the modem logs if available to the bugreport.
+    // Do this at the end to allow for sufficient time for the modem logs to be
+    // collected.
+    dump_modem_logs();
 
     printf("========================================================\n");
     printf("== Final progress (pid %d): %d/%d (originally %d)\n",
@@ -1025,14 +1117,15 @@
 
 static void usage() {
   fprintf(stderr,
-          "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
-          "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
+          "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] [-t]"
+          "[-z] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
           "  -h: display this help message\n"
           "  -b: play sound file instead of vibrate, at beginning of job\n"
           "  -e: play sound file instead of vibrate, at end of job\n"
           "  -o: write to file (instead of stdout)\n"
           "  -d: append date to filename (requires -o)\n"
           "  -p: capture screenshot to filename.png (requires -o)\n"
+          "  -t: only captures telephony sections\n"
           "  -z: generate zipped file (requires -o)\n"
           "  -s: write output to control socket (for init)\n"
           "  -S: write file location to control socket (for init; requires -o and -z)"
@@ -1046,31 +1139,11 @@
           VERSION_DEFAULT.c_str());
 }
 
-static void wake_lock_releaser() {
-    if (release_wake_lock(WAKE_LOCK_NAME) < 0) {
-        MYLOGE("Failed to release wake lock: %s \n", strerror(errno));
-    } else {
-        MYLOGD("Wake lock released.\n");
-    }
-}
-
-static void sig_handler(int signo) {
-    wake_lock_releaser();
+static void sigpipe_handler(int n) {
+    // don't complain to stderr or stdout
     _exit(EXIT_FAILURE);
 }
 
-static void register_sig_handler() {
-    struct sigaction sa;
-    sigemptyset(&sa.sa_mask);
-    sa.sa_flags = 0;
-    sa.sa_handler = sig_handler;
-    sigaction(SIGPIPE, &sa, NULL); // broken pipe
-    sigaction(SIGSEGV, &sa, NULL); // segment fault
-    sigaction(SIGINT, &sa, NULL); // ctrl-c
-    sigaction(SIGTERM, &sa, NULL); // killed
-    sigaction(SIGQUIT, &sa, NULL); // quit
-}
-
 /* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
    temporary file.
  */
@@ -1139,6 +1212,7 @@
 }
 
 int main(int argc, char *argv[]) {
+    struct sigaction sigact;
     int do_add_date = 0;
     int do_zip_file = 0;
     int do_vibrate = 1;
@@ -1149,20 +1223,14 @@
     int do_broadcast = 0;
     int do_early_screenshot = 0;
     int is_remote_mode = 0;
+    bool telephony_only = false;
+
     std::string version = VERSION_DEFAULT;
 
     now = time(NULL);
 
     MYLOGI("begin\n");
 
-    if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
-        MYLOGE("Failed to acquire wake lock: %s \n", strerror(errno));
-    } else {
-        MYLOGD("Wake lock acquired.\n");
-        atexit(wake_lock_releaser);
-        register_sig_handler();
-    }
-
     /* gets the sequential id */
     char last_id[PROPERTY_VALUE_MAX];
     property_get("dumpstate.last_id", last_id, "0");
@@ -1171,6 +1239,11 @@
     property_set("dumpstate.last_id", last_id);
     MYLOGI("dumpstate id: %lu\n", id);
 
+    /* clear SIGPIPE handler */
+    memset(&sigact, 0, sizeof(sigact));
+    sigact.sa_handler = sigpipe_handler;
+    sigaction(SIGPIPE, &sigact, NULL);
+
     /* set as high priority, and protect from OOM killer */
     setpriority(PRIO_PROCESS, 0, -20);
 
@@ -1192,9 +1265,10 @@
     format_args(argc, const_cast<const char **>(argv), &args);
     MYLOGD("Dumpstate command line: %s\n", args.c_str());
     int c;
-    while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
+    while ((c = getopt(argc, argv, "dho:svqzptPBRSV:")) != -1) {
         switch (c) {
             case 'd': do_add_date = 1;          break;
+            case 't': telephony_only = true;    break;
             case 'z': do_zip_file = 1;          break;
             case 'o': use_outfile = optarg;     break;
             case 's': use_socket = 1;           break;
@@ -1291,6 +1365,9 @@
         char build_id[PROPERTY_VALUE_MAX];
         property_get("ro.build.id", build_id, "UNKNOWN_BUILD");
         base_name = base_name + "-" + build_id;
+        if (telephony_only) {
+            base_name = base_name + "-telephony";
+        }
         if (do_fb) {
             // TODO: if dumpstate was an object, the paths could be internal variables and then
             // we could have a function to calculate the derived values, such as:
@@ -1400,48 +1477,60 @@
     // duration is logged into MYLOG instead.
     print_header(version);
 
-    // Dumps systrace right away, otherwise it will be filled with unnecessary events.
-    // First try to dump anrd trace if the daemon is running. Otherwise, dump
-    // the raw trace.
-    if (!dump_anrd_trace()) {
-        dump_systrace();
+    if (telephony_only) {
+        dump_iptables();
+        if (!drop_root_user()) {
+            return -1;
+        }
+        do_dmesg();
+        do_logcat();
+        do_kmsg();
+        dumpstate_board();
+        dump_modem_logs();
+    } else {
+        // Dumps systrace right away, otherwise it will be filled with unnecessary events.
+        // First try to dump anrd trace if the daemon is running. Otherwise, dump
+        // the raw trace.
+        if (!dump_anrd_trace()) {
+            dump_systrace();
+        }
+
+        // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
+        dump_raft();
+
+        // Invoking the following dumpsys calls before dump_traces() to try and
+        // keep the system stats as close to its initial state as possible.
+        run_command_as_shell("DUMPSYS MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "-a", NULL);
+        run_command_as_shell("DUMPSYS CPUINFO", 10, "dumpsys", "-t", "10", "cpuinfo", "-a", NULL);
+
+        /* collect stack traces from Dalvik and native processes (needs root) */
+        dump_traces_path = dump_traces();
+
+        /* Run some operations that require root. */
+        get_tombstone_fds(tombstone_data);
+        add_dir(RECOVERY_DIR, true);
+        add_dir(RECOVERY_DATA_DIR, true);
+        add_dir(LOGPERSIST_DATA_DIR, false);
+        if (!is_user_build()) {
+            add_dir(PROFILE_DATA_DIR_CUR, true);
+            add_dir(PROFILE_DATA_DIR_REF, true);
+        }
+        add_mountinfo();
+        dump_iptables();
+
+        // Capture any IPSec policies in play.  No keys are exposed here.
+        run_command("IP XFRM POLICY", 10, "ip", "xfrm", "policy", nullptr);
+
+        // Run ss as root so we can see socket marks.
+        run_command("DETAILED SOCKET STATE", 10, "ss", "-eionptu", NULL);
+
+        if (!drop_root_user()) {
+            return -1;
+        }
+
+        dumpstate(do_early_screenshot ? "": screenshot_path, version);
     }
 
-    // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
-    dump_raft();
-
-    // Invoking the following dumpsys calls before dump_traces() to try and
-    // keep the system stats as close to its initial state as possible.
-    run_command_as_shell("DUMPSYS MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "-a", NULL);
-    run_command_as_shell("DUMPSYS CPUINFO", 10, "dumpsys", "-t", "10", "cpuinfo", "-a", NULL);
-
-    /* collect stack traces from Dalvik and native processes (needs root) */
-    dump_traces_path = dump_traces();
-
-    /* Run some operations that require root. */
-    get_tombstone_fds(tombstone_data);
-    add_dir(RECOVERY_DIR, true);
-    add_dir(RECOVERY_DATA_DIR, true);
-    add_dir(LOGPERSIST_DATA_DIR, false);
-    if (!is_user_build()) {
-        add_dir(PROFILE_DATA_DIR_CUR, true);
-        add_dir(PROFILE_DATA_DIR_REF, true);
-    }
-    add_mountinfo();
-    dump_iptables();
-
-    // Capture any IPSec policies in play.  No keys are exposed here.
-    run_command("IP XFRM POLICY", 10, "ip", "xfrm", "policy", nullptr);
-
-    // Run ss as root so we can see socket marks.
-    run_command("DETAILED SOCKET STATE", 10, "ss", "-eionptu", NULL);
-
-    if (!drop_root_user()) {
-        return -1;
-    }
-
-    dumpstate(do_early_screenshot ? "": screenshot_path, version);
-
     /* close output if needed */
     if (is_redirecting) {
         fclose(stdout);
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 5ed9023..0b6aaab 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -87,6 +87,9 @@
 /* root dir for all files copied as-is into the bugreport. */
 extern const std::string ZIP_ROOT_DIR;
 
+/* Checkes whether dumpstate is generating a zipped bugreport. */
+bool is_zipping();
+
 /* adds a new entry to the existing zip file. */
 bool add_zip_entry(const std::string& entry_name, const std::string& entry_path);
 
diff --git a/cmds/dumpstate/dumpstate.rc b/cmds/dumpstate/dumpstate.rc
index 3448e91..336db9f 100644
--- a/cmds/dumpstate/dumpstate.rc
+++ b/cmds/dumpstate/dumpstate.rc
@@ -46,3 +46,11 @@
     class main
     disabled
     oneshot
+
+# bugreportelefony is a lightweight version of bugreport that only includes a few, urgent
+# sections used to report telephony bugs.
+service bugreportelefony /system/bin/dumpstate -t -d -B -z \
+        -o /data/user_de/0/com.android.shell/files/bugreports/bugreport
+    class main
+    disabled
+    oneshot
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index bbe48be..6ec636e 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -829,8 +829,7 @@
     }
 
     gid_t groups[] = { AID_LOG, AID_SDCARD_R, AID_SDCARD_RW,
-            AID_MOUNT, AID_INET, AID_NET_BW_STATS, AID_READPROC, AID_WAKELOCK,
-            AID_BLUETOOTH };
+            AID_MOUNT, AID_INET, AID_NET_BW_STATS, AID_READPROC, AID_BLUETOOTH };
     if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
         MYLOGE("Unable to setgroups, aborting: %s\n", strerror(errno));
         return false;
@@ -851,10 +850,8 @@
     capheader.version = _LINUX_CAPABILITY_VERSION_3;
     capheader.pid = 0;
 
-    capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted =
-            (CAP_TO_MASK(CAP_SYSLOG) | CAP_TO_MASK(CAP_BLOCK_SUSPEND));
-    capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective =
-            (CAP_TO_MASK(CAP_SYSLOG) | CAP_TO_MASK(CAP_BLOCK_SUSPEND));
+    capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG);
+    capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective = CAP_TO_MASK(CAP_SYSLOG);
     capdata[0].inheritable = 0;
     capdata[1].inheritable = 0;
 
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index f7e8d13..5af8c5f 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -184,9 +184,20 @@
   return count;
 }
 
+static const char* get_location_from_path(const char* path) {
+    static constexpr char kLocationSeparator = '/';
+    const char *location = strrchr(path, kLocationSeparator);
+    if (location == NULL) {
+        return path;
+    } else {
+        // Skip the separator character.
+        return location + 1;
+    }
+}
+
 static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vdex_fd, int image_fd,
         const char* input_file_name, const char* output_file_name, int swap_fd,
-        const char *instruction_set, const char* compiler_filter, bool vm_safe_mode,
+        const char* instruction_set, const char* compiler_filter, bool vm_safe_mode,
         bool debuggable, bool post_bootcomplete, int profile_fd, const char* shared_libraries) {
     static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
 
@@ -196,6 +207,9 @@
         return;
     }
 
+    // Get the relative path to the input file.
+    const char* relative_input_file_name = get_location_from_path(input_file_name);
+
     char dex2oat_Xms_flag[kPropertyValueMax];
     bool have_dex2oat_Xms_flag = get_property("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0;
 
@@ -286,7 +300,7 @@
     char dex2oat_image_fd[arraysize("--app-image-fd=") + MAX_INT_LEN];
 
     sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
-    sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
+    sprintf(zip_location_arg, "--zip-location=%s", relative_input_file_name);
     sprintf(input_vdex_fd_arg, "--input-vdex-fd=%d", input_vdex_fd);
     sprintf(output_vdex_fd_arg, "--output-vdex-fd=%d", output_vdex_fd);
     sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);
@@ -314,11 +328,11 @@
 
     bool have_dex2oat_compiler_filter_flag;
     if (skip_compilation) {
-        strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-none");
+        strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=extract");
         have_dex2oat_compiler_filter_flag = true;
         have_dex2oat_relocation_skip_flag = true;
     } else if (vm_safe_mode) {
-        strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=interpret-only");
+        strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=quicken");
         have_dex2oat_compiler_filter_flag = true;
     } else if (compiler_filter != nullptr &&
             strlen(compiler_filter) + strlen("--compiler-filter=") <
@@ -348,8 +362,18 @@
         sprintf(profile_arg, "--profile-file-fd=%d", profile_fd);
     }
 
+    // Get the directory of the apk to pass as a base classpath directory.
+    char base_dir[arraysize("--classpath-dir=") + PKG_PATH_MAX];
+    std::string apk_dir(input_file_name);
+    unsigned long dir_index = apk_dir.rfind('/');
+    bool has_base_dir = dir_index != std::string::npos;
+    if (has_base_dir) {
+        apk_dir = apk_dir.substr(0, dir_index);
+        sprintf(base_dir, "--classpath-dir=%s", apk_dir.c_str());
+    }
 
-    ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
+
+    ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, relative_input_file_name, output_file_name);
 
     const char* argv[9  // program name, mandatory arguments and the final NULL
                      + (have_dex2oat_isa_variant ? 1 : 0)
@@ -367,6 +391,7 @@
                      + dex2oat_flags_count
                      + (profile_fd == -1 ? 0 : 1)
                      + (shared_libraries != nullptr ? 4 : 0)
+                     + (has_base_dir ? 1 : 0)
                      + (have_dex2oat_large_app_threshold ? 1 : 0)];
     int i = 0;
     argv[i++] = DEX2OAT_BIN;
@@ -431,6 +456,9 @@
         argv[i++] = RUNTIME_ARG;
         argv[i++] = shared_libraries;
     }
+    if (has_base_dir) {
+        argv[i++] = base_dir;
+    }
     // Do not add after dex2oat_flags, they should override others for debugging.
     argv[i] = NULL;
 
@@ -768,17 +796,6 @@
     exit(68);   /* only get here on exec failure */
 }
 
-static const char* get_location_from_path(const char* path) {
-    static constexpr char kLocationSeparator = '/';
-    const char *location = strrchr(path, kLocationSeparator);
-    if (location == NULL) {
-        return path;
-    } else {
-        // Skip the separator character.
-        return location + 1;
-    }
-}
-
 bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths) {
     std::vector<unique_fd> profile_fds;
     unique_fd reference_profile_fd;
@@ -1139,8 +1156,8 @@
 // Opens the vdex files and assigns the input fd to in_vdex_wrapper_fd and the output fd to
 // out_vdex_wrapper_fd. Returns true for success or false in case of errors.
 bool open_vdex_files(const char* apk_path, const char* out_oat_path, int dexopt_needed,
-        const char* instruction_set, bool is_public, bool profile_guided,
-        int uid, bool is_secondary_dex, Dex2oatFileWrapper* in_vdex_wrapper_fd,
+        const char* instruction_set, bool is_public, int uid, bool is_secondary_dex,
+        Dex2oatFileWrapper* in_vdex_wrapper_fd,
         Dex2oatFileWrapper* out_vdex_wrapper_fd) {
     CHECK(in_vdex_wrapper_fd != nullptr);
     CHECK(out_vdex_wrapper_fd != nullptr);
@@ -1150,9 +1167,7 @@
     int dexopt_action = abs(dexopt_needed);
     bool is_odex_location = dexopt_needed < 0;
     std::string in_vdex_path_str;
-    // Disable passing an input vdex when the compilation is profile-guided. The dexlayout
-    // optimization in dex2oat is incompatible with it. b/35872504.
-    if (dexopt_action != DEX2OAT_FROM_SCRATCH && !profile_guided) {
+    if (dexopt_action != DEX2OAT_FROM_SCRATCH) {
         // Open the possibly existing vdex. If none exist, we pass -1 to dex2oat for input-vdex-fd.
         const char* path = nullptr;
         if (is_odex_location) {
@@ -1511,8 +1526,8 @@
     // Open vdex files.
     Dex2oatFileWrapper in_vdex_fd;
     Dex2oatFileWrapper out_vdex_fd;
-    if (!open_vdex_files(dex_path, out_oat_path, dexopt_needed, instruction_set, is_public,
-            profile_guided, uid, is_secondary_dex, &in_vdex_fd, &out_vdex_fd)) {
+    if (!open_vdex_files(dex_path, out_oat_path, dexopt_needed, instruction_set, is_public, uid,
+            is_secondary_dex, &in_vdex_fd, &out_vdex_fd)) {
         return -1;
     }
 
@@ -1540,14 +1555,12 @@
             _exit(67);
         }
 
-        // Pass dex2oat the relative path to the input file.
-        const char *input_file_name = get_location_from_path(dex_path);
         run_dex2oat(input_fd.get(),
                     out_oat_fd.get(),
                     in_vdex_fd.get(),
                     out_vdex_fd.get(),
                     image_fd.get(),
-                    input_file_name,
+                    dex_path,
                     out_oat_path,
                     swap_fd.get(),
                     instruction_set,
diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp
index 4740202..df4941c 100644
--- a/cmds/lshal/Android.bp
+++ b/cmds/lshal/Android.bp
@@ -22,7 +22,6 @@
         "libhidltransport",
         "libhidl-gen-utils",
         "libvintf",
-        "android.hidl.manager@1.0",
     ],
     srcs: [
         "Lshal.cpp",
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 420ec3c..d6caf5f 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -163,6 +163,7 @@
     return true;
 }
 
+// Must process hwbinder services first, then passthrough services.
 void Lshal::forEachTable(const std::function<void(Table &)> &f) {
     f(mServicesTable);
     f(mPassthroughRefTable);
@@ -243,6 +244,18 @@
 }
 
 void Lshal::dumpVintf() const {
+    mOut << "<!-- " << std::endl
+         << "    This is a skeleton device manifest. Notes: " << std::endl
+         << "    1. android.hidl.*, android.frameworks.*, android.system.* are not included." << std::endl
+         << "    2. If a HAL is supported in both hwbinder and passthrough transport, " << std::endl
+         << "       only hwbinder is shown." << std::endl
+         << "    3. It is likely that HALs in passthrough transport does not have" << std::endl
+         << "       <interface> declared; users will have to write them by hand." << std::endl
+         << "    4. sepolicy version is set to 0.0. It is recommended that the entry" << std::endl
+         << "       is removed from the manifest file and written by assemble_vintf" << std::endl
+         << "       at build time." << std::endl
+         << "-->" << std::endl;
+
     vintf::HalManifest manifest;
     forEachTable([this, &manifest] (const Table &table) {
         for (const TableEntry &entry : table) {
@@ -271,6 +284,8 @@
             std::string instanceName =
                     &table == &mImplementationsTable ? "" : splittedFqInstanceName.second;
 
+            vintf::Version version{fqName.getPackageMajorVersion(),
+                                   fqName.getPackageMinorVersion()};
             vintf::Transport transport;
             vintf::Arch arch;
             if (entry.transport == "hwbinder") {
@@ -296,35 +311,33 @@
                 continue;
             }
 
-            vintf::ManifestHal *hal = manifest.getHal(fqName.package());
-            if (hal == nullptr) {
-                if (!manifest.add(vintf::ManifestHal{
+            bool done = false;
+            for (vintf::ManifestHal *hal : manifest.getHals(fqName.package())) {
+                if (hal->transport() != transport) {
+                    if (transport != vintf::Transport::PASSTHROUGH) {
+                        mErr << "Fatal: should not reach here. Generated result may be wrong."
+                             << std::endl;
+                    }
+                    done = true;
+                    break;
+                }
+                if (hal->hasVersion(version)) {
+                    hal->interfaces[interfaceName].name = interfaceName;
+                    hal->interfaces[interfaceName].instances.insert(instanceName);
+                    done = true;
+                    break;
+                }
+            }
+            if (done) {
+                continue; // to next TableEntry
+            }
+            if (!manifest.add(vintf::ManifestHal{
                     .format = vintf::HalFormat::HIDL,
                     .name = fqName.package(),
-                    .impl = {.implLevel = vintf::ImplLevel::GENERIC, .impl = ""},
-                    .transportArch = {transport, arch}
-                })) {
-                    mErr << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl;
-                    continue;
-                }
-                hal = manifest.getHal(fqName.package());
-            }
-            if (hal == nullptr) {
-                mErr << "Warning: cannot get hal '" << fqInstanceName
-                     << "' after adding it" << std::endl;
-                continue;
-            }
-            vintf::Version version{fqName.getPackageMajorVersion(), fqName.getPackageMinorVersion()};
-            if (std::find(hal->versions.begin(), hal->versions.end(), version) == hal->versions.end()) {
-                hal->versions.push_back(version);
-            }
-            if (&table != &mImplementationsTable) {
-                auto it = hal->interfaces.find(interfaceName);
-                if (it == hal->interfaces.end()) {
-                    hal->interfaces.insert({interfaceName, {interfaceName, {{instanceName}}}});
-                } else {
-                    it->second.instances.insert(instanceName);
-                }
+                    .versions = {version},
+                    .transportArch = {transport, arch},
+                    .interfaces = {{interfaceName, {interfaceName, {{instanceName}}}}}})) {
+                mErr << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl;
             }
         }
     });
@@ -672,6 +685,7 @@
         << "           -c, --clients: print the client PIDs, or client cmdlines if -m is set"
                                                                               << std::endl
         << "           -m, --cmdline: print cmdline instead of PIDs" << std::endl
+        << "           -d, --debug: emit debug info from IBase::debug" << std::endl
         << "           --sort=i, --sort=interface: sort by interface name" << std::endl
         << "           --sort=p, --sort=pid: sort by server pid" << std::endl
         << "           --init-vintf=path: form a skeleton HAL manifest to specified file " << std::endl
diff --git a/data/etc/android.hardware.sensor.heartrate.fitness.xml b/data/etc/android.hardware.sensor.heartrate.fitness.xml
new file mode 100644
index 0000000..aef77b4
--- /dev/null
+++ b/data/etc/android.hardware.sensor.heartrate.fitness.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- Feature for devices supporting a fitness heart rate monitor -->
+<permissions>
+    <feature name="android.hardware.sensor.heartrate.fitness" />
+</permissions>
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index 9cb4d6d..f9464e8 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -50,8 +50,8 @@
     <!-- Feature to specify if the device support managed users. -->
     <feature name="android.software.managed_users" />
 
-    <!-- Feature to specify if the device supports a VR mode. -->
-    <feature name="android.software.vr.mode" />
+    <!-- Feature to specify if the device supports a VR mode.
+         feature name="android.software.vr.mode" -->
     <!-- Devices with all optimizations required to be a "VR Ready" device that
          pass all CTS tests for this feature must include feature
          android.hardware.vr.high_performance -->
diff --git a/include/android/sensor.h b/include/android/sensor.h
index 4a00818..6c12972 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -48,6 +48,7 @@
  *
  */
 
+#include <stdbool.h>
 #include <sys/types.h>
 
 #include <android/looper.h>
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 74e75d7..b0d53ef 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -681,8 +681,16 @@
         return UNEXPECTED_NULL;
     }
 
+    if (val->max_size() < static_cast<size_t>(size)) {
+        return NO_MEMORY;
+    }
+
     val->resize(static_cast<size_t>(size));
 
+    if (val->size() < static_cast<size_t>(size)) {
+        return NO_MEMORY;
+    }
+
     for (auto& v: *val) {
         status = (this->*read_func)(&v);
 
diff --git a/include/gui/GraphicsEnv.h b/include/gui/GraphicsEnv.h
new file mode 100644
index 0000000..4c7366f
--- /dev/null
+++ b/include/gui/GraphicsEnv.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef ANDROID_GUI_GRAPHICS_ENV_H
+#define ANDROID_GUI_GRAPHICS_ENV_H 1
+
+#include <string>
+
+struct android_namespace_t;
+
+namespace android {
+
+class GraphicsEnv {
+public:
+    static GraphicsEnv& getInstance();
+
+    // Set a search path for loading graphics drivers. The path is a list of
+    // directories separated by ':'. A directory can be contained in a zip file
+    // (drivers must be stored uncompressed and page aligned); such elements
+    // in the search path must have a '!' after the zip filename, e.g.
+    //     /data/app/com.example.driver/base.apk!/lib/arm64-v8a
+    void setDriverPath(const std::string path);
+    android_namespace_t* getDriverNamespace();
+
+private:
+    GraphicsEnv() = default;
+    std::string mDriverPath;
+    android_namespace_t* mDriverNamespace = nullptr;
+};
+
+} // namespace android
+
+/* FIXME
+ * Export an un-mangled function that just does
+ *     return android::GraphicsEnv::getInstance().getDriverNamespace();
+ * This allows libEGL to get the function pointer via dlsym, since it can't
+ * directly link against libgui. In a future release, we'll fix this so that
+ * libgui does not depend on graphics API libraries, and libEGL can link
+ * against it. The current dependencies from libgui -> libEGL are:
+ *  - the GLConsumer class, which should be moved to its own library
+ *  - the EGLsyncKHR synchronization in BufferQueue, which is deprecated and
+ *    will be removed soon.
+ */
+extern "C" android_namespace_t* android_getDriverNamespace();
+
+#endif // ANDROID_GUI_GRAPHICS_ENV_H
diff --git a/include/ui/Fence.h b/include/ui/Fence.h
index 2fbc9ef..1df15f8 100644
--- a/include/ui/Fence.h
+++ b/include/ui/Fence.h
@@ -27,6 +27,8 @@
 #include <utils/String8.h>
 #include <utils/Timers.h>
 
+#include <experimental/optional>
+
 struct ANativeWindowBuffer;
 
 namespace android {
@@ -96,16 +98,26 @@
     // occurs then -1 is returned.
     nsecs_t getSignalTime() const;
 
+#if __cplusplus > 201103L
     // hasSignaled returns whether the fence has signaled yet. Prefer this to
     // getSignalTime() or wait() if all you care about is whether the fence has
-    // signaled.
-    inline bool hasSignaled() {
+    // signaled. Returns an optional bool, which will have a value if there was
+    // no error.
+    inline std::experimental::optional<bool> hasSignaled() {
         // The sync_wait call underlying wait() has been measured to be
         // significantly faster than the sync_fence_info call underlying
         // getSignalTime(), which might otherwise appear to be the more obvious
         // way to check whether a fence has signaled.
-        return wait(0) == NO_ERROR;
+        switch (wait(0)) {
+            case NO_ERROR:
+                return true;
+            case -ETIME:
+                return false;
+            default:
+                return {};
+        }
     }
+#endif
 
     // Flattenable interface
     size_t getFlattenedSize() const;
diff --git a/include/ui/Rect.h b/include/ui/Rect.h
index e9859fe..a7eb871 100644
--- a/include/ui/Rect.h
+++ b/include/ui/Rect.h
@@ -44,13 +44,9 @@
     template <typename T>
     inline Rect(T w, T h) {
         if (w > INT32_MAX) {
-            ALOG(LOG_WARN, "Rect",
-                    "Width %u too large for Rect class, clamping", w);
             w = INT32_MAX;
         }
         if (h > INT32_MAX) {
-            ALOG(LOG_WARN, "Rect",
-                    "Height %u too large for Rect class, clamping", h);
             h = INT32_MAX;
         }
         left = top = 0;
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 4780757..f7347ae 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -15,6 +15,9 @@
 cc_library {
     name: "libbinder",
 
+    // for vndbinder
+    vendor_available: true,
+
     srcs: [
         "AppOpsManager.cpp",
         "Binder.cpp",
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 2062b3b..3aeff2e 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -135,10 +135,12 @@
     {
         unsigned n;
         for (n = 0; n < 5; n++){
+            if (n > 0) {
+                ALOGI("Waiting for service %s...", String8(name).string());
+                sleep(1);
+            }
             sp<IBinder> svc = checkService(name);
             if (svc != NULL) return svc;
-            ALOGI("Waiting for service %s...\n", String8(name).string());
-            sleep(1);
         }
         return NULL;
     }
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 061cb08..d753eb5 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -514,7 +514,7 @@
         // grow objects
         if (mObjectsCapacity < mObjectsSize + numObjects) {
             size_t newSize = ((mObjectsSize + numObjects)*3)/2;
-            if (newSize < mObjectsSize) return NO_MEMORY;   // overflow
+            if (newSize*sizeof(binder_size_t) < mObjectsSize) return NO_MEMORY;   // overflow
             binder_size_t *objects =
                 (binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
             if (objects == (binder_size_t*)0) {
@@ -1308,7 +1308,7 @@
     }
     if (!enoughObjects) {
         size_t newSize = ((mObjectsSize+2)*3)/2;
-        if (newSize < mObjectsSize) return NO_MEMORY;   // overflow
+        if (newSize*sizeof(binder_size_t) < mObjectsSize) return NO_MEMORY;   // overflow
         binder_size_t* objects = (binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
         if (objects == NULL) return NO_MEMORY;
         mObjects = objects;
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 2152206..acd0538 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -61,3 +61,13 @@
         "libbase",
     ],
 }
+
+cc_test {
+    name: "schd-dbg",
+    srcs: ["schd-dbg.cpp"],
+    shared_libs: [
+        "libbinder",
+        "libutils",
+        "libbase",
+    ],
+}
diff --git a/libs/binder/tests/schd-dbg.cpp b/libs/binder/tests/schd-dbg.cpp
new file mode 100644
index 0000000..2732071
--- /dev/null
+++ b/libs/binder/tests/schd-dbg.cpp
@@ -0,0 +1,426 @@
+#include <binder/Binder.h>
+#include <binder/IBinder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+
+#include <iomanip>
+#include <iostream>
+#include <tuple>
+#include <vector>
+
+#include <pthread.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+using namespace std;
+using namespace android;
+
+enum BinderWorkerServiceCode {
+  BINDER_NOP = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+#define ASSERT(cond)                                                \
+  do {                                                              \
+    if (!(cond)) {                                                  \
+      cerr << __func__ << ":" << __LINE__ << " condition:" << #cond \
+           << " failed\n"                                           \
+           << endl;                                                 \
+      exit(EXIT_FAILURE);                                           \
+    }                                                               \
+  } while (0)
+
+vector<sp<IBinder> > workers;
+
+// the ratio that the service is synced on the same cpu beyond
+// GOOD_SYNC_MIN is considered as good
+#define GOOD_SYNC_MIN (0.6)
+
+#define DUMP_PRICISION 3
+
+// the default value
+int no_process = 2;
+int iterations = 100;
+int payload_size = 16;
+int no_inherent = 0;
+int no_sync = 0;
+int verbose = 0;
+
+// the deadline latency that we are interested in
+uint64_t deadline_us = 2500;
+
+int thread_pri() {
+  struct sched_param param;
+  int policy;
+  ASSERT(!pthread_getschedparam(pthread_self(), &policy, &param));
+  return param.sched_priority;
+}
+
+void thread_dump(const char* prefix) {
+  struct sched_param param;
+  int policy;
+  if (!verbose) return;
+  cout << "--------------------------------------------------" << endl;
+  cout << setw(12) << left << prefix << " pid: " << getpid()
+       << " tid: " << gettid() << " cpu: " << sched_getcpu() << endl;
+  ASSERT(!pthread_getschedparam(pthread_self(), &policy, &param));
+  string s = (policy == SCHED_OTHER)
+                 ? "SCHED_OTHER"
+                 : (policy == SCHED_FIFO)
+                       ? "SCHED_FIFO"
+                       : (policy == SCHED_RR) ? "SCHED_RR" : "???";
+  cout << setw(12) << left << s << param.sched_priority << endl;
+  return;
+}
+
+class BinderWorkerService : public BBinder {
+ public:
+  BinderWorkerService() {
+  }
+  ~BinderWorkerService() {
+  }
+  virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+                              uint32_t flags = 0) {
+    (void)flags;
+    (void)data;
+    (void)reply;
+    switch (code) {
+      // The transaction format is like
+      //
+      // data[in]:  int32: caller priority
+      //            int32: caller cpu
+      //
+      // reply[out]: int32: 1 if caller's priority != callee's priority
+      //             int32: 1 if caller's cpu != callee's cpu
+      //
+      // note the caller cpu read here is not always correct
+      // there're still chances that the caller got switched out
+      // right after it read the cpu number and still before the transaction.
+      case BINDER_NOP: {
+        thread_dump("binder");
+        int priority = thread_pri();
+        int priority_caller = data.readInt32();
+        int h = 0, s = 0;
+        if (priority_caller != priority) {
+          h++;
+          if (verbose) {
+            cout << "err priority_caller:" << priority_caller
+                 << ", priority:" << priority << endl;
+          }
+        }
+        if (priority == sched_get_priority_max(SCHED_FIFO)) {
+          int cpu = sched_getcpu();
+          int cpu_caller = data.readInt32();
+          if (cpu != cpu_caller) {
+            s++;
+          }
+        }
+        reply->writeInt32(h);
+        reply->writeInt32(s);
+        return NO_ERROR;
+      }
+      default:
+        return UNKNOWN_TRANSACTION;
+    };
+  }
+};
+
+class Pipe {
+  int m_readFd;
+  int m_writeFd;
+  Pipe(int readFd, int writeFd) : m_readFd{readFd}, m_writeFd{writeFd} {
+  }
+  Pipe(const Pipe&) = delete;
+  Pipe& operator=(const Pipe&) = delete;
+  Pipe& operator=(const Pipe&&) = delete;
+
+ public:
+  Pipe(Pipe&& rval) noexcept {
+    m_readFd = rval.m_readFd;
+    m_writeFd = rval.m_writeFd;
+    rval.m_readFd = 0;
+    rval.m_writeFd = 0;
+  }
+  ~Pipe() {
+    if (m_readFd) close(m_readFd);
+    if (m_writeFd) close(m_writeFd);
+  }
+  void signal() {
+    bool val = true;
+    int error = write(m_writeFd, &val, sizeof(val));
+    ASSERT(error >= 0);
+  };
+  void wait() {
+    bool val = false;
+    int error = read(m_readFd, &val, sizeof(val));
+    ASSERT(error >= 0);
+  }
+  template <typename T>
+  void send(const T& v) {
+    int error = write(m_writeFd, &v, sizeof(T));
+    ASSERT(error >= 0);
+  }
+  template <typename T>
+  void recv(T& v) {
+    int error = read(m_readFd, &v, sizeof(T));
+    ASSERT(error >= 0);
+  }
+  static tuple<Pipe, Pipe> createPipePair() {
+    int a[2];
+    int b[2];
+
+    int error1 = pipe(a);
+    int error2 = pipe(b);
+    ASSERT(error1 >= 0);
+    ASSERT(error2 >= 0);
+
+    return make_tuple(Pipe(a[0], b[1]), Pipe(b[0], a[1]));
+  }
+};
+
+typedef chrono::time_point<chrono::high_resolution_clock> Tick;
+
+static inline Tick tickNow() {
+  return chrono::high_resolution_clock::now();
+}
+
+static inline uint64_t tickNano(Tick& sta, Tick& end) {
+  return uint64_t(chrono::duration_cast<chrono::nanoseconds>(end - sta).count());
+}
+
+struct Results {
+  uint64_t m_best = 0xffffffffffffffffULL;
+  uint64_t m_worst = 0;
+  uint64_t m_transactions = 0;
+  uint64_t m_total_time = 0;
+  uint64_t m_miss = 0;
+
+  void add_time(uint64_t nano) {
+    m_best = min(nano, m_best);
+    m_worst = max(nano, m_worst);
+    m_transactions += 1;
+    m_total_time += nano;
+    if (nano > deadline_us * 1000) m_miss++;
+  }
+  void dump() {
+    double best = (double)m_best / 1.0E6;
+    double worst = (double)m_worst / 1.0E6;
+    double average = (double)m_total_time / m_transactions / 1.0E6;
+    // FIXME: libjson?
+    cout << std::setprecision(DUMP_PRICISION) << "{ \"avg\":" << setw(5) << left
+         << average << ", \"wst\":" << setw(5) << left << worst
+         << ", \"bst\":" << setw(5) << left << best << ", \"miss\":" << m_miss
+         << "}";
+  }
+};
+
+String16 generateServiceName(int num) {
+  char num_str[32];
+  snprintf(num_str, sizeof(num_str), "%d", num);
+  String16 serviceName = String16("binderWorker") + String16(num_str);
+  return serviceName;
+}
+
+static void parcel_fill(Parcel& data, int sz, int priority, int cpu) {
+  ASSERT(sz >= (int)sizeof(uint32_t) * 2);
+  data.writeInt32(priority);
+  data.writeInt32(cpu);
+  sz -= sizeof(uint32_t);
+  while (sz > (int)sizeof(uint32_t)) {
+    data.writeInt32(0);
+    sz -= sizeof(uint32_t);
+  }
+}
+
+static void* thread_start(void* p) {
+  Results* results_fifo = (Results*)p;
+  Parcel data, reply;
+  Tick sta, end;
+
+  parcel_fill(data, payload_size, thread_pri(), sched_getcpu());
+  thread_dump("fifo-caller");
+
+  sta = tickNow();
+  status_t ret = workers[0]->transact(BINDER_NOP, data, &reply);
+  end = tickNow();
+  results_fifo->add_time(tickNano(sta, end));
+
+  no_inherent += reply.readInt32();
+  no_sync += reply.readInt32();
+  return 0;
+}
+
+// create a fifo thread to transact and wait it to finished
+static void thread_transaction(Results* results_fifo) {
+  void* dummy;
+  pthread_t thread;
+  pthread_attr_t attr;
+  struct sched_param param;
+  ASSERT(!pthread_attr_init(&attr));
+  ASSERT(!pthread_attr_setschedpolicy(&attr, SCHED_FIFO));
+  param.sched_priority = sched_get_priority_max(SCHED_FIFO);
+  ASSERT(!pthread_attr_setschedparam(&attr, &param));
+  ASSERT(!pthread_create(&thread, &attr, &thread_start, results_fifo));
+  ASSERT(!pthread_join(thread, &dummy));
+}
+
+#define is_client(_num) ((_num) >= (no_process / 2))
+
+void worker_fx(int num, int no_process, int iterations, int payload_size,
+               Pipe p) {
+  int dummy;
+  Results results_other, results_fifo;
+
+  // Create BinderWorkerService and for go.
+  ProcessState::self()->startThreadPool();
+  sp<IServiceManager> serviceMgr = defaultServiceManager();
+  sp<BinderWorkerService> service = new BinderWorkerService;
+  serviceMgr->addService(generateServiceName(num), service);
+  p.signal();
+  p.wait();
+
+  // If client/server pairs, then half the workers are
+  // servers and half are clients
+  int server_count = no_process / 2;
+
+  for (int i = 0; i < server_count; i++) {
+    // self service is in-process so just skip
+    if (num == i) continue;
+    workers.push_back(serviceMgr->getService(generateServiceName(i)));
+  }
+
+  // Client for each pair iterates here
+  // each iterations contains exatcly 2 transactions
+  for (int i = 0; is_client(num) && i < iterations; i++) {
+    Parcel data, reply;
+    Tick sta, end;
+    // the target is paired to make it easier to diagnose
+    int target = num % server_count;
+
+    // 1. transaction by fifo thread
+    thread_transaction(&results_fifo);
+    parcel_fill(data, payload_size, thread_pri(), sched_getcpu());
+    thread_dump("other-caller");
+
+    // 2. transaction by other thread
+    sta = tickNow();
+    ASSERT(NO_ERROR == workers[target]->transact(BINDER_NOP, data, &reply));
+    end = tickNow();
+    results_other.add_time(tickNano(sta, end));
+
+    no_inherent += reply.readInt32();
+    no_sync += reply.readInt32();
+  }
+  // Signal completion to master and wait.
+  p.signal();
+  p.wait();
+
+  p.send(&dummy);
+  p.wait();
+  // Client for each pair dump here
+  if (is_client(num)) {
+    int no_trans = iterations * 2;
+    double sync_ratio = (1.0 - (double)no_sync / no_trans);
+    // FIXME: libjson?
+    cout << "\"P" << (num - server_count) << "\":{\"SYNC\":\""
+         << ((sync_ratio > GOOD_SYNC_MIN) ? "GOOD" : "POOR") << "\","
+         << "\"S\":" << (no_trans - no_sync) << ",\"I\":" << no_trans << ","
+         << "\"R\":" << sync_ratio << "," << endl;
+
+    cout << "      \"other_ms\":";
+    results_other.dump();
+    cout << "," << endl;
+    cout << "      \"fifo_ms\": ";
+    results_fifo.dump();
+    cout << endl;
+    cout << "}," << endl;
+  }
+  exit(no_inherent);
+}
+
+Pipe make_process(int num, int iterations, int no_process, int payload_size) {
+  auto pipe_pair = Pipe::createPipePair();
+  pid_t pid = fork();
+  if (pid) {
+    // parent
+    return move(get<0>(pipe_pair));
+  } else {
+    // child
+    thread_dump(is_client(num) ? "client" : "server");
+    worker_fx(num, no_process, iterations, payload_size,
+              move(get<1>(pipe_pair)));
+    // never get here
+    return move(get<0>(pipe_pair));
+  }
+}
+
+void wait_all(vector<Pipe>& v) {
+  for (size_t i = 0; i < v.size(); i++) {
+    v[i].wait();
+  }
+}
+
+void signal_all(vector<Pipe>& v) {
+  for (size_t i = 0; i < v.size(); i++) {
+    v[i].signal();
+  }
+}
+
+// This test is modified from binderThroughputTest.cpp
+int main(int argc, char** argv) {
+  for (int i = 1; i < argc; i++) {
+    if (string(argv[i]) == "-i") {
+      iterations = atoi(argv[i + 1]);
+      i++;
+      continue;
+    }
+    if (string(argv[i]) == "-pair") {
+      no_process = 2 * atoi(argv[i + 1]);
+      i++;
+      continue;
+    }
+    if (string(argv[i]) == "-deadline_us") {
+      deadline_us = atoi(argv[i + 1]);
+      i++;
+      continue;
+    }
+    if (string(argv[i]) == "-v") {
+      verbose = 1;
+      i++;
+    }
+  }
+  vector<Pipe> pipes;
+  thread_dump("main");
+  // FIXME: libjson?
+  cout << "{" << endl;
+  cout << "\"cfg\":{\"pair\":" << (no_process / 2)
+       << ",\"iterations\":" << iterations << ",\"deadline_us\":" << deadline_us
+       << "}," << endl;
+
+  // the main process fork 2 processes for each pairs
+  // 1 server + 1 client
+  // each has a pipe to communicate with
+  for (int i = 0; i < no_process; i++) {
+    pipes.push_back(make_process(i, iterations, no_process, payload_size));
+  }
+  wait_all(pipes);
+  signal_all(pipes);
+  wait_all(pipes);
+  signal_all(pipes);
+  for (int i = 0; i < no_process; i++) {
+    int status;
+    pipes[i].signal();
+    wait(&status);
+    // the exit status is number of transactions without priority inheritance
+    // detected in the child process
+    no_inherent += status;
+  }
+  // FIXME: libjson?
+  cout << "\"inheritance\": " << (no_inherent == 0 ? "\"PASS\"" : "\"FAIL\"")
+       << endl;
+  cout << "}" << endl;
+  return -no_inherent;
+}
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 8e8bb80..7ac03f1 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -73,6 +73,7 @@
         "DisplayEventReceiver.cpp",
         "GLConsumer.cpp",
         "GraphicBufferAlloc.cpp",
+        "GraphicsEnv.cpp",
         "GuiConfig.cpp",
         "IDisplayEventConnection.cpp",
         "IGraphicBufferAlloc.cpp",
@@ -95,6 +96,7 @@
     ],
 
     shared_libs: [
+        "libnativeloader",
         "libbinder",
         "libcutils",
         "libEGL",
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 7fbf312..ee4c58c 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -716,6 +716,7 @@
 }
 
 sp<NativeHandle> BufferQueueConsumer::getSidebandStream() const {
+    Mutex::Autolock lock(mCore->mMutex);
     return mCore->mSidebandStream;
 }
 
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index d74d32c..6e6cce2 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -93,6 +93,7 @@
     mSharedBufferSlot(INVALID_BUFFER_SLOT),
     mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
             HAL_DATASPACE_UNKNOWN),
+    mLastQueuedSlot(INVALID_BUFFER_SLOT),
     mUniqueId(getUniqueId())
 {
     if (allocator == NULL) {
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index f8f3872..f0e701e 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -721,6 +721,7 @@
     mSlots[*outSlot].mFence = Fence::NO_FENCE;
     mSlots[*outSlot].mRequestBufferCalled = true;
     mSlots[*outSlot].mAcquireCalled = false;
+    mSlots[*outSlot].mNeedsReallocation = false;
     mCore->mActiveBuffers.insert(found);
     VALIDATE_CONSISTENCY();
 
@@ -1358,6 +1359,7 @@
 
 String8 BufferQueueProducer::getConsumerName() const {
     ATRACE_CALL();
+    Mutex::Autolock lock(mCore->mMutex);
     BQ_LOGV("getConsumerName: %s", mConsumerName.string());
     return mConsumerName;
 }
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 5546d54..3cf3078 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -314,6 +314,18 @@
 
     if (!mSlots[slot].mFence.get()) {
         mSlots[slot].mFence = fence;
+        return OK;
+    }
+
+    auto signaled = mSlots[slot].mFence->hasSignaled();
+
+    if (!signaled) {
+        CB_LOGE("fence has invalid state");
+        return BAD_VALUE;
+    }
+
+    if (*signaled) {
+        mSlots[slot].mFence = fence;
     } else {
         char fenceName[32] = {};
         snprintf(fenceName, 32, "%.28s:%d", mName.string(), slot);
diff --git a/libs/gui/GraphicsEnv.cpp b/libs/gui/GraphicsEnv.cpp
new file mode 100644
index 0000000..68f0f98
--- /dev/null
+++ b/libs/gui/GraphicsEnv.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright 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.
+ */
+
+//#define LOG_NDEBUG 1
+#define LOG_TAG "GraphicsEnv"
+#include <gui/GraphicsEnv.h>
+
+#include <mutex>
+
+#include <log/log.h>
+#include <nativeloader/dlext_namespaces.h>
+
+namespace android {
+
+/*static*/ GraphicsEnv& GraphicsEnv::getInstance() {
+    static GraphicsEnv env;
+    return env;
+}
+
+void GraphicsEnv::setDriverPath(const std::string path) {
+    if (!mDriverPath.empty()) {
+        ALOGV("ignoring attempt to change driver path from '%s' to '%s'",
+                mDriverPath.c_str(), path.c_str());
+        return;
+    }
+    ALOGV("setting driver path to '%s'", path.c_str());
+    mDriverPath = path;
+}
+
+android_namespace_t* GraphicsEnv::getDriverNamespace() {
+    static std::once_flag once;
+    std::call_once(once, [this]() {
+        // TODO; In the next version of Android, all graphics drivers will be
+        // loaded into a custom namespace. To minimize risk for this release,
+        // only updated drivers use a custom namespace.
+        //
+        // Additionally, the custom namespace will be
+        // ANDROID_NAMESPACE_TYPE_ISOLATED, and will only have access to a
+        // subset of the system.
+        if (mDriverPath.empty())
+            return;
+
+        char defaultPath[PATH_MAX];
+        android_get_LD_LIBRARY_PATH(defaultPath, sizeof(defaultPath));
+        size_t defaultPathLen = strlen(defaultPath);
+
+        std::string path;
+        path.reserve(mDriverPath.size() + 1 + defaultPathLen);
+        path.append(mDriverPath);
+        path.push_back(':');
+        path.append(defaultPath, defaultPathLen);
+
+        mDriverNamespace = android_create_namespace(
+                "gfx driver",
+                nullptr,                    // ld_library_path
+                path.c_str(),               // default_library_path
+                ANDROID_NAMESPACE_TYPE_SHARED,
+                nullptr,                    // permitted_when_isolated_path
+                nullptr);                   // parent
+    });
+    return mDriverNamespace;
+}
+
+} // namespace android
+
+extern "C" android_namespace_t* android_getDriverNamespace() {
+    return android::GraphicsEnv::getInstance().getDriverNamespace();
+}
diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp
index 5338034..57c3073 100644
--- a/libs/gui/SensorManager.cpp
+++ b/libs/gui/SensorManager.cpp
@@ -194,7 +194,8 @@
         // a non_wake-up version.
         if (type == SENSOR_TYPE_PROXIMITY || type == SENSOR_TYPE_SIGNIFICANT_MOTION ||
             type == SENSOR_TYPE_TILT_DETECTOR || type == SENSOR_TYPE_WAKE_GESTURE ||
-            type == SENSOR_TYPE_GLANCE_GESTURE || type == SENSOR_TYPE_PICK_UP_GESTURE) {
+            type == SENSOR_TYPE_GLANCE_GESTURE || type == SENSOR_TYPE_PICK_UP_GESTURE ||
+            type == SENSOR_TYPE_WRIST_TILT_GESTURE) {
             wakeUpSensor = true;
         }
         // For now we just return the first sensor of that type we find.
diff --git a/libs/ui/Gralloc1On0Adapter.cpp b/libs/ui/Gralloc1On0Adapter.cpp
index d5b88de..ec7df31 100644
--- a/libs/ui/Gralloc1On0Adapter.cpp
+++ b/libs/ui/Gralloc1On0Adapter.cpp
@@ -288,6 +288,7 @@
 gralloc1_error_t Gralloc1On0Adapter::retain(
         const std::shared_ptr<Buffer>& buffer)
 {
+    std::lock_guard<std::mutex> lock(mBufferMutex);
     buffer->retain();
     return GRALLOC1_ERROR_NONE;
 }
@@ -295,6 +296,7 @@
 gralloc1_error_t Gralloc1On0Adapter::release(
         const std::shared_ptr<Buffer>& buffer)
 {
+    std::lock_guard<std::mutex> lock(mBufferMutex);
     if (!buffer->release()) {
         return GRALLOC1_ERROR_NONE;
     }
@@ -314,7 +316,6 @@
         }
     }
 
-    std::lock_guard<std::mutex> lock(mBufferMutex);
     mBuffers.erase(handle);
     return GRALLOC1_ERROR_NONE;
 }
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 60c4b36..c1056a7 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -23,28 +23,28 @@
 
 // The headers modules are in frameworks/native/opengl/Android.bp.
 ndk_library {
-    name: "libEGL.ndk",
+    name: "libEGL",
     symbol_file: "libEGL.map.txt",
     first_version: "9",
     unversioned_until: "current",
 }
 
 ndk_library {
-    name: "libGLESv1_CM.ndk",
+    name: "libGLESv1_CM",
     symbol_file: "libGLESv1_CM.map.txt",
     first_version: "9",
     unversioned_until: "current",
 }
 
 ndk_library {
-    name: "libGLESv2.ndk",
+    name: "libGLESv2",
     symbol_file: "libGLESv2.map.txt",
     first_version: "9",
     unversioned_until: "current",
 }
 
 ndk_library {
-    name: "libGLESv3.ndk",
+    name: "libGLESv3",
     symbol_file: "libGLESv3.map.txt",
     first_version: "18",
     unversioned_until: "current",
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 218ab35..69e3c13 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -14,6 +14,10 @@
  ** limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include <array>
 #include <ctype.h>
 #include <dirent.h>
 #include <dlfcn.h>
@@ -23,8 +27,10 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <android/dlext.h>
 #include <cutils/properties.h>
 #include <log/log.h>
+#include <utils/Trace.h>
 
 #include <EGL/egl.h>
 
@@ -114,6 +120,11 @@
     return NULL;
 }
 
+static void* do_dlopen(const char* path, int mode) {
+    ATRACE_CALL();
+    return dlopen(path, mode);
+}
+
 // ----------------------------------------------------------------------------
 
 Loader::driver_t::driver_t(void* gles)
@@ -154,14 +165,30 @@
 // ----------------------------------------------------------------------------
 
 Loader::Loader()
-    : getProcAddress(NULL) {
+    : getProcAddress(NULL),
+      mLibGui(nullptr),
+      mGetDriverNamespace(nullptr)
+{
+    // FIXME: See note in GraphicsEnv.h about android_getDriverNamespace().
+    // libgui should already be loaded in any process that uses libEGL, but
+    // if for some reason it isn't, then we're not going to get a driver
+    // namespace anyway, so don't force it to be loaded.
+    mLibGui = dlopen("libgui.so", RTLD_NOLOAD | RTLD_LOCAL | RTLD_LAZY);
+    if (!mLibGui) {
+        ALOGD("failed to load libgui: %s", dlerror());
+        return;
+    }
+    mGetDriverNamespace = reinterpret_cast<decltype(mGetDriverNamespace)>(
+            dlsym(mLibGui, "android_getDriverNamespace"));
 }
 
 Loader::~Loader() {
+    if (mLibGui)
+        dlclose(mLibGui);
 }
 
 static void* load_wrapper(const char* path) {
-    void* so = dlopen(path, RTLD_NOW | RTLD_LOCAL);
+    void* so = do_dlopen(path, RTLD_NOW | RTLD_LOCAL);
     ALOGE_IF(!so, "dlopen(\"%s\") failed: %s", path, dlerror());
     return so;
 }
@@ -208,6 +235,8 @@
 
 void* Loader::open(egl_connection_t* cnx)
 {
+    ATRACE_CALL();
+
     void* dso;
     driver_t* hnd = 0;
 
@@ -253,6 +282,8 @@
         __eglMustCastToProperFunctionPointerType* curr,
         getProcAddressType getProcAddress)
 {
+    ATRACE_CALL();
+
     const ssize_t SIZE = 256;
     char scrap[SIZE];
     while (*api) {
@@ -304,9 +335,8 @@
     }
 }
 
-void *Loader::load_driver(const char* kind,
-        egl_connection_t* cnx, uint32_t mask)
-{
+static void* load_system_driver(const char* kind) {
+    ATRACE_CALL();
     class MatchFile {
     public:
         static String8 find(const char* kind) {
@@ -422,7 +452,7 @@
     }
     const char* const driver_absolute_path = absolutePath.string();
 
-    void* dso = dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
+    void* dso = do_dlopen(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");
@@ -431,11 +461,63 @@
 
     ALOGD("loaded %s", driver_absolute_path);
 
+    return dso;
+}
+
+static void* do_android_dlopen_ext(const char* path, int mode, const android_dlextinfo* info) {
+    ATRACE_CALL();
+    return android_dlopen_ext(path, mode, info);
+}
+
+static const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
+    "ro.hardware.egl",
+    "ro.board.platform",
+}};
+
+static void* load_updated_driver(const char* kind, android_namespace_t* ns) {
+    ATRACE_CALL();
+    const android_dlextinfo dlextinfo = {
+        .flags = ANDROID_DLEXT_USE_NAMESPACE,
+        .library_namespace = ns,
+    };
+    void* so = nullptr;
+    char prop[PROPERTY_VALUE_MAX + 1];
+    for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
+        if (property_get(key, prop, nullptr) > 0) {
+            String8 name;
+            name.appendFormat("lib%s_%s.so", kind, prop);
+            so = do_android_dlopen_ext(name.string(), RTLD_LOCAL | RTLD_NOW,
+                    &dlextinfo);
+            if (so)
+                return so;
+        }
+    }
+    return nullptr;
+}
+
+void *Loader::load_driver(const char* kind,
+        egl_connection_t* cnx, uint32_t mask)
+{
+    ATRACE_CALL();
+
+    void* dso = nullptr;
+    if (mGetDriverNamespace) {
+        android_namespace_t* ns = mGetDriverNamespace();
+        if (ns) {
+            dso = load_updated_driver(kind, ns);
+        }
+    }
+    if (!dso) {
+        dso = load_system_driver(kind);
+        if (!dso)
+            return NULL;
+    }
+
     if (mask & EGL) {
         getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress");
 
         ALOGE_IF(!getProcAddress,
-                "can't find eglGetProcAddress() in %s", driver_absolute_path);
+                "can't find eglGetProcAddress() in EGL driver library");
 
         egl_t* egl = &cnx->egl;
         __eglMustCastToProperFunctionPointerType* curr =
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 94f680e..d0435e7 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -25,6 +25,8 @@
 #include <utils/Singleton.h>
 #include <utils/String8.h>
 
+#include <gui/GraphicsEnv.h>
+
 #include <EGL/egl.h>
 
 // ----------------------------------------------------------------------------
@@ -53,7 +55,10 @@
     };
     
     getProcAddressType getProcAddress;
-    
+
+    void* mLibGui;
+    decltype(android_getDriverNamespace)* mGetDriverNamespace;
+
 public:
     ~Loader();
     
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index a42b3f1..f8e25b4 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -267,6 +267,7 @@
 
 EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
 {
+    ATRACE_CALL();
     clearError();
 
     uintptr_t index = reinterpret_cast<uintptr_t>(display);
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index a32f037..d7df40c 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -15,6 +15,7 @@
  */
 
 #define __STDC_LIMIT_MACROS 1
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
 #include <string.h>
 
@@ -26,6 +27,7 @@
 #include "egl_tls.h"
 #include "Loader.h"
 #include <cutils/properties.h>
+#include <utils/Trace.h>
 
 // ----------------------------------------------------------------------------
 namespace android {
@@ -103,6 +105,7 @@
 EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) {
 
     Mutex::Autolock _l(lock);
+    ATRACE_CALL();
 
     // get our driver loader
     Loader& loader(Loader::getInstance());
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
new file mode 100644
index 0000000..4fd98e2
--- /dev/null
+++ b/services/inputflinger/Android.bp
@@ -0,0 +1,51 @@
+// Copyright (C) 2013 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.
+
+cc_library_shared {
+    name: "libinputflinger",
+
+    srcs: [
+        "EventHub.cpp",
+        "InputApplication.cpp",
+        "InputDispatcher.cpp",
+        "InputListener.cpp",
+        "InputManager.cpp",
+        "InputReader.cpp",
+        "InputWindow.cpp",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "libcrypto",
+        "libcutils",
+        "libinput",
+        "liblog",
+        "libutils",
+        "libui",
+        "libhardware_legacy",
+    ],
+
+    cflags: [
+        "-Wno-unused-parameter",
+        // TODO: Move inputflinger to its own process and mark it hidden
+        //-fvisibility=hidden
+    ],
+
+    export_include_dirs: ["."],
+}
+
+subdirs = [
+    "host",
+    "tests",
+]
diff --git a/services/inputflinger/Android.mk b/services/inputflinger/Android.mk
deleted file mode 100644
index ed867d8..0000000
--- a/services/inputflinger/Android.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright (C) 2013 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    EventHub.cpp \
-    InputApplication.cpp \
-    InputDispatcher.cpp \
-    InputListener.cpp \
-    InputManager.cpp \
-    InputReader.cpp \
-    InputWindow.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libbinder \
-    libcrypto \
-    libcutils \
-    libinput \
-    liblog \
-    libutils \
-    libui \
-    libhardware_legacy
-
-
-# TODO: Move inputflinger to its own process and mark it hidden
-#LOCAL_CFLAGS += -fvisibility=hidden
-
-LOCAL_CFLAGS += -Wno-unused-parameter
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-
-LOCAL_MODULE := libinputflinger
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/services/inputflinger/host/Android.bp b/services/inputflinger/host/Android.bp
new file mode 100644
index 0000000..b8e9bce
--- /dev/null
+++ b/services/inputflinger/host/Android.bp
@@ -0,0 +1,57 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_shared {
+    name: "libinputflingerhost",
+
+    srcs: [
+        "InputFlinger.cpp",
+        "InputDriver.cpp",
+        "InputHost.cpp",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "libcrypto",
+        "libcutils",
+        "libinput",
+        "liblog",
+        "libutils",
+        "libhardware",
+    ],
+
+    cflags: [
+        "-Wno-unused-parameter",
+        // TODO: Move inputflinger to its own process and mark it hidden
+        //-fvisibility=hidden
+    ],
+
+    export_include_dirs: ["."],
+}
+
+//#######################################################################
+// build input flinger executable
+cc_binary {
+    name: "inputflinger",
+
+    srcs: ["main.cpp"],
+
+    shared_libs: [
+        "libbinder",
+        "libinputflingerhost",
+        "libutils",
+    ],
+
+    init_rc: ["inputflinger.rc"],
+}
diff --git a/services/inputflinger/host/Android.mk b/services/inputflinger/host/Android.mk
deleted file mode 100644
index 0a7fc27..0000000
--- a/services/inputflinger/host/Android.mk
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_CLANG := true
-
-LOCAL_SRC_FILES:= \
-    InputFlinger.cpp \
-    InputDriver.cpp \
-    InputHost.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libbinder \
-    libcrypto \
-    libcutils \
-    libinput \
-    liblog \
-    libutils \
-    libhardware
-
-
-# TODO: Move inputflinger to its own process and mark it hidden
-#LOCAL_CFLAGS += -fvisibility=hidden
-
-LOCAL_CFLAGS += -Wno-unused-parameter
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-
-LOCAL_MODULE := libinputflingerhost
-
-include $(BUILD_SHARED_LIBRARY)
-
-########################################################################
-# build input flinger executable
-include $(CLEAR_VARS)
-
-LOCAL_CLANG := true
-
-LOCAL_SRC_FILES:= \
-	main.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libbinder \
-	libinputflingerhost \
-	libutils
-
-LOCAL_MODULE := inputflinger
-LOCAL_INIT_RC := inputflinger.rc
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
new file mode 100644
index 0000000..29d93f0
--- /dev/null
+++ b/services/inputflinger/tests/Android.bp
@@ -0,0 +1,23 @@
+// Build the unit tests.
+
+cc_test {
+    name: "inputflinger_tests",
+    srcs: [
+        "InputReader_test.cpp",
+        "InputDispatcher_test.cpp",
+    ],
+    test_per_src: true,
+    cflags: ["-Wno-unused-parameter"],
+    shared_libs = [
+        "libcutils",
+        "liblog",
+        "libutils",
+        "libhardware",
+        "libhardware_legacy",
+        "libui",
+        "libskia",
+        "libinput",
+        "libinputflinger",
+        "libinputservice",
+    ],
+}
diff --git a/services/inputflinger/tests/Android.mk b/services/inputflinger/tests/Android.mk
deleted file mode 100644
index 4c43392..0000000
--- a/services/inputflinger/tests/Android.mk
+++ /dev/null
@@ -1,40 +0,0 @@
-# Build the unit tests.
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# Build the unit tests.
-test_src_files := \
-    InputReader_test.cpp \
-    InputDispatcher_test.cpp
-
-shared_libraries := \
-    libcutils \
-    liblog \
-    libutils \
-    libhardware \
-    libhardware_legacy \
-    libui \
-    libskia \
-    libinput \
-    libinputflinger \
-    libinputservice
-
-c_includes := \
-    external/skia/include/core
-
-
-module_tags := tests
-
-$(foreach file,$(test_src_files), \
-    $(eval include $(CLEAR_VARS)) \
-    $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
-    $(eval LOCAL_C_INCLUDES := $(c_includes)) \
-    $(eval LOCAL_CFLAGS += -Wno-unused-parameter) \
-    $(eval LOCAL_SRC_FILES := $(file)) \
-    $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
-    $(eval LOCAL_MODULE_TAGS := $(module_tags)) \
-    $(eval include $(BUILD_NATIVE_TEST)) \
-)
-
-# Build the manual test programs.
-include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/services/sensorservice/BatteryService.cpp b/services/sensorservice/BatteryService.cpp
index 81f32cd..452c8c6 100644
--- a/services/sensorservice/BatteryService.cpp
+++ b/services/sensorservice/BatteryService.cpp
@@ -30,12 +30,7 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-BatteryService::BatteryService() {
-    const sp<IServiceManager> sm(defaultServiceManager());
-    if (sm != NULL) {
-        const String16 name("batterystats");
-        mBatteryStatService = interface_cast<IBatteryStats>(sm->getService(name));
-    }
+BatteryService::BatteryService() : mBatteryStatService(nullptr) {
 }
 
 bool BatteryService::addSensor(uid_t uid, int handle) {
@@ -61,7 +56,7 @@
 
 
 void BatteryService::enableSensorImpl(uid_t uid, int handle) {
-    if (mBatteryStatService != 0) {
+    if (checkService()) {
         if (addSensor(uid, handle)) {
             int64_t identity = IPCThreadState::self()->clearCallingIdentity();
             mBatteryStatService->noteStartSensor(uid, handle);
@@ -70,7 +65,7 @@
     }
 }
 void BatteryService::disableSensorImpl(uid_t uid, int handle) {
-    if (mBatteryStatService != 0) {
+    if (checkService()) {
         if (removeSensor(uid, handle)) {
             int64_t identity = IPCThreadState::self()->clearCallingIdentity();
             mBatteryStatService->noteStopSensor(uid, handle);
@@ -80,7 +75,7 @@
 }
 
 void BatteryService::cleanupImpl(uid_t uid) {
-    if (mBatteryStatService != 0) {
+    if (checkService()) {
         Mutex::Autolock _l(mActivationsLock);
         int64_t identity = IPCThreadState::self()->clearCallingIdentity();
         for (size_t i=0 ; i<mActivations.size() ; i++) {
@@ -95,6 +90,17 @@
     }
 }
 
+bool BatteryService::checkService() {
+    if (mBatteryStatService == nullptr) {
+        const sp<IServiceManager> sm(defaultServiceManager());
+        if (sm != NULL) {
+            const String16 name("batterystats");
+            mBatteryStatService = interface_cast<IBatteryStats>(sm->getService(name));
+        }
+    }
+    return mBatteryStatService != nullptr;
+}
+
 ANDROID_SINGLETON_STATIC_INSTANCE(BatteryService)
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/BatteryService.h b/services/sensorservice/BatteryService.h
index 08ba857..43a750c 100644
--- a/services/sensorservice/BatteryService.h
+++ b/services/sensorservice/BatteryService.h
@@ -49,6 +49,7 @@
     SortedVector<Info> mActivations;
     bool addSensor(uid_t uid, int handle);
     bool removeSensor(uid_t uid, int handle);
+    bool checkService();
 
 public:
     static void enableSensor(uid_t uid, int handle) {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 0de5abc..0a795aa 100755
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1362,6 +1362,7 @@
 
         // Wake us up to check if the frame has been received
         setTransactionFlags(eTransactionNeeded);
+        mFlinger->setTransactionFlags(eTraversalNeeded);
     }
     mPendingStates.push_back(mCurrentState);
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5eea3d9..deeb456 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2292,8 +2292,7 @@
         if (s.client != NULL) {
             sp<IBinder> binder = IInterface::asBinder(s.client);
             if (binder != NULL) {
-                String16 desc(binder->getInterfaceDescriptor());
-                if (desc == ISurfaceComposerClient::descriptor) {
+                if (binder->queryLocalInterface(ISurfaceComposerClient::descriptor) != NULL) {
                     sp<Client> client( static_cast<Client *>(s.client.get()) );
                     transactionFlags |= setClientStateLocked(client, s.state);
                 }
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 6710bca..2d36b54 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -2203,8 +2203,7 @@
         if (s.client != NULL) {
             sp<IBinder> binder = IInterface::asBinder(s.client);
             if (binder != NULL) {
-                String16 desc(binder->getInterfaceDescriptor());
-                if (desc == ISurfaceComposerClient::descriptor) {
+                if (binder->queryLocalInterface(ISurfaceComposerClient::descriptor) != NULL) {
                     sp<Client> client( static_cast<Client *>(s.client.get()) );
                     transactionFlags |= setClientStateLocked(client, s.state);
                 }
diff --git a/vulkan/Android.bp b/vulkan/Android.bp
index 3f077a2..f5be518 100644
--- a/vulkan/Android.bp
+++ b/vulkan/Android.bp
@@ -26,6 +26,7 @@
 cc_library_static {
     name: "vulkan_headers",
     export_include_dirs: ["include"],
+    vendor_available: true,
 }
 
 subdirs = [
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index 088d001..0616711 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -28,7 +28,7 @@
 // API version (major.minor.patch)
 define VERSION_MAJOR 1
 define VERSION_MINOR 0
-define VERSION_PATCH 43
+define VERSION_PATCH 46
 
 // API limits
 define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
@@ -93,7 +93,7 @@
 @extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_NAME             "VK_ANDROID_native_buffer"
 
 // 12
-@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION       5
+@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION       6
 @extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_NAME               "VK_EXT_debug_report"
 
 // 13
@@ -248,6 +248,10 @@
 @extension("VK_KHR_push_descriptor") define VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION 1
 @extension("VK_KHR_push_descriptor") define VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME "VK_KHR_push_descriptor"
 
+// 85
+@extension("VK_KHR_incremental_present") define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1
+@extension("VK_KHR_incremental_present") define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present"
+
 // 86
 @extension("VK_KHR_descriptor_update_template") define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_SPEC_VERSION 1
 @extension("VK_KHR_descriptor_update_template") define VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME "VK_KHR_descriptor_update_template"
@@ -304,6 +308,10 @@
 @extension("VK_EXT_discard_rectangles") define VK_EXT_DISCARD_RECTANGLES_SPEC_VERSION 1
 @extension("VK_EXT_discard_rectangles") define VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME "VK_EXT_discard_rectangles"
 
+// 105
+@extension("VK_EXT_swapchain_colorspace") define VK_EXT_SWAPCHAIN_COLORSPACE_SPEC_VERSION 2
+@extension("VK_EXT_swapchain_colorspace") define VK_EXT_SWAPCHAIN_COLORSPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace"
+
 // 106
 @extension("VK_EXT_hdr_metadata") define VK_EXT_HDR_METADATA_SPEC_VERSION 1
 @extension("VK_EXT_hdr_metadata") define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata"
@@ -1023,6 +1031,9 @@
     //@extension("VK_KHR_push_descriptor") // 81
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR    = 1000080000,
 
+    //@extension("VK_KHR_incremental_present") // 85
+    VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR                       = 1000084000,
+
     //@extension("VK_KHR_descriptor_update_template") // 86
     VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR    = 1000085000,
 
@@ -1158,6 +1169,21 @@
 @extension("VK_KHR_surface") // 1
 enum VkColorSpaceKHR {
     VK_COLORSPACE_SRGB_NONLINEAR_KHR                        = 0x00000000,
+
+    //@extension("VK_EXT_swapchain_colorspace") // 105
+    VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT                 = 1000104001,
+    VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT                 = 1000104002,
+    VK_COLOR_SPACE_DCI_P3_LINEAR_EXT                        = 1000104003,
+    VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT                     = 1000104004,
+    VK_COLOR_SPACE_BT709_LINEAR_EXT                         = 1000104005,
+    VK_COLOR_SPACE_BT709_NONLINEAR_EXT                      = 1000104006,
+    VK_COLOR_SPACE_BT2020_LINEAR_EXT                        = 1000104007,
+    VK_COLOR_SPACE_HDR10_ST2084_EXT                         = 1000104008,
+    VK_COLOR_SPACE_DOLBYVISION_EXT                          = 1000104009,
+    VK_COLOR_SPACE_HDR10_HLG_EXT                            = 1000104010,
+    VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT                      = 1000104011,
+    VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT                   = 1000104012,
+    VK_COLOR_SPACE_PASS_THROUGH_EXT                         = 1000104013,
 }
 
 @extension("VK_EXT_debug_report") // 12
@@ -1195,6 +1221,9 @@
     VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT        = 30,
     VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT        = 31,
     VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32,
+
+    //extension("VK_KHR_descriptor_update_template") // 86
+    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = 1000085000,
 }
 
 @extension("VK_EXT_debug_report") // 12
@@ -3657,7 +3686,7 @@
 @extension("VK_KHX_device_group_creation") // 71
 class VkPhysicalDeviceGroupPropertiesKHX {
     VkStructureType                                 sType
-    const void*                                     pNext
+    void*                                           pNext
     u32                                             physicalDeviceCount
     VkPhysicalDevice[VK_MAX_DEVICE_GROUP_SIZE_KHX]  physicalDevices
     VkBool32                                        subsetAllocation
@@ -3858,6 +3887,27 @@
     u32                                         maxPushDescriptors
 }
 
+@extension("VK_KHR_incremental_present") // 85
+class VkRectLayerKHR {
+    VkOffset2D                                  offset
+    VkExtent2D                                  extent
+    u32                                         layer
+}
+
+@extension("VK_KHR_incremental_present") // 85
+class VkPresentRegionKHR {
+    u32                                         rectangleCount
+    const VkRectLayerKHR*                       pRectangles
+}
+
+@extension("VK_KHR_incremental_present") // 85
+class VkPresentRegionsKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    u32                                         swapchainCount
+    const VkPresentRegionKHR*                   pRegions
+}
+
 @extension("VK_KHR_descriptor_update_template") // 86
 class VkDescriptorUpdateTemplateEntryKHR {
     u32                                         dstBinding
@@ -4124,7 +4174,7 @@
 @extension("VK_EXT_discard_rectangles") // 100
 class VkPhysicalDeviceDiscardRectanglePropertiesEXT {
     VkStructureType                             sType
-    const void*                                 pNext
+    void*                                       pNext
     u32                                         maxDiscardRectangles
 }
 
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
index dc1ede1..ef0c246 100644
--- a/vulkan/include/vulkan/vulkan.h
+++ b/vulkan/include/vulkan/vulkan.h
@@ -43,7 +43,7 @@
 #define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
 #define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
 // Version of this file
-#define VK_HEADER_VERSION 43
+#define VK_HEADER_VERSION 46
 
 
 #define VK_NULL_HANDLE 0
@@ -281,6 +281,7 @@
     VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHX = 1000078002,
     VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHX = 1000079000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR = 1000080000,
+    VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000,
     VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = 1000085000,
     VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000,
     VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001,
@@ -3298,6 +3299,19 @@
 
 typedef enum VkColorSpaceKHR {
     VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0,
+    VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001,
+    VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT = 1000104002,
+    VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = 1000104003,
+    VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104004,
+    VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104005,
+    VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104006,
+    VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104007,
+    VK_COLOR_SPACE_HDR10_ST2084_EXT = 1000104008,
+    VK_COLOR_SPACE_DOLBYVISION_EXT = 1000104009,
+    VK_COLOR_SPACE_HDR10_HLG_EXT = 1000104010,
+    VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT = 1000104011,
+    VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012,
+    VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013,
     VK_COLOR_SPACE_BEGIN_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
     VK_COLOR_SPACE_END_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
     VK_COLOR_SPACE_RANGE_SIZE_KHR = (VK_COLOR_SPACE_SRGB_NONLINEAR_KHR - VK_COLOR_SPACE_SRGB_NONLINEAR_KHR + 1),
@@ -3991,6 +4005,30 @@
     const VkWriteDescriptorSet*                 pDescriptorWrites);
 #endif
 
+#define VK_KHR_incremental_present 1
+#define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1
+#define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present"
+
+typedef struct VkRectLayerKHR {
+    VkOffset2D    offset;
+    VkExtent2D    extent;
+    uint32_t      layer;
+} VkRectLayerKHR;
+
+typedef struct VkPresentRegionKHR {
+    uint32_t                 rectangleCount;
+    const VkRectLayerKHR*    pRectangles;
+} VkPresentRegionKHR;
+
+typedef struct VkPresentRegionsKHR {
+    VkStructureType              sType;
+    const void*                  pNext;
+    uint32_t                     swapchainCount;
+    const VkPresentRegionKHR*    pRegions;
+} VkPresentRegionsKHR;
+
+
+
 #define VK_KHR_descriptor_update_template 1
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplateKHR)
 
@@ -4066,7 +4104,7 @@
 #define VK_EXT_debug_report 1
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
 
-#define VK_EXT_DEBUG_REPORT_SPEC_VERSION  5
+#define VK_EXT_DEBUG_REPORT_SPEC_VERSION  6
 #define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report"
 #define VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
 
@@ -4105,6 +4143,7 @@
     VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30,
     VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT = 31,
     VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = 1000085000,
     VK_DEBUG_REPORT_OBJECT_TYPE_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
     VK_DEBUG_REPORT_OBJECT_TYPE_END_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT,
     VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1),
@@ -4761,7 +4800,7 @@
 
 typedef struct VkPhysicalDeviceGroupPropertiesKHX {
     VkStructureType     sType;
-    const void*         pNext;
+    void*               pNext;
     uint32_t            physicalDeviceCount;
     VkPhysicalDevice    physicalDevices[VK_MAX_DEVICE_GROUP_SIZE_KHX];
     VkBool32            subsetAllocation;
@@ -4886,7 +4925,7 @@
 
 
 
-#ifdef VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHX
 #define VK_KHX_external_memory_win32 1
 #define VK_KHX_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
 #define VK_KHX_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHX_external_memory_win32"
@@ -4929,7 +4968,7 @@
     HANDLE                                      handle,
     VkMemoryWin32HandlePropertiesKHX*           pMemoryWin32HandleProperties);
 #endif
-#endif /* VK_USE_PLATFORM_WIN32_KHR */
+#endif /* VK_USE_PLATFORM_WIN32_KHX */
 
 #define VK_KHX_external_memory_fd 1
 #define VK_KHX_EXTERNAL_MEMORY_FD_SPEC_VERSION 1
@@ -5663,7 +5702,7 @@
 
 typedef struct VkPhysicalDeviceDiscardRectanglePropertiesEXT {
     VkStructureType    sType;
-    const void*        pNext;
+    void*              pNext;
     uint32_t           maxDiscardRectangles;
 } VkPhysicalDeviceDiscardRectanglePropertiesEXT;
 
@@ -5687,6 +5726,11 @@
     const VkRect2D*                             pDiscardRectangles);
 #endif
 
+#define VK_EXT_swapchain_colorspace 1
+#define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 2
+#define VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace"
+
+
 #define VK_EXT_hdr_metadata 1
 #define VK_EXT_HDR_METADATA_SPEC_VERSION  1
 #define VK_EXT_HDR_METADATA_EXTENSION_NAME "VK_EXT_hdr_metadata"
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 147cc56..e1f164a 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -14,7 +14,7 @@
 
 // Headers module is in frameworks/native/vulkan/Android.bp.
 ndk_library {
-    name: "libvulkan.ndk",
+    name: "libvulkan",
     symbol_file: "libvulkan.map.txt",
     first_version: "24",
     unversioned_until: "current",
@@ -69,6 +69,7 @@
         "libziparchive",
     ],
     shared_libs: [
+        "libgui",
         "libhardware",
         "libsync",
         "libbase",
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
index 7610c01..ea6fadc 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -110,7 +110,7 @@
 
 // clang-format on
 
-}  // anonymous
+}  // namespace
 
 bool InitDispatchTable(
     VkInstance instance,
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 56396f4..f9d3de1 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -21,10 +21,15 @@
 
 #include <algorithm>
 #include <array>
+#include <dlfcn.h>
 #include <new>
 
 #include <log/log.h>
 
+#include <android/dlext.h>
+#include <cutils/properties.h>
+#include <gui/GraphicsEnv.h>
+
 #include "driver.h"
 #include "stubhal.h"
 
@@ -126,17 +131,74 @@
 
 Hal Hal::hal_;
 
+void* LoadLibrary(const android_dlextinfo& dlextinfo,
+                  const char* subname,
+                  int subname_len) {
+    const char kLibFormat[] = "vulkan.%*s.so";
+    char* name = static_cast<char*>(
+        alloca(sizeof(kLibFormat) + static_cast<size_t>(subname_len)));
+    sprintf(name, kLibFormat, subname_len, subname);
+    return android_dlopen_ext(name, RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+}
+
+const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
+    "ro.hardware." HWVULKAN_HARDWARE_MODULE_ID,
+    "ro.board.platform",
+}};
+
+int LoadUpdatedDriver(const hw_module_t** module) {
+    const android_dlextinfo dlextinfo = {
+        .flags = ANDROID_DLEXT_USE_NAMESPACE,
+        .library_namespace = android::GraphicsEnv::getInstance().getDriverNamespace(),
+    };
+    if (!dlextinfo.library_namespace)
+        return -ENOENT;
+
+    void* so = nullptr;
+    char prop[PROPERTY_VALUE_MAX];
+    for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
+        int prop_len = property_get(key, prop, nullptr);
+        if (prop_len > 0) {
+            so = LoadLibrary(dlextinfo, prop, prop_len);
+            if (so)
+                break;
+        }
+    }
+    if (!so)
+        return -ENOENT;
+
+    hw_module_t* hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
+    if (!hmi) {
+        ALOGE("couldn't find symbol '%s' in HAL library: %s", HAL_MODULE_INFO_SYM_AS_STR, dlerror());
+        dlclose(so);
+        return -EINVAL;
+    }
+    if (strcmp(hmi->id, HWVULKAN_HARDWARE_MODULE_ID) != 0) {
+        ALOGE("HAL id '%s' != '%s'", hmi->id, HWVULKAN_HARDWARE_MODULE_ID);
+        dlclose(so);
+        return -EINVAL;
+    }
+    hmi->dso = so;
+    *module = hmi;
+    ALOGD("loaded updated driver");
+    return 0;
+}
+
 bool Hal::Open() {
     ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
 
     // Use a stub device unless we successfully open a real HAL device.
     hal_.dev_ = &stubhal::kDevice;
 
-    const hwvulkan_module_t* module;
-    int result =
-        hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
+    int result;
+    const hwvulkan_module_t* module = nullptr;
+
+    result = LoadUpdatedDriver(reinterpret_cast<const hw_module_t**>(&module));
+    if (result == -ENOENT) {
+        result = hw_get_module(HWVULKAN_HARDWARE_MODULE_ID, reinterpret_cast<const hw_module_t**>(&module));
+    }
     if (result != 0) {
-        ALOGI("no Vulkan HAL present, using stub HAL");
+        ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
         return true;
     }
 
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index 8cbd398..e9cbceb 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -278,7 +278,7 @@
     // clang-format on
 };
 
-}  // anonymous
+}  // namespace
 
 const ProcHook* GetProcHook(const char* name) {
     const auto& begin = g_proc_hooks;