Merge "Suppress implicit-fallthrough warnings."
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index f8f0265..2d780f5 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,3 +1,7 @@
 [Hook Scripts]
 owners_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "OWNERS$"
 installd_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "^cmds/installd/"
+dumpstate_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "^cmds/dumpstate/"
+dumpsys_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "^cmds/dumpsys/"
+# bugreports matches both cmds/bugreport and cmds/bugreportz
+bugreports_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "^cmds/bugreport"
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp
index bb84a18..cc2a6f7 100644
--- a/cmds/atrace/Android.bp
+++ b/cmds/atrace/Android.bp
@@ -19,6 +19,7 @@
         "libz",
         "libbase",
         "libpdx_default_transport",
+        "android.hardware.atrace@1.0",
     ],
 
     init_rc: ["atrace.rc"],
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 94dbebc..e897482 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -37,6 +37,7 @@
 #include <binder/IServiceManager.h>
 #include <binder/Parcel.h>
 
+#include <android/hardware/atrace/1.0/IAtraceDevice.h>
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <hidl/ServiceManagement.h>
 
@@ -52,6 +53,12 @@
 
 using namespace android;
 using pdx::default_transport::ServiceUtility;
+using hardware::hidl_vec;
+using hardware::hidl_string;
+using hardware::Return;
+using hardware::atrace::V1_0::IAtraceDevice;
+using hardware::atrace::V1_0::Status;
+using hardware::atrace::V1_0::toString;
 
 using std::string;
 
@@ -92,11 +99,7 @@
 
 /* Tracing categories */
 static const TracingCategory k_categories[] = {
-    { "gfx",        "Graphics",         ATRACE_TAG_GRAPHICS, {
-        { OPT,      "events/mdss/enable" },
-        { OPT,      "events/sde/enable" },
-        { OPT,      "events/mali_systrace/enable" },
-    } },
+    { "gfx",        "Graphics",         ATRACE_TAG_GRAPHICS, { } },
     { "input",      "Input",            ATRACE_TAG_INPUT, { } },
     { "view",       "View System",      ATRACE_TAG_VIEW, { } },
     { "webview",    "WebView",          ATRACE_TAG_WEBVIEW, { } },
@@ -223,6 +226,23 @@
     } },
 };
 
+struct TracingVendorCategory {
+    // The name identifying the category.
+    std::string name;
+
+    // A longer description of the category.
+    std::string description;
+
+    // If the category is enabled through command.
+    bool enabled;
+
+    TracingVendorCategory(string &&name, string &&description, bool enabled)
+            : name(std::move(name))
+            , description(std::move(description))
+            , enabled(enabled)
+    {}
+};
+
 /* Command line options */
 static int g_traceDurationSeconds = 5;
 static bool g_traceOverwrite = false;
@@ -240,6 +260,8 @@
 static bool g_traceAborted = false;
 static bool g_categoryEnables[arraysize(k_categories)] = {};
 static std::string g_traceFolder;
+static sp<IAtraceDevice> g_atraceHal;
+static std::vector<TracingVendorCategory> g_vendorCategories;
 
 /* Sys file paths */
 static const char* k_traceClockPath =
@@ -755,13 +777,20 @@
     return ok;
 }
 
-static bool setCategoryEnable(const char* name, bool enable)
+static bool setCategoryEnable(const char* name)
 {
+    bool vendor_found = false;
+    for (auto &c : g_vendorCategories) {
+        if (strcmp(name, c.name.c_str()) == 0) {
+            c.enabled = true;
+            vendor_found = true;
+        }
+    }
     for (size_t i = 0; i < arraysize(k_categories); i++) {
         const TracingCategory& c = k_categories[i];
         if (strcmp(name, c.name) == 0) {
             if (isCategorySupported(c)) {
-                g_categoryEnables[i] = enable;
+                g_categoryEnables[i] = true;
                 return true;
             } else {
                 if (isCategorySupportedForRoot(c)) {
@@ -775,6 +804,9 @@
             }
         }
     }
+    if (vendor_found) {
+        return true;
+    }
     fprintf(stderr, "error: unknown tracing category \"%s\"\n", name);
     return false;
 }
@@ -795,7 +827,7 @@
             tokenizer->skipDelimiters(" ");
             continue;
         }
-        ok &= setCategoryEnable(token.string(), true);
+        ok &= setCategoryEnable(token.string());
     }
     delete tokenizer;
     return ok;
@@ -1083,6 +1115,9 @@
             printf("  %10s - %s\n", c.name, c.longname);
         }
     }
+    for (const auto &c : g_vendorCategories) {
+        printf("  %10s - %s (HAL)\n", c.name.c_str(), c.description.c_str());
+    }
 }
 
 // Print the command usage help to stderr.
@@ -1139,6 +1174,79 @@
     return true;
 }
 
+void initVendorCategories()
+{
+    g_atraceHal = IAtraceDevice::getService();
+
+    if (g_atraceHal == nullptr) {
+        // No atrace HAL
+        return;
+    }
+
+    Return<void> ret = g_atraceHal->listCategories(
+        [](const auto& list) {
+            g_vendorCategories.reserve(list.size());
+            for (const auto& category : list) {
+                g_vendorCategories.emplace_back(category.name, category.description, false);
+            }
+        });
+    if (!ret.isOk()) {
+        fprintf(stderr, "calling atrace HAL failed: %s\n", ret.description().c_str());
+    }
+}
+
+static bool setUpVendorTracing()
+{
+    if (g_atraceHal == nullptr) {
+        // No atrace HAL
+        return true;
+    }
+
+    std::vector<hidl_string> categories;
+    for (const auto &c : g_vendorCategories) {
+        if (c.enabled) {
+            categories.emplace_back(c.name);
+        }
+    }
+
+    if (!categories.size()) {
+        return true;
+    }
+
+    auto ret = g_atraceHal->enableCategories(categories);
+    if (!ret.isOk()) {
+        fprintf(stderr, "calling atrace HAL failed: %s\n", ret.description().c_str());
+        return false;
+    } else if (ret != Status::SUCCESS) {
+        fprintf(stderr, "calling atrace HAL failed: %s\n", toString(ret).c_str());
+        return false;
+    }
+    return true;
+}
+
+static bool cleanUpVendorTracing()
+{
+    if (g_atraceHal == nullptr) {
+        // No atrace HAL
+        return true;
+    }
+
+    if (!g_vendorCategories.size()) {
+        // No vendor categories
+        return true;
+    }
+
+    auto ret = g_atraceHal->disableAllCategories();
+    if (!ret.isOk()) {
+        fprintf(stderr, "calling atrace HAL failed: %s\n", ret.description().c_str());
+        return false;
+    } else if (ret != Status::SUCCESS) {
+        fprintf(stderr, "calling atrace HAL failed: %s\n", toString(ret).c_str());
+        return false;
+    }
+    return true;
+}
+
 int main(int argc, char **argv)
 {
     bool async = false;
@@ -1158,6 +1266,8 @@
         exit(-1);
     }
 
+    initVendorCategories();
+
     for (;;) {
         int ret;
         int option_index = 0;
@@ -1176,7 +1286,7 @@
 
         if (ret < 0) {
             for (int i = optind; i < argc; i++) {
-                if (!setCategoryEnable(argv[i], true)) {
+                if (!setCategoryEnable(argv[i])) {
                     fprintf(stderr, "error enabling tracing category \"%s\"\n", argv[i]);
                     exit(1);
                 }
@@ -1279,6 +1389,7 @@
 
     if (ok && traceStart && !onlyUserspace) {
         ok &= setUpKernelTracing();
+        ok &= setUpVendorTracing();
         ok &= startTrace();
     }
 
@@ -1347,6 +1458,7 @@
 
     // Reset the trace buffer size to 1.
     if (traceStop) {
+        cleanUpVendorTracing();
         cleanUpUserspaceTracing();
         if (!onlyUserspace)
             cleanUpKernelTracing();
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 5903656..d950b7c 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -125,12 +125,6 @@
     chmod 0666 /sys/kernel/tracing/events/block/block_rq_complete/enable
     chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_complete/enable
 
-    # graphics
-    chmod 0666 /sys/kernel/tracing/events/sde/enable
-    chmod 0666 /sys/kernel/debug/tracing/events/sde/enable
-    chmod 0666 /sys/kernel/tracing/events/mdss/enable
-    chmod 0666 /sys/kernel/debug/tracing/events/mdss/enable
-
 # Tracing disabled by default
     write /sys/kernel/debug/tracing/tracing_on 0
     write /sys/kernel/tracing/tracing_on 0
diff --git a/cmds/bugreport/OWNERS b/cmds/bugreport/OWNERS
new file mode 100644
index 0000000..1ba7cff
--- /dev/null
+++ b/cmds/bugreport/OWNERS
@@ -0,0 +1,6 @@
+set noparent
+
+felipeal@google.com
+nandana@google.com
+jsharkey@android.com
+enh@google.com
diff --git a/cmds/bugreportz/OWNERS b/cmds/bugreportz/OWNERS
new file mode 100644
index 0000000..1ba7cff
--- /dev/null
+++ b/cmds/bugreportz/OWNERS
@@ -0,0 +1,6 @@
+set noparent
+
+felipeal@google.com
+nandana@google.com
+jsharkey@android.com
+enh@google.com
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index c852df1..e185cbe 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -57,10 +57,21 @@
         export_aidl_headers: true,
     },
     srcs: [
-        "binder/android/os/IDumpstate.aidl",
+        "binder/android/os/DumpstateOptions.cpp",
+        ":dumpstate_aidl",
+    ],
+    export_include_dirs: ["binder"],
+}
+
+filegroup {
+    name: "dumpstate_aidl",
+    srcs: [
         "binder/android/os/IDumpstateListener.aidl",
         "binder/android/os/IDumpstateToken.aidl",
+        //"binder/android/os/DumpstateOptions.aidl",
+        "binder/android/os/IDumpstate.aidl",
     ],
+    path: "binder",
 }
 
 cc_defaults {
@@ -133,6 +144,7 @@
     name: "dumpstate_test",
     defaults: ["dumpstate_defaults"],
     srcs: [
+        "dumpstate.cpp",
         "tests/dumpstate_test.cpp",
     ],
     static_libs: ["libgmock"],
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index 49a78e7..260ea4b 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -77,6 +77,13 @@
     return binder::Status::ok();
 }
 
+binder::Status DumpstateService::startBugreport(int, const sp<IDumpstateListener>&,
+                                                const DumpstateOptions&, int32_t* returned_id) {
+    // TODO: fork to handle the bugreport request and return the process id or a request id here.
+    *returned_id = -1;
+    return binder::Status::ok();
+}
+
 status_t DumpstateService::dump(int fd, const Vector<String16>&) {
     dprintf(fd, "id: %d\n", ds_.id_);
     dprintf(fd, "pid: %d\n", ds_.pid_);
diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h
index 7bca24a..131aff3 100644
--- a/cmds/dumpstate/DumpstateService.h
+++ b/cmds/dumpstate/DumpstateService.h
@@ -41,6 +41,9 @@
                                bool getSectionDetails,
                                sp<IDumpstateToken>* returned_token) override;
 
+    binder::Status startBugreport(int fd, const sp<IDumpstateListener>& listener,
+                                  const DumpstateOptions& options, int32_t* returned_id) override;
+
   private:
     Dumpstate& ds_;
     std::mutex lock_;
diff --git a/cmds/dumpstate/DumpstateUtil.cpp b/cmds/dumpstate/DumpstateUtil.cpp
index 85eb464..600a500 100644
--- a/cmds/dumpstate/DumpstateUtil.cpp
+++ b/cmds/dumpstate/DumpstateUtil.cpp
@@ -56,11 +56,11 @@
     timespec ts;
     ts.tv_sec = MSEC_TO_SEC(timeout_ms);
     ts.tv_nsec = (timeout_ms % 1000) * 1000000;
-    int ret = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, NULL, &ts));
+    int ret = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, nullptr, &ts));
     int saved_errno = errno;
 
     // Set the signals back the way they were.
-    if (sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) {
+    if (sigprocmask(SIG_SETMASK, &old_mask, nullptr) == -1) {
         printf("*** sigprocmask failed: %s\n", strerror(errno));
         if (ret == 0) {
             return false;
@@ -310,7 +310,7 @@
         struct sigaction sigact;
         memset(&sigact, 0, sizeof(sigact));
         sigact.sa_handler = SIG_IGN;
-        sigaction(SIGPIPE, &sigact, NULL);
+        sigaction(SIGPIPE, &sigact, nullptr);
 
         execvp(path, (char**)args.data());
         // execvp's result will be handled after waitpid_with_timeout() below, but
diff --git a/cmds/dumpstate/OWNERS b/cmds/dumpstate/OWNERS
new file mode 100644
index 0000000..1ba7cff
--- /dev/null
+++ b/cmds/dumpstate/OWNERS
@@ -0,0 +1,6 @@
+set noparent
+
+felipeal@google.com
+nandana@google.com
+jsharkey@android.com
+enh@google.com
diff --git a/cmds/dumpstate/binder/android/os/DumpstateOptions.aidl b/cmds/dumpstate/binder/android/os/DumpstateOptions.aidl
new file mode 100644
index 0000000..c1a7f15
--- /dev/null
+++ b/cmds/dumpstate/binder/android/os/DumpstateOptions.aidl
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/**
+  * Specifies arguments for IDumpstate.
+  * {@hide}
+  */
+parcelable DumpstateOptions cpp_header "android/os/DumpstateOptions.h";
diff --git a/cmds/dumpstate/binder/android/os/DumpstateOptions.cpp b/cmds/dumpstate/binder/android/os/DumpstateOptions.cpp
new file mode 100644
index 0000000..5654190
--- /dev/null
+++ b/cmds/dumpstate/binder/android/os/DumpstateOptions.cpp
@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/os/DumpstateOptions.h>
+
+#include <binder/IBinder.h>
+#include <binder/Parcel.h>
+
+namespace android {
+namespace os {
+
+status_t DumpstateOptions::readFromParcel(const ::android::Parcel* parcel) {
+    if (status_t err = parcel->readBool(&get_section_details)) {
+        return err;
+    }
+    if (status_t err = parcel->readUtf8FromUtf16(&name)) {
+        return err;
+    }
+    return android::OK;
+}
+
+status_t DumpstateOptions::writeToParcel(::android::Parcel* parcel) const {
+    if (status_t err = parcel->writeBool(get_section_details)) {
+        return err;
+    }
+    if (status_t err = parcel->writeUtf8AsUtf16(name)) {
+        return err;
+    }
+    return android::OK;
+}
+
+}  // namespace os
+}  // namespace android
diff --git a/cmds/dumpstate/binder/android/os/DumpstateOptions.h b/cmds/dumpstate/binder/android/os/DumpstateOptions.h
new file mode 100644
index 0000000..a748e3c
--- /dev/null
+++ b/cmds/dumpstate/binder/android/os/DumpstateOptions.h
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2018, 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_OS_DUMPSTATE_OPTIONS_H_
+#define ANDROID_OS_DUMPSTATE_OPTIONS_H_
+
+#include <binder/Parcelable.h>
+
+namespace android {
+namespace os {
+
+struct DumpstateOptions : public android::Parcelable {
+    // If true the caller can get callbacks with per-section progress details.
+    bool get_section_details = false;
+
+    // Name of the caller.
+    std::string name;
+
+    status_t writeToParcel(android::Parcel* parcel) const override;
+    status_t readFromParcel(const android::Parcel* parcel) override;
+};
+
+}  // namespace os
+}  // namespace android
+
+#endif  // ANDROID_OS_DUMPSTATE_OPTIONS_H_
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index 9b11b96..68a4f21 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -18,6 +18,7 @@
 
 import android.os.IDumpstateListener;
 import android.os.IDumpstateToken;
+import android.os.DumpstateOptions;
 
 /**
   * Binder interface for the currently running dumpstate process.
@@ -25,6 +26,8 @@
   */
 interface IDumpstate {
 
+
+    // TODO: remove method once startBugReport is used by Shell.
     /*
      * Sets the listener for this dumpstate progress.
      *
@@ -35,4 +38,11 @@
      */
     IDumpstateToken setListener(@utf8InCpp String name, IDumpstateListener listener,
                                 boolean getSectionDetails);
+
+    /*
+     * Starts a bugreport in a child process.
+     *
+     * Returns an identifier of the bugreport process running in the background.
+     */
+    int startBugreport(int fd, IDumpstateListener listener, in DumpstateOptions options);
 }
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 6cfdb2b..17bb7c3 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -101,7 +101,6 @@
 #define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
 #define BLK_DEV_SYS_DIR "/sys/block"
 
-#define RAFT_DIR "/data/misc/raft"
 #define RECOVERY_DIR "/cache/recovery"
 #define RECOVERY_DATA_DIR "/data/misc/recovery"
 #define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
@@ -455,40 +454,6 @@
     }
 }
 
-static void dump_raft() {
-    if (PropertiesHelper::IsUserBuild()) {
-        return;
-    }
-
-    std::string raft_path = ds.GetPath("-raft_log.txt");
-    if (raft_path.empty()) {
-        MYLOGD("raft_path is empty\n");
-        return;
-    }
-
-    struct stat s;
-    if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
-        MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
-        return;
-    }
-
-    CommandOptions options = CommandOptions::WithTimeout(600).Build();
-    if (!ds.IsZipping()) {
-        // Write compressed and encoded raft logs to stdout if it's not a zipped bugreport.
-        RunCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options);
-        return;
-    }
-
-    RunCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_path}, options);
-    if (!ds.AddZipEntry("raft_log.txt", raft_path)) {
-        MYLOGE("Unable to add raft log %s to zip file\n", raft_path.c_str());
-    } else {
-        if (remove(raft_path.c_str())) {
-            MYLOGE("Error removing raft file %s: %s\n", raft_path.c_str(), strerror(errno));
-        }
-    }
-}
-
 static bool skip_not_stat(const char *path) {
     static const char stat[] = "/stat";
     size_t len = strlen(path);
@@ -1372,7 +1337,7 @@
     printf("== Running Application Services (platform)\n");
     printf("========================================================\n");
 
-    RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform"},
+    RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
             DUMPSYS_COMPONENTS_OPTIONS);
 
     printf("========================================================\n");
@@ -1411,6 +1376,54 @@
     printf("========================================================\n");
 }
 
+/* Dumps state for the default case. Returns true if everything went fine. */
+static bool DumpstateDefault() {
+    // 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();
+    }
+
+    // Invoking the following dumpsys calls before dump_traces() to try and
+    // keep the system stats as close to its initial state as possible.
+    RunDumpsysCritical();
+
+    /* collect stack traces from Dalvik and native processes (needs root) */
+    dump_traces_path = dump_traces();
+
+    /* Run some operations that require root. */
+    ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
+    ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
+
+    ds.AddDir(RECOVERY_DIR, true);
+    ds.AddDir(RECOVERY_DATA_DIR, true);
+    ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
+    ds.AddDir(LOGPERSIST_DATA_DIR, false);
+    if (!PropertiesHelper::IsUserBuild()) {
+        ds.AddDir(PROFILE_DATA_DIR_CUR, true);
+        ds.AddDir(PROFILE_DATA_DIR_REF, true);
+    }
+    add_mountinfo();
+    DumpIpTablesAsRoot();
+
+    // Capture any IPSec policies in play.  No keys are exposed here.
+    RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
+
+    // Run ss as root so we can see socket marks.
+    RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
+
+    // Run iotop as root to show top 100 IO threads
+    RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
+
+    if (!DropRootUser()) {
+        return false;
+    }
+
+    dumpstate();
+    return true;
+}
+
 // This method collects common dumpsys for telephony and wifi
 static void DumpstateRadioCommon() {
     DumpIpTablesAsRoot();
@@ -1466,6 +1479,12 @@
             DUMPSYS_COMPONENTS_OPTIONS);
 
     printf("========================================================\n");
+    printf("== Checkins\n");
+    printf("========================================================\n");
+
+    RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
+
+    printf("========================================================\n");
     printf("== dumpstate: done (id %d)\n", ds.id_);
     printf("========================================================\n");
 }
@@ -1745,24 +1764,290 @@
     // clang-format on
 }
 
-/** Main entry point for dumpstate. */
-int run_main(int argc, char* argv[]) {
-    int do_add_date = 0;
-    int do_zip_file = 0;
-    int do_vibrate = 1;
-    char* use_outfile = nullptr;
-    int use_socket = 0;
-    int use_control_socket = 0;
-    int do_fb = 0;
-    int do_broadcast = 0;
-    int is_remote_mode = 0;
-    bool show_header_only = false;
-    bool do_start_service = false;
-    bool telephony_only = false;
-    bool wifi_only = false;
-    int dup_stdout_fd;
-    int dup_stderr_fd;
+/*
+ * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
+ * if we are writing zip files and adds the version file.
+ */
+static void PrepareToWriteToFile() {
+    const Dumpstate::DumpOptions& options = ds.options_;
+    ds.bugreport_dir_ = dirname(options.use_outfile.c_str());
+    std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
+    std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
+    ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(options.use_outfile.c_str()),
+                                                device_name.c_str(), build_id.c_str());
+    if (options.do_add_date) {
+        char date[80];
+        strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
+        ds.name_ = date;
+    } else {
+        ds.name_ = "undated";
+    }
 
+    if (options.telephony_only) {
+        ds.base_name_ += "-telephony";
+    } else if (options.wifi_only) {
+        ds.base_name_ += "-wifi";
+    }
+
+    if (options.do_fb) {
+        ds.screenshot_path_ = ds.GetPath(".png");
+    }
+    ds.tmp_path_ = ds.GetPath(".tmp");
+    ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
+
+    MYLOGD(
+        "Bugreport dir: %s\n"
+        "Base name: %s\n"
+        "Suffix: %s\n"
+        "Log path: %s\n"
+        "Temporary path: %s\n"
+        "Screenshot path: %s\n",
+        ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
+        ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
+
+    if (options.do_zip_file) {
+        ds.path_ = ds.GetPath(".zip");
+        MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
+        create_parent_dirs(ds.path_.c_str());
+        ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
+        if (ds.zip_file == nullptr) {
+            MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
+        } else {
+            ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
+        }
+        ds.AddTextZipEntry("version.txt", ds.version_);
+    }
+}
+
+/*
+ * Finalizes writing to the file by renaming or zipping the tmp file to the final location,
+ * printing zipped file status, etc.
+ */
+static void FinalizeFile() {
+    const Dumpstate::DumpOptions& options = ds.options_;
+    /* check if user changed the suffix using system properties */
+    std::string name =
+        android::base::GetProperty(android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
+    bool change_suffix = false;
+    if (!name.empty()) {
+        /* must whitelist which characters are allowed, otherwise it could cross directories */
+        std::regex valid_regex("^[-_a-zA-Z0-9]+$");
+        if (std::regex_match(name.c_str(), valid_regex)) {
+            change_suffix = true;
+        } else {
+            MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
+        }
+    }
+    if (change_suffix) {
+        MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
+        ds.name_ = name;
+        if (!ds.screenshot_path_.empty()) {
+            std::string new_screenshot_path = ds.GetPath(".png");
+            if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
+                MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
+                       new_screenshot_path.c_str(), strerror(errno));
+            } else {
+                ds.screenshot_path_ = new_screenshot_path;
+            }
+        }
+    }
+
+    bool do_text_file = true;
+    if (options.do_zip_file) {
+        if (!ds.FinishZipFile()) {
+            MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
+            do_text_file = true;
+        } else {
+            do_text_file = false;
+            // Since zip file is already created, it needs to be renamed.
+            std::string new_path = ds.GetPath(".zip");
+            if (ds.path_ != new_path) {
+                MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
+                if (rename(ds.path_.c_str(), new_path.c_str())) {
+                    MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
+                           strerror(errno));
+                } else {
+                    ds.path_ = new_path;
+                }
+            }
+        }
+    }
+    if (do_text_file) {
+        ds.path_ = ds.GetPath(".txt");
+        MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), ds.tmp_path_.c_str());
+        if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
+            MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), strerror(errno));
+            ds.path_.clear();
+        }
+    }
+    if (options.use_control_socket) {
+        if (do_text_file) {
+            dprintf(ds.control_socket_fd_,
+                    "FAIL:could not create zip file, check %s "
+                    "for more details\n",
+                    ds.log_path_.c_str());
+        } else {
+            dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
+        }
+    }
+}
+
+/* Broadcasts that we are done with the bugreport */
+static void SendBugreportFinishedBroadcast() {
+    const Dumpstate::DumpOptions& options = ds.options_;
+    if (!ds.path_.empty()) {
+        MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
+        // clang-format off
+
+        std::vector<std::string> am_args = {
+             "--receiver-permission", "android.permission.DUMP",
+             "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
+             "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
+             "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
+             "--es", "android.intent.extra.BUGREPORT", ds.path_,
+             "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
+        };
+        // clang-format on
+        if (options.do_fb) {
+            am_args.push_back("--es");
+            am_args.push_back("android.intent.extra.SCREENSHOT");
+            am_args.push_back(ds.screenshot_path_);
+        }
+        if (!ds.notification_title.empty()) {
+            am_args.push_back("--es");
+            am_args.push_back("android.intent.extra.TITLE");
+            am_args.push_back(ds.notification_title);
+            if (!ds.notification_description.empty()) {
+                am_args.push_back("--es");
+                am_args.push_back("android.intent.extra.DESCRIPTION");
+                am_args.push_back(ds.notification_description);
+            }
+        }
+        if (options.is_remote_mode) {
+            am_args.push_back("--es");
+            am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
+            am_args.push_back(SHA256_file_hash(ds.path_));
+            SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
+        } else {
+            SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
+        }
+    } else {
+        MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
+    }
+}
+
+int Dumpstate::ParseCommandlineOptions(int argc, char* argv[]) {
+    int ret = -1;  // success
+    int c;
+    while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
+        switch (c) {
+            // clang-format off
+            case 'd': options_.do_add_date = true;            break;
+            case 'z': options_.do_zip_file = true;            break;
+            case 'o': options_.use_outfile = optarg;          break;
+            case 's': options_.use_socket = true;             break;
+            case 'S': options_.use_control_socket = true;     break;
+            case 'v': options_.show_header_only = true;       break;
+            case 'q': options_.do_vibrate = false;            break;
+            case 'p': options_.do_fb = true;                  break;
+            case 'P': update_progress_ = true;                break;
+            case 'R': options_.is_remote_mode = true;         break;
+            case 'B': options_.do_broadcast = true;           break;
+            case 'V':                                         break;  // compatibility no-op
+            case 'h':
+                ret = 0;
+                break;
+            default:
+                fprintf(stderr, "Invalid option: %c\n", c);
+                ret = 1;
+                break;
+                // clang-format on
+        }
+    }
+
+    // TODO: use helper function to convert argv into a string
+    for (int i = 0; i < argc; i++) {
+        args_ += argv[i];
+        if (i < argc - 1) {
+            args_ += " ";
+        }
+    }
+
+    // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
+    optind = 1;
+    return ret;
+}
+
+// TODO: Move away from system properties when we have binder.
+void Dumpstate::SetOptionsFromProperties() {
+    extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
+    if (!extra_options_.empty()) {
+        // Framework uses a system property to override some command-line args.
+        // Currently, it contains the type of the requested bugreport.
+        if (extra_options_ == "bugreportplus") {
+            // Currently, the dumpstate binder is only used by Shell to update progress.
+            options_.do_start_service = true;
+            update_progress_ = true;
+            options_.do_fb = false;
+        } else if (extra_options_ == "bugreportremote") {
+            options_.do_vibrate = false;
+            options_.is_remote_mode = true;
+            options_.do_fb = false;
+        } else if (extra_options_ == "bugreportwear") {
+            options_.do_start_service = true;
+            update_progress_ = true;
+            options_.do_zip_file = true;
+        } else if (extra_options_ == "bugreporttelephony") {
+            options_.telephony_only = true;
+        } else if (extra_options_ == "bugreportwifi") {
+            options_.wifi_only = true;
+            options_.do_zip_file = true;
+        } else {
+            MYLOGE("Unknown extra option: %s\n", extra_options_.c_str());
+        }
+        // Reset the property
+        android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
+    }
+
+    notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
+    if (!notification_title.empty()) {
+        // Reset the property
+        android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
+
+        notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
+        if (!notification_description.empty()) {
+            // Reset the property
+            android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
+        }
+        MYLOGD("notification (title:  %s, description: %s)\n", notification_title.c_str(),
+               notification_description.c_str());
+    }
+}
+
+bool Dumpstate::ValidateOptions() {
+    if ((options_.do_zip_file || options_.do_add_date || ds.update_progress_ ||
+         options_.do_broadcast) &&
+        options_.use_outfile.empty()) {
+        return false;
+    }
+
+    if (options_.use_control_socket && !options_.do_zip_file) {
+        return false;
+    }
+
+    if (ds.update_progress_ && !options_.do_broadcast) {
+        return false;
+    }
+
+    if (options_.is_remote_mode && (ds.update_progress_ || !options_.do_broadcast ||
+                                    !options_.do_zip_file || !options_.do_add_date)) {
+        return false;
+    }
+    return true;
+}
+
+/* Main entry point for dumpstate. */
+int run_main(int argc, char* argv[]) {
     /* set as high priority, and protect from OOM killer */
     setpriority(PRIO_PROCESS, 0, -20);
 
@@ -1779,97 +2064,12 @@
         }
     }
 
-    /* parse arguments */
-    int c;
-    while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
-        switch (c) {
-            // clang-format off
-            case 'd': do_add_date = 1;            break;
-            case 'z': do_zip_file = 1;            break;
-            case 'o': use_outfile = optarg;       break;
-            case 's': use_socket = 1;             break;
-            case 'S': use_control_socket = 1;     break;
-            case 'v': show_header_only = true;    break;
-            case 'q': do_vibrate = 0;             break;
-            case 'p': do_fb = 1;                  break;
-            case 'P': ds.update_progress_ = true; break;
-            case 'R': is_remote_mode = 1;         break;
-            case 'B': do_broadcast = 1;           break;
-            case 'V':                             break; // compatibility no-op
-            case 'h':
-                ShowUsageAndExit(0);
-                break;
-            default:
-                fprintf(stderr, "Invalid option: %c\n", c);
-                ShowUsageAndExit();
-                // clang-format on
-        }
+    int status = ds.ParseCommandlineOptions(argc, argv);
+    if (status != -1) {
+        ShowUsageAndExit(status);
     }
-
-    // TODO: use helper function to convert argv into a string
-    for (int i = 0; i < argc; i++) {
-        ds.args_ += argv[i];
-        if (i < argc - 1) {
-            ds.args_ += " ";
-        }
-    }
-
-    ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
-    if (!ds.extra_options_.empty()) {
-        // Framework uses a system property to override some command-line args.
-        // Currently, it contains the type of the requested bugreport.
-        if (ds.extra_options_ == "bugreportplus") {
-            // Currently, the dumpstate binder is only used by Shell to update progress.
-            do_start_service = true;
-            ds.update_progress_ = true;
-            do_fb = 0;
-        } else if (ds.extra_options_ == "bugreportremote") {
-            do_vibrate = 0;
-            is_remote_mode = 1;
-            do_fb = 0;
-        } else if (ds.extra_options_ == "bugreportwear") {
-            do_start_service = true;
-            ds.update_progress_ = true;
-            do_zip_file = 1;
-        } else if (ds.extra_options_ == "bugreporttelephony") {
-            telephony_only = true;
-        } else if (ds.extra_options_ == "bugreportwifi") {
-            wifi_only = true;
-            do_zip_file = 1;
-        } else {
-            MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
-        }
-        // Reset the property
-        android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
-    }
-
-    ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
-    if (!ds.notification_title.empty()) {
-        // Reset the property
-        android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
-
-        ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
-        if (!ds.notification_description.empty()) {
-            // Reset the property
-            android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
-        }
-        MYLOGD("notification (title:  %s, description: %s)\n",
-               ds.notification_title.c_str(), ds.notification_description.c_str());
-    }
-
-    if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) {
-        ExitOnInvalidArgs();
-    }
-
-    if (use_control_socket && !do_zip_file) {
-        ExitOnInvalidArgs();
-    }
-
-    if (ds.update_progress_ && !do_broadcast) {
-        ExitOnInvalidArgs();
-    }
-
-    if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
+    ds.SetOptionsFromProperties();
+    if (!ds.ValidateOptions()) {
         ExitOnInvalidArgs();
     }
 
@@ -1884,18 +2084,20 @@
         exit(1);
     }
 
-    if (show_header_only) {
+    const Dumpstate::DumpOptions& options = ds.options_;
+    if (options.show_header_only) {
         ds.PrintHeader();
         exit(0);
     }
 
-    /* redirect output if needed */
-    bool is_redirecting = !use_socket && use_outfile;
+    // Redirect output if needed
+    bool is_redirecting = !options.use_socket && !options.use_outfile.empty();
 
     // TODO: temporarily set progress until it's part of the Dumpstate constructor
-    std::string stats_path =
-        is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile))
-                       : "";
+    std::string stats_path = is_redirecting
+                                 ? android::base::StringPrintf("%s/dumpstate-stats.txt",
+                                                               dirname(options.use_outfile.c_str()))
+                                 : "";
     ds.progress_.reset(new Progress(stats_path));
 
     /* gets the sequential id */
@@ -1907,7 +2109,7 @@
 
     register_sig_handler();
 
-    if (do_start_service) {
+    if (options.do_start_service) {
         MYLOGI("Starting 'dumpstate' service\n");
         android::status_t ret;
         if ((ret = android::os::DumpstateService::Start()) != android::OK) {
@@ -1928,70 +2130,22 @@
 
     // If we are going to use a socket, do it as early as possible
     // to avoid timeouts from bugreport.
-    if (use_socket) {
+    if (options.use_socket) {
         redirect_to_socket(stdout, "dumpstate");
     }
 
-    if (use_control_socket) {
+    if (options.use_control_socket) {
         MYLOGD("Opening control socket\n");
         ds.control_socket_fd_ = open_socket("dumpstate");
         ds.update_progress_ = 1;
     }
 
     if (is_redirecting) {
-        ds.bugreport_dir_ = dirname(use_outfile);
-        std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
-        std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
-        ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
-                                                    device_name.c_str(), build_id.c_str());
-        if (do_add_date) {
-            char date[80];
-            strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
-            ds.name_ = date;
-        } else {
-            ds.name_ = "undated";
-        }
-
-        if (telephony_only) {
-            ds.base_name_ += "-telephony";
-        } else if (wifi_only) {
-            ds.base_name_ += "-wifi";
-        }
-
-        if (do_fb) {
-            ds.screenshot_path_ = ds.GetPath(".png");
-        }
-        ds.tmp_path_ = ds.GetPath(".tmp");
-        ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
-
-        MYLOGD(
-            "Bugreport dir: %s\n"
-            "Base name: %s\n"
-            "Suffix: %s\n"
-            "Log path: %s\n"
-            "Temporary path: %s\n"
-            "Screenshot path: %s\n",
-            ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(),
-            ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
-
-        if (do_zip_file) {
-            ds.path_ = ds.GetPath(".zip");
-            MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
-            create_parent_dirs(ds.path_.c_str());
-            ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
-            if (ds.zip_file == nullptr) {
-                MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
-                do_zip_file = 0;
-            } else {
-                ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
-            }
-            ds.AddTextZipEntry("version.txt", ds.version_);
-        }
+        PrepareToWriteToFile();
 
         if (ds.update_progress_) {
-            if (do_broadcast) {
+            if (options.do_broadcast) {
                 // clang-format off
-
                 std::vector<std::string> am_args = {
                      "--receiver-permission", "android.permission.DUMP",
                      "--es", "android.intent.extra.NAME", ds.name_,
@@ -2002,7 +2156,7 @@
                 // clang-format on
                 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
             }
-            if (use_control_socket) {
+            if (options.use_control_socket) {
                 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
             }
         }
@@ -2015,11 +2169,11 @@
         fclose(cmdline);
     }
 
-    if (do_vibrate) {
+    if (options.do_vibrate) {
         Vibrate(150);
     }
 
-    if (do_fb && ds.do_early_screenshot_) {
+    if (options.do_fb && ds.do_early_screenshot_) {
         if (ds.screenshot_path_.empty()) {
             // should not have happened
             MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
@@ -2029,13 +2183,15 @@
         }
     }
 
-    if (do_zip_file) {
+    if (options.do_zip_file && ds.zip_file != nullptr) {
         if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
             MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
                    strerror(errno));
         }
     }
 
+    int dup_stdout_fd;
+    int dup_stderr_fd;
     if (is_redirecting) {
         TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
         redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
@@ -2062,60 +2218,17 @@
     // duration is logged into MYLOG instead.
     ds.PrintHeader();
 
-    if (telephony_only) {
+    if (options.telephony_only) {
         DumpstateTelephonyOnly();
         ds.DumpstateBoard();
-    } else if (wifi_only) {
+    } else if (options.wifi_only) {
         DumpstateWifiOnly();
     } 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();
-        }
-
-        // Invoking the following dumpsys calls before dump_traces() to try and
-        // keep the system stats as close to its initial state as possible.
-        RunDumpsysCritical();
-
-        // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
-        dump_raft();
-
-        /* collect stack traces from Dalvik and native processes (needs root) */
-        dump_traces_path = dump_traces();
-
-        /* Run some operations that require root. */
-        ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
-        ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
-
-        ds.AddDir(RECOVERY_DIR, true);
-        ds.AddDir(RECOVERY_DATA_DIR, true);
-        ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
-        ds.AddDir(LOGPERSIST_DATA_DIR, false);
-        if (!PropertiesHelper::IsUserBuild()) {
-            ds.AddDir(PROFILE_DATA_DIR_CUR, true);
-            ds.AddDir(PROFILE_DATA_DIR_REF, true);
-        }
-        add_mountinfo();
-        DumpIpTablesAsRoot();
-
-        // Capture any IPSec policies in play.  No keys are exposed here.
-        RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
-                   CommandOptions::WithTimeout(10).Build());
-
-        // Run ss as root so we can see socket marks.
-        RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
-                   CommandOptions::WithTimeout(10).Build());
-
-        // Run iotop as root to show top 100 IO threads
-        RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
-
-        if (!DropRootUser()) {
+        // Dump state for the default case. This also drops root.
+        if (!DumpstateDefault()) {
+            // Something went wrong.
             return -1;
         }
-
-        dumpstate();
     }
 
     /* close output if needed */
@@ -2124,79 +2237,12 @@
     }
 
     /* rename or zip the (now complete) .tmp file to its final location */
-    if (use_outfile) {
-
-        /* check if user changed the suffix using system properties */
-        std::string name = android::base::GetProperty(
-            android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
-        bool change_suffix= false;
-        if (!name.empty()) {
-            /* must whitelist which characters are allowed, otherwise it could cross directories */
-            std::regex valid_regex("^[-_a-zA-Z0-9]+$");
-            if (std::regex_match(name.c_str(), valid_regex)) {
-                change_suffix = true;
-            } else {
-                MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
-            }
-        }
-        if (change_suffix) {
-            MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
-            ds.name_ = name;
-            if (!ds.screenshot_path_.empty()) {
-                std::string new_screenshot_path = ds.GetPath(".png");
-                if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
-                    MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
-                           new_screenshot_path.c_str(), strerror(errno));
-                } else {
-                    ds.screenshot_path_ = new_screenshot_path;
-                }
-            }
-        }
-
-        bool do_text_file = true;
-        if (do_zip_file) {
-            if (!ds.FinishZipFile()) {
-                MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
-                do_text_file = true;
-            } else {
-                do_text_file = false;
-                // Since zip file is already created, it needs to be renamed.
-                std::string new_path = ds.GetPath(".zip");
-                if (ds.path_ != new_path) {
-                    MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
-                    if (rename(ds.path_.c_str(), new_path.c_str())) {
-                        MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
-                               strerror(errno));
-                    } else {
-                        ds.path_ = new_path;
-                    }
-                }
-            }
-        }
-        if (do_text_file) {
-            ds.path_ = ds.GetPath(".txt");
-            MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(),
-                   ds.tmp_path_.c_str());
-            if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
-                MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(),
-                       strerror(errno));
-                ds.path_.clear();
-            }
-        }
-        if (use_control_socket) {
-            if (do_text_file) {
-                dprintf(ds.control_socket_fd_,
-                        "FAIL:could not create zip file, check %s "
-                        "for more details\n",
-                        ds.log_path_.c_str());
-            } else {
-                dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
-            }
-        }
+    if (!options.use_outfile.empty()) {
+        FinalizeFile();
     }
 
     /* vibrate a few but shortly times to let user know it's finished */
-    if (do_vibrate) {
+    if (options.do_vibrate) {
         for (int i = 0; i < 3; i++) {
             Vibrate(75);
             usleep((75 + 50) * 1000);
@@ -2204,47 +2250,8 @@
     }
 
     /* tell activity manager we're done */
-    if (do_broadcast) {
-        if (!ds.path_.empty()) {
-            MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
-            // clang-format off
-
-            std::vector<std::string> am_args = {
-                 "--receiver-permission", "android.permission.DUMP",
-                 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
-                 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
-                 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
-                 "--es", "android.intent.extra.BUGREPORT", ds.path_,
-                 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
-            };
-            // clang-format on
-            if (do_fb) {
-                am_args.push_back("--es");
-                am_args.push_back("android.intent.extra.SCREENSHOT");
-                am_args.push_back(ds.screenshot_path_);
-            }
-            if (!ds.notification_title.empty()) {
-                am_args.push_back("--es");
-                am_args.push_back("android.intent.extra.TITLE");
-                am_args.push_back(ds.notification_title);
-                if (!ds.notification_description.empty()) {
-                    am_args.push_back("--es");
-                    am_args.push_back("android.intent.extra.DESCRIPTION");
-                    am_args.push_back(ds.notification_description);
-                }
-            }
-            if (is_remote_mode) {
-                am_args.push_back("--es");
-                am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
-                am_args.push_back(SHA256_file_hash(ds.path_));
-                SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
-                              am_args);
-            } else {
-                SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
-            }
-        } else {
-            MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
-        }
+    if (options.do_broadcast) {
+        SendBugreportFinishedBroadcast();
     }
 
     MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
@@ -2256,7 +2263,7 @@
         TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
     }
 
-    if (use_control_socket && ds.control_socket_fd_ != -1) {
+    if (options.use_control_socket && ds.control_socket_fd_ != -1) {
         MYLOGD("Closing control socket\n");
         close(ds.control_socket_fd_);
     }
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index b220013..389cc2e 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -290,14 +290,51 @@
     /* Returns true if the current version supports priority dump feature. */
     bool CurrentVersionSupportsPriorityDumps() const;
 
-    // TODO: initialize fields on constructor
+    // TODO: revisit the return values later.
+    /*
+     * Parses commandline arguments and sets runtime options accordingly.
+     *
+     * Returns 0 or positive number if the caller should exit with returned value as
+     * exit code, or returns -1 if caller should proceed with execution.
+     */
+    int ParseCommandlineOptions(int argc, char* argv[]);
 
+    /* Sets runtime options from the system properties. */
+    void SetOptionsFromProperties();
+
+    /* Returns true if the options set so far are consistent. */
+    bool ValidateOptions();
+
+    // TODO: add update_progress_ & other options from DumpState.
+    /*
+     * Structure to hold options that determine the behavior of dumpstate.
+     */
+    struct DumpOptions {
+        bool do_add_date = false;
+        bool do_zip_file = false;
+        bool do_vibrate = true;
+        bool use_socket = false;
+        bool use_control_socket = false;
+        bool do_fb = false;
+        bool do_broadcast = false;
+        bool is_remote_mode = false;
+        bool show_header_only = false;
+        bool do_start_service = false;
+        bool telephony_only = false;
+        bool wifi_only = false;
+        std::string use_outfile;
+    };
+
+    // TODO: initialize fields on constructor
     // dumpstate id - unique after each device reboot.
     uint32_t id_;
 
     // dumpstate pid
     pid_t pid_;
 
+    // Runtime options.
+    DumpOptions options_;
+
     // Whether progress updates should be published.
     bool update_progress_ = false;
 
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 838b385..c57535a 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -54,6 +54,8 @@
 using ::testing::internal::GetCapturedStderr;
 using ::testing::internal::GetCapturedStdout;
 
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
 class DumpstateListenerMock : public IDumpstateListener {
   public:
     MOCK_METHOD1(onProgressUpdated, binder::Status(int32_t progress));
@@ -144,6 +146,7 @@
         ds.progress_.reset(new Progress());
         ds.update_progress_ = false;
         ds.update_progress_threshold_ = 0;
+        ds.options_ = Dumpstate::DumpOptions();
     }
 
     // Runs a command and capture `stdout` and `stderr`.
@@ -201,6 +204,157 @@
     Dumpstate& ds = Dumpstate::GetInstance();
 };
 
+TEST_F(DumpstateTest, ParseCommandlineOptionsNone) {
+    // clang-format off
+    char* argv[] = {
+        const_cast<char*>("dumpstate")
+    };
+    // clang-format on
+
+    int ret = ds.ParseCommandlineOptions(ARRAY_SIZE(argv), argv);
+    EXPECT_EQ(-1, ret);
+    EXPECT_FALSE(ds.options_.do_add_date);
+    EXPECT_FALSE(ds.options_.do_zip_file);
+    EXPECT_EQ("", ds.options_.use_outfile);
+    EXPECT_FALSE(ds.options_.use_socket);
+    EXPECT_FALSE(ds.options_.use_control_socket);
+    EXPECT_FALSE(ds.options_.show_header_only);
+    EXPECT_TRUE(ds.options_.do_vibrate);
+    EXPECT_FALSE(ds.options_.do_fb);
+    EXPECT_FALSE(ds.update_progress_);
+    EXPECT_FALSE(ds.options_.is_remote_mode);
+    EXPECT_FALSE(ds.options_.do_broadcast);
+}
+
+TEST_F(DumpstateTest, ParseCommandlineOptionsPartial1) {
+    // clang-format off
+    char* argv[] = {
+        const_cast<char*>("dumpstate"),
+        const_cast<char*>("-d"),
+        const_cast<char*>("-z"),
+        const_cast<char*>("-o abc"),
+        const_cast<char*>("-s"),
+        const_cast<char*>("-S"),
+
+    };
+    // clang-format on
+    int ret = ds.ParseCommandlineOptions(ARRAY_SIZE(argv), argv);
+    EXPECT_EQ(-1, ret);
+    EXPECT_TRUE(ds.options_.do_add_date);
+    EXPECT_TRUE(ds.options_.do_zip_file);
+    // TODO: Maybe we should trim the filename
+    EXPECT_EQ(" abc", std::string(ds.options_.use_outfile));
+    EXPECT_TRUE(ds.options_.use_socket);
+    EXPECT_TRUE(ds.options_.use_control_socket);
+
+    // Other options retain default values
+    EXPECT_FALSE(ds.options_.show_header_only);
+    EXPECT_TRUE(ds.options_.do_vibrate);
+    EXPECT_FALSE(ds.options_.do_fb);
+    EXPECT_FALSE(ds.update_progress_);
+    EXPECT_FALSE(ds.options_.is_remote_mode);
+    EXPECT_FALSE(ds.options_.do_broadcast);
+}
+
+TEST_F(DumpstateTest, ParseCommandlineOptionsPartial2) {
+    // clang-format off
+    char* argv[] = {
+        const_cast<char*>("dumpstate"),
+        const_cast<char*>("-v"),
+        const_cast<char*>("-q"),
+        const_cast<char*>("-p"),
+        const_cast<char*>("-P"),
+        const_cast<char*>("-R"),
+        const_cast<char*>("-B"),
+    };
+    // clang-format on
+    int ret = ds.ParseCommandlineOptions(ARRAY_SIZE(argv), argv);
+    EXPECT_EQ(-1, ret);
+    EXPECT_TRUE(ds.options_.show_header_only);
+    EXPECT_FALSE(ds.options_.do_vibrate);
+    EXPECT_TRUE(ds.options_.do_fb);
+    EXPECT_TRUE(ds.update_progress_);
+    EXPECT_TRUE(ds.options_.is_remote_mode);
+    EXPECT_TRUE(ds.options_.do_broadcast);
+
+    // Other options retain default values
+    EXPECT_FALSE(ds.options_.do_add_date);
+    EXPECT_FALSE(ds.options_.do_zip_file);
+    EXPECT_EQ("", ds.options_.use_outfile);
+    EXPECT_FALSE(ds.options_.use_socket);
+    EXPECT_FALSE(ds.options_.use_control_socket);
+}
+
+TEST_F(DumpstateTest, ParseCommandlineOptionsHelp) {
+    // clang-format off
+    char* argv[] = {
+        const_cast<char*>("dumpstate"),
+        const_cast<char*>("-h")
+    };
+    // clang-format on
+    int ret = ds.ParseCommandlineOptions(ARRAY_SIZE(argv), argv);
+
+    // -h is for help. Caller exit with code = 0 after printing usage, so expect return = 0.
+    EXPECT_EQ(0, ret);
+}
+
+TEST_F(DumpstateTest, ParseCommandlineOptionsUnknown) {
+    // clang-format off
+    char* argv[] = {
+        const_cast<char*>("dumpstate"),
+        const_cast<char*>("-u")  // unknown flag
+    };
+    // clang-format on
+    int ret = ds.ParseCommandlineOptions(ARRAY_SIZE(argv), argv);
+
+    // -u is unknown. Caller exit with code = 1 to show execution failure, after printing usage,
+    // so expect return = 1.
+    EXPECT_EQ(1, ret);
+}
+
+TEST_F(DumpstateTest, ValidateOptionsNeedOutfile1) {
+    ds.options_.do_zip_file = true;
+    EXPECT_FALSE(ds.ValidateOptions());
+    ds.options_.use_outfile = "a/b/c";
+    EXPECT_TRUE(ds.ValidateOptions());
+}
+
+TEST_F(DumpstateTest, ValidateOptionsNeedOutfile2) {
+    ds.options_.do_broadcast = true;
+    EXPECT_FALSE(ds.ValidateOptions());
+    ds.options_.use_outfile = "a/b/c";
+    EXPECT_TRUE(ds.ValidateOptions());
+}
+
+TEST_F(DumpstateTest, ValidateOptionsNeedZipfile) {
+    ds.options_.use_control_socket = true;
+    EXPECT_FALSE(ds.ValidateOptions());
+
+    ds.options_.do_zip_file = true;
+    ds.options_.use_outfile = "a/b/c";  // do_zip_file needs outfile
+    EXPECT_TRUE(ds.ValidateOptions());
+}
+
+TEST_F(DumpstateTest, ValidateOptionsUpdateProgressNeedsBroadcast) {
+    ds.update_progress_ = true;
+    ds.options_.use_outfile = "a/b/c";  // update_progress_ needs outfile
+    EXPECT_FALSE(ds.ValidateOptions());
+
+    ds.options_.do_broadcast = true;
+    EXPECT_TRUE(ds.ValidateOptions());
+}
+
+TEST_F(DumpstateTest, ValidateOptionsRemoteMode) {
+    ds.options_.is_remote_mode = true;
+    EXPECT_FALSE(ds.ValidateOptions());
+
+    ds.options_.do_broadcast = true;
+    ds.options_.do_zip_file = true;
+    ds.options_.do_add_date = true;
+    ds.options_.use_outfile = "a/b/c";  // do_broadcast needs outfile
+    EXPECT_TRUE(ds.ValidateOptions());
+}
+
 TEST_F(DumpstateTest, RunCommandNoArgs) {
     EXPECT_EQ(-1, RunCommand("", {}));
 }
diff --git a/cmds/dumpsys/OWNERS b/cmds/dumpsys/OWNERS
new file mode 100644
index 0000000..1ba7cff
--- /dev/null
+++ b/cmds/dumpsys/OWNERS
@@ -0,0 +1,6 @@
+set noparent
+
+felipeal@google.com
+nandana@google.com
+jsharkey@android.com
+enh@google.com
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 94c3102..9d0d8ba 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -108,10 +108,8 @@
         "-Wall",
         "-Werror"
     ],
-    clang: true,
 
-    srcs: [
-        "otapreopt_parameters.cpp"],
+    srcs: ["otapreopt_parameters.cpp"],
 
     export_include_dirs: ["."],
 
@@ -123,4 +121,39 @@
     ],
 }
 
-subdirs = ["tests"]
+//
+//  OTA Executable
+//
+
+cc_binary {
+    name: "otapreopt",
+    cflags: [
+        "-Wall",
+        "-Werror"
+    ],
+
+    srcs: [
+        "dexopt.cpp",
+        "globals.cpp",
+        "otapreopt.cpp",
+        "utils.cpp",
+    ],
+
+    header_libs: ["dex2oat_headers"],
+
+    static_libs: [
+        "libartimagevalues",
+        "libdiskusage",
+        "libotapreoptparameters",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libcrypto",
+        "libcutils",
+        "liblog",
+        "liblogwrap",
+        "libselinux",
+        "libutils",
+    ],
+}
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index a4f95da..30de0b3 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -1,43 +1,5 @@
 LOCAL_PATH := $(call my-dir)
 
-#
-# OTA Executable
-#
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := otapreopt
-LOCAL_CFLAGS := -Wall -Werror
-
-# Base & ASLR boundaries for boot image creation.
-ifndef LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA
-  LOCAL_LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA := -0x1000000
-else
-  LOCAL_LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA := $(LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA)
-endif
-ifndef LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA
-  LOCAL_LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA := 0x1000000
-else
-  LOCAL_LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA := $(LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA)
-endif
-LOCAL_CFLAGS += -DART_BASE_ADDRESS=$(LIBART_IMG_HOST_BASE_ADDRESS)
-LOCAL_CFLAGS += -DART_BASE_ADDRESS_MIN_DELTA=$(LOCAL_LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA)
-LOCAL_CFLAGS += -DART_BASE_ADDRESS_MAX_DELTA=$(LOCAL_LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA)
-
-LOCAL_SRC_FILES := otapreopt.cpp otapreopt_parameters.cpp globals.cpp utils.cpp dexopt.cpp
-LOCAL_HEADER_LIBRARIES := dex2oat_headers
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libcrypto \
-    libcutils \
-    liblog \
-    liblogwrap \
-    libselinux \
-    libutils \
-
-LOCAL_STATIC_LIBRARIES := libdiskusage
-LOCAL_CLANG := true
-include $(BUILD_EXECUTABLE)
-
 # OTA slot script
 
 include $(CLEAR_VARS)
diff --git a/cmds/installd/MatchExtensionGen.h b/cmds/installd/MatchExtensionGen.h
index fded6b7..35c3889 100644
--- a/cmds/installd/MatchExtensionGen.h
+++ b/cmds/installd/MatchExtensionGen.h
@@ -31,6 +31,7 @@
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
                 }
+                break;
             case 'p': case 'P':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
@@ -41,10 +42,15 @@
                         switch (ext[5]) {
                         case '\0': return AID_MEDIA_VIDEO;
                         }
+                        break;
                     }
+                    break;
                 }
+                break;
             }
+            break;
         }
+        break;
     case 'a': case 'A':
         switch (ext[1]) {
         case 'a': case 'A':
@@ -53,7 +59,9 @@
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_AUDIO;
                 }
+                break;
             }
+            break;
         case 'i': case 'I':
             switch (ext[2]) {
             case 'f': case 'F':
@@ -63,56 +71,73 @@
                     switch (ext[4]) {
                     case '\0': return AID_MEDIA_AUDIO;
                     }
+                    break;
                 case 'f': case 'F':
                     switch (ext[4]) {
                     case '\0': return AID_MEDIA_AUDIO;
                     }
+                    break;
                 }
+                break;
             }
+            break;
         case 'm': case 'M':
             switch (ext[2]) {
             case 'r': case 'R':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_AUDIO;
                 }
+                break;
             }
+            break;
         case 'r': case 'R':
             switch (ext[2]) {
             case 't': case 'T':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             case 'w': case 'W':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         case 's': case 'S':
             switch (ext[2]) {
             case 'f': case 'F':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
                 }
+                break;
             case 'x': case 'X':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
                 }
+                break;
             }
+            break;
         case 'v': case 'V':
             switch (ext[2]) {
             case 'i': case 'I':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
                 }
+                break;
             }
+            break;
         case 'w': case 'W':
             switch (ext[2]) {
             case 'b': case 'B':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_AUDIO;
                 }
+                break;
             }
+            break;
         }
+        break;
     case 'b': case 'B':
         switch (ext[1]) {
         case 'm': case 'M':
@@ -121,8 +146,11 @@
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         }
+        break;
     case 'c': case 'C':
         switch (ext[1]) {
         case 'r': case 'R':
@@ -131,8 +159,11 @@
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         }
+        break;
     case 'd': case 'D':
         switch (ext[1]) {
         case 'i': case 'I':
@@ -141,23 +172,30 @@
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
                 }
+                break;
             }
+            break;
         case 'l': case 'L':
             switch (ext[2]) {
             case '\0': return AID_MEDIA_VIDEO;
             }
+            break;
         case 'n': case 'N':
             switch (ext[2]) {
             case 'g': case 'G':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         case 'v': case 'V':
             switch (ext[2]) {
             case '\0': return AID_MEDIA_VIDEO;
             }
+            break;
         }
+        break;
     case 'f': case 'F':
         switch (ext[1]) {
         case 'l': case 'L':
@@ -168,13 +206,18 @@
                     switch (ext[4]) {
                     case '\0': return AID_MEDIA_AUDIO;
                     }
+                    break;
                 }
+                break;
             case 'i': case 'I':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
                 }
+                break;
             }
+            break;
         }
+        break;
     case 'g': case 'G':
         switch (ext[1]) {
         case 'i': case 'I':
@@ -183,15 +226,20 @@
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         case 's': case 'S':
             switch (ext[2]) {
             case 'm': case 'M':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_AUDIO;
                 }
+                break;
             }
+            break;
         }
+        break;
     case 'j': case 'J':
         switch (ext[1]) {
         case 'n': case 'N':
@@ -200,7 +248,9 @@
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         case 'p': case 'P':
             switch (ext[2]) {
             case 'e': case 'E':
@@ -210,13 +260,18 @@
                     switch (ext[4]) {
                     case '\0': return AID_MEDIA_IMAGE;
                     }
+                    break;
                 }
+                break;
             case 'g': case 'G':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         }
+        break;
     case 'l': case 'L':
         switch (ext[1]) {
         case 's': case 'S':
@@ -225,12 +280,16 @@
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
                 }
+                break;
             case 'x': case 'X':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
                 }
+                break;
             }
+            break;
         }
+        break;
     case 'm': case 'M':
         switch (ext[1]) {
         case '3':
@@ -239,36 +298,46 @@
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_AUDIO;
                 }
+                break;
             }
+            break;
         case '4':
             switch (ext[2]) {
             case 'a': case 'A':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_AUDIO;
                 }
+                break;
             case 'v': case 'V':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
                 }
+                break;
             }
+            break;
         case 'k': case 'K':
             switch (ext[2]) {
             case 'a': case 'A':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_AUDIO;
                 }
+                break;
             case 'v': case 'V':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
                 }
+                break;
             }
+            break;
         case 'n': case 'N':
             switch (ext[2]) {
             case 'g': case 'G':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
                 }
+                break;
             }
+            break;
         case 'o': case 'O':
             switch (ext[2]) {
             case 'v': case 'V':
@@ -280,23 +349,30 @@
                         switch (ext[5]) {
                         case '\0': return AID_MEDIA_VIDEO;
                         }
+                        break;
                     }
+                    break;
                 }
+                break;
             }
+            break;
         case 'p': case 'P':
             switch (ext[2]) {
             case '2':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_AUDIO;
                 }
+                break;
             case '3':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_AUDIO;
                 }
+                break;
             case '4':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
                 }
+                break;
             case 'e': case 'E':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
@@ -307,8 +383,11 @@
                         switch (ext[5]) {
                         case '\0': return AID_MEDIA_AUDIO;
                         }
+                        break;
                     }
+                    break;
                 }
+                break;
             case 'g': case 'G':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
@@ -316,16 +395,22 @@
                     switch (ext[4]) {
                     case '\0': return AID_MEDIA_AUDIO;
                     }
+                    break;
                 }
+                break;
             }
+            break;
         case 'x': case 'X':
             switch (ext[2]) {
             case 'u': case 'U':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
                 }
+                break;
             }
+            break;
         }
+        break;
     case 'n': case 'N':
         switch (ext[1]) {
         case 'e': case 'E':
@@ -334,15 +419,20 @@
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         case 'r': case 'R':
             switch (ext[2]) {
             case 'w': case 'W':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         }
+        break;
     case 'o': case 'O':
         switch (ext[1]) {
         case 'g': case 'G':
@@ -351,19 +441,25 @@
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_AUDIO;
                 }
+                break;
             case 'g': case 'G':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_AUDIO;
                 }
+                break;
             }
+            break;
         case 'r': case 'R':
             switch (ext[2]) {
             case 'f': case 'F':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         }
+        break;
     case 'p': case 'P':
         switch (ext[1]) {
         case 'b': case 'B':
@@ -372,68 +468,88 @@
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         case 'c': case 'C':
             switch (ext[2]) {
             case 'x': case 'X':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         case 'e': case 'E':
             switch (ext[2]) {
             case 'f': case 'F':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         case 'g': case 'G':
             switch (ext[2]) {
             case 'm': case 'M':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         case 'l': case 'L':
             switch (ext[2]) {
             case 's': case 'S':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_AUDIO;
                 }
+                break;
             }
+            break;
         case 'n': case 'N':
             switch (ext[2]) {
             case 'g': case 'G':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             case 'm': case 'M':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         case 'p': case 'P':
             switch (ext[2]) {
             case 'm': case 'M':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         case 's': case 'S':
             switch (ext[2]) {
             case 'd': case 'D':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         }
+        break;
     case 'q': case 'Q':
         switch (ext[1]) {
         case 't': case 'T':
             switch (ext[2]) {
             case '\0': return AID_MEDIA_VIDEO;
             }
+            break;
         }
+        break;
     case 'r': case 'R':
         switch (ext[1]) {
         case 'a': case 'A':
@@ -443,30 +559,39 @@
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_AUDIO;
                 }
+                break;
             case 's': case 'S':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         case 'g': case 'G':
             switch (ext[2]) {
             case 'b': case 'B':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         case 'm': case 'M':
             switch (ext[2]) {
             case '\0': return AID_MEDIA_AUDIO;
             }
+            break;
         case 'w': case 'W':
             switch (ext[2]) {
             case '2':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         }
+        break;
     case 's': case 'S':
         switch (ext[1]) {
         case 'd': case 'D':
@@ -475,21 +600,27 @@
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_AUDIO;
                 }
+                break;
             }
+            break;
         case 'n': case 'N':
             switch (ext[2]) {
             case 'd': case 'D':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_AUDIO;
                 }
+                break;
             }
+            break;
         case 'r': case 'R':
             switch (ext[2]) {
             case 'w': case 'W':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         case 'v': case 'V':
             switch (ext[2]) {
             case 'g': case 'G':
@@ -499,9 +630,13 @@
                     switch (ext[4]) {
                     case '\0': return AID_MEDIA_IMAGE;
                     }
+                    break;
                 }
+                break;
             }
+            break;
         }
+        break;
     case 't': case 'T':
         switch (ext[1]) {
         case 'i': case 'I':
@@ -513,13 +648,18 @@
                     switch (ext[4]) {
                     case '\0': return AID_MEDIA_IMAGE;
                     }
+                    break;
                 }
+                break;
             }
+            break;
         case 's': case 'S':
             switch (ext[2]) {
             case '\0': return AID_MEDIA_VIDEO;
             }
+            break;
         }
+        break;
     case 'v': case 'V':
         switch (ext[1]) {
         case 'o': case 'O':
@@ -528,8 +668,11 @@
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
                 }
+                break;
             }
+            break;
         }
+        break;
     case 'w': case 'W':
         switch (ext[1]) {
         case 'a': case 'A':
@@ -538,11 +681,14 @@
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_AUDIO;
                 }
+                break;
             case 'x': case 'X':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_AUDIO;
                 }
+                break;
             }
+            break;
         case 'b': case 'B':
             switch (ext[2]) {
             case 'm': case 'M':
@@ -551,8 +697,11 @@
                     switch (ext[4]) {
                     case '\0': return AID_MEDIA_IMAGE;
                     }
+                    break;
                 }
+                break;
             }
+            break;
         case 'e': case 'E':
             switch (ext[2]) {
             case 'b': case 'B':
@@ -561,12 +710,16 @@
                     switch (ext[4]) {
                     case '\0': return AID_MEDIA_VIDEO;
                     }
+                    break;
                 case 'p': case 'P':
                     switch (ext[4]) {
                     case '\0': return AID_MEDIA_IMAGE;
                     }
+                    break;
                 }
+                break;
             }
+            break;
         case 'm': case 'M':
             switch (ext[2]) {
             case '\0': return AID_MEDIA_VIDEO;
@@ -574,30 +727,39 @@
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_AUDIO;
                 }
+                break;
             case 'v': case 'V':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
                 }
+                break;
             case 'x': case 'X':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
                 }
+                break;
             }
+            break;
         case 'r': case 'R':
             switch (ext[2]) {
             case 'f': case 'F':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
                 }
+                break;
             }
+            break;
         case 'v': case 'V':
             switch (ext[2]) {
             case 'x': case 'X':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_VIDEO;
                 }
+                break;
             }
+            break;
         }
+        break;
     case 'x': case 'X':
         switch (ext[1]) {
         case 'b': case 'B':
@@ -606,22 +768,29 @@
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         case 'p': case 'P':
             switch (ext[2]) {
             case 'm': case 'M':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         case 'w': case 'W':
             switch (ext[2]) {
             case 'd': case 'D':
                 switch (ext[3]) {
                 case '\0': return AID_MEDIA_IMAGE;
                 }
+                break;
             }
+            break;
         }
+        break;
     }
 
     return 0;
diff --git a/cmds/installd/art_helper/Android.bp b/cmds/installd/art_helper/Android.bp
new file mode 100644
index 0000000..c47dd72
--- /dev/null
+++ b/cmds/installd/art_helper/Android.bp
@@ -0,0 +1,12 @@
+// Inherit image values.
+art_global_defaults {
+    name: "libartimagevalues_defaults",
+}
+
+cc_library_static {
+    name: "libartimagevalues",
+    defaults: ["libartimagevalues_defaults"],
+    srcs: ["art_image_values.cpp"],
+    export_include_dirs: ["."],
+    cflags: ["-Wconversion"],
+}
diff --git a/cmds/installd/art_helper/art_image_values.cpp b/cmds/installd/art_helper/art_image_values.cpp
new file mode 100644
index 0000000..a139049
--- /dev/null
+++ b/cmds/installd/art_helper/art_image_values.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "art_image_values.h"
+
+namespace android {
+namespace installd {
+namespace art {
+
+uint32_t GetImageBaseAddress() {
+    return ART_BASE_ADDRESS;
+}
+int32_t GetImageMinBaseAddressDelta() {
+    return ART_BASE_ADDRESS_MIN_DELTA;
+}
+int32_t GetImageMaxBaseAddressDelta() {
+    return ART_BASE_ADDRESS_MAX_DELTA;
+}
+
+static_assert(ART_BASE_ADDRESS_MIN_DELTA < ART_BASE_ADDRESS_MAX_DELTA, "Inconsistent setup");
+
+}  // namespace art
+}  // namespace installd
+}  // namespace android
diff --git a/cmds/installd/art_helper/art_image_values.h b/cmds/installd/art_helper/art_image_values.h
new file mode 100644
index 0000000..20c44c9
--- /dev/null
+++ b/cmds/installd/art_helper/art_image_values.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 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 FRAMEWORKS_NATIVE_CMDS_INSTALLD_ART_HELPER_ART_IMAGE_VALUES_H
+#define FRAMEWORKS_NATIVE_CMDS_INSTALLD_ART_HELPER_ART_IMAGE_VALUES_H
+
+#include <cstdint>
+
+namespace android {
+namespace installd {
+namespace art {
+
+uint32_t GetImageBaseAddress();
+int32_t GetImageMinBaseAddressDelta();
+int32_t GetImageMaxBaseAddressDelta();
+
+}  // namespace art
+}  // namespace installd
+}  // namespace android
+
+#endif  // FRAMEWORKS_NATIVE_CMDS_INSTALLD_ART_HELPER_ART_IMAGE_VALUES_H
diff --git a/cmds/installd/matchgen.py b/cmds/installd/matchgen.py
index 131487d..42ce82b 100644
--- a/cmds/installd/matchgen.py
+++ b/cmds/installd/matchgen.py
@@ -84,6 +84,8 @@
                 print "%scase '%s':" % (prefix, k)
             dump(target[k], index + 1)
     print "%s}" % (prefix)
+    if index > 0:
+        print "%sbreak;" % (prefix)
 
 dump(trie, 0)
 
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 7291ef3..28c7658 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -32,6 +32,7 @@
 #include <android-base/macros.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
+#include <art_image_values.h>
 #include <cutils/fs.h>
 #include <cutils/properties.h>
 #include <dex2oat_return_codes.h>
@@ -360,12 +361,11 @@
         }
 
         std::string preopted_boot_art_path = StringPrintf("/system/framework/%s/boot.art", isa);
-        if (access(preopted_boot_art_path.c_str(), F_OK) == 0) {
-          return PatchoatBootImage(isa_path, isa);
-        } else {
+        if (access(preopted_boot_art_path.c_str(), F_OK) != 0) {
           // No preopted boot image. Try to compile.
           return Dex2oatBootImage(boot_classpath_, art_path, oat_path, isa);
         }
+        return true;
     }
 
     static bool CreatePath(const std::string& path) {
@@ -430,29 +430,6 @@
         CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory.";
     }
 
-    bool PatchoatBootImage(const std::string& output_dir, const char* isa) const {
-        // This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc.
-
-        std::vector<std::string> cmd;
-        cmd.push_back("/system/bin/patchoat");
-
-        cmd.push_back("--input-image-location=/system/framework/boot.art");
-        cmd.push_back(StringPrintf("--output-image-directory=%s", output_dir.c_str()));
-
-        cmd.push_back(StringPrintf("--instruction-set=%s", isa));
-
-        int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA,
-                                                          ART_BASE_ADDRESS_MAX_DELTA);
-        cmd.push_back(StringPrintf("--base-offset-delta=%d", base_offset));
-
-        std::string error_msg;
-        bool result = Exec(cmd, &error_msg);
-        if (!result) {
-            LOG(ERROR) << "Could not generate boot image: " << error_msg;
-        }
-        return result;
-    }
-
     bool Dex2oatBootImage(const std::string& boot_cp,
                           const std::string& art_path,
                           const std::string& oat_path,
@@ -466,9 +443,9 @@
         }
         cmd.push_back(StringPrintf("--oat-file=%s", oat_path.c_str()));
 
-        int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA,
-                ART_BASE_ADDRESS_MAX_DELTA);
-        cmd.push_back(StringPrintf("--base=0x%x", ART_BASE_ADDRESS + base_offset));
+        int32_t base_offset = ChooseRelocationOffsetDelta(art::GetImageMinBaseAddressDelta(),
+                                                          art::GetImageMaxBaseAddressDelta());
+        cmd.push_back(StringPrintf("--base=0x%x", art::GetImageBaseAddress() + base_offset));
 
         cmd.push_back(StringPrintf("--instruction-set=%s", isa));
 
@@ -610,7 +587,7 @@
         // If the dexopt failed, we may have a stale boot image from a previous OTA run.
         // Then regenerate and retry.
         if (WEXITSTATUS(dexopt_result) ==
-                static_cast<int>(art::dex2oat::ReturnCode::kCreateRuntime)) {
+                static_cast<int>(::art::dex2oat::ReturnCode::kCreateRuntime)) {
             if (!PrepareBootImage(/* force */ true)) {
                 LOG(ERROR) << "Forced boot image creating failed. Original error return was "
                         << dexopt_result;
diff --git a/cmds/installd/otapreopt_parameters.cpp b/cmds/installd/otapreopt_parameters.cpp
index cf3de01..b1ad8db 100644
--- a/cmds/installd/otapreopt_parameters.cpp
+++ b/cmds/installd/otapreopt_parameters.cpp
@@ -16,6 +16,8 @@
 
 #include "otapreopt_parameters.h"
 
+#include <cstring>
+
 #include <android-base/logging.h>
 
 #include "dexopt.h"
@@ -248,6 +250,8 @@
         case 8: num_args_expected = 16; break;
         // Version 9 adds a new dexopt flag: DEXOPT_GENERATE_APP_IMAGE
         case 9: num_args_expected = 16; break;
+        // Version 10 is a compatibility bump.
+        case 10: num_args_expected = 16; break;
         default:
             LOG(ERROR) << "Don't know how to read arguments for version " << version;
             return false;
@@ -360,6 +364,15 @@
         }
     }
 
+    if (version < 10) {
+        // Do not accept '&' as shared libraries from versions prior to 10. These may lead
+        // to runtime crashes. The server side of version 10+ should send the correct
+        // context in almost all cases (e.g., only for actual shared packages).
+        if (shared_libraries != nullptr && std::string("&") == shared_libraries) {
+            return false;
+        }
+    }
+
     return true;
 }
 
diff --git a/cmds/installd/tests/installd_otapreopt_test.cpp b/cmds/installd/tests/installd_otapreopt_test.cpp
index b518507..66dd51e 100644
--- a/cmds/installd/tests/installd_otapreopt_test.cpp
+++ b/cmds/installd/tests/installd_otapreopt_test.cpp
@@ -114,11 +114,14 @@
             case 7: return "7";
             case 8: return "8";
             case 9: return "9";
+            case 10: return "10";
         }
         return nullptr;
     }
 
-    std::vector<const char*> getArgs(uint32_t version, bool versioned) {
+    std::vector<const char*> getArgs(uint32_t version,
+                                     bool versioned,
+                                     const char* shared_libs = "shared.lib") {
         std::vector<const char*> args;
         args.push_back("otapreopt");  // "otapreopt"
         args.push_back("a");  // slot
@@ -135,7 +138,7 @@
         args.push_back("0");  // dexopt_flags
         args.push_back("speed");  // filter
         args.push_back("!");  // volume
-        args.push_back("shared.lib");  // libs
+        args.push_back(shared_libs);  // libs
 
         if (version > 1) {
             args.push_back("!");  // seinfo
@@ -159,9 +162,11 @@
         return args;
     }
 
-    void VerifyReadArguments(uint32_t version, bool versioned) {
+    void VerifyReadArguments(uint32_t version,
+                             bool versioned,
+                             const char* shared_libs = "shared.lib") {
         OTAPreoptParameters params;
-        std::vector<const char*> args = getArgs(version, versioned);
+        std::vector<const char*> args = getArgs(version, versioned, shared_libs);
         ASSERT_TRUE(params.ReadArguments(args.size() - 1, args.data()));
         verifyPackageParameters(params, version, versioned, args.data());
     }
@@ -199,6 +204,18 @@
     VerifyReadArguments(7, true);
 }
 
+TEST_F(OTAPreoptTest, ReadArgumentsV9SharedLibsAmpersand) {
+    OTAPreoptParameters params;
+    std::vector<const char*> args = getArgs(9, true, "&");
+    ASSERT_FALSE(params.ReadArguments(args.size() - 1, args.data()));
+}
+
+TEST_F(OTAPreoptTest, ReadArgumentsV10SharedLibsAmpersand) {
+    OTAPreoptParameters params;
+    std::vector<const char*> args = getArgs(10, true, "&");
+    ASSERT_TRUE(params.ReadArguments(args.size() - 1, args.data()));
+}
+
 TEST_F(OTAPreoptTest, ReadArgumentsFailToManyArgs) {
     OTAPreoptParameters params;
     std::vector<const char*> args = getArgs(5, true);
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index bcdd03e..ad7a5ae 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -21,6 +21,7 @@
 #include <gtest/gtest.h>
 
 #include "InstalldNativeService.h"
+#include "MatchExtensionGen.h"
 #include "globals.h"
 #include "utils.h"
 
@@ -529,5 +530,19 @@
     EXPECT_NE(0, validate_apk_path_subdirs("/data/app/com.example/dir/dir/dir//file"));
 }
 
+TEST_F(UtilsTest, MatchExtension_Valid) {
+    EXPECT_EQ(AID_MEDIA_VIDEO, MatchExtension("mpg"));
+    EXPECT_EQ(AID_MEDIA_VIDEO, MatchExtension("mpeg"));
+    EXPECT_EQ(AID_MEDIA_VIDEO, MatchExtension("mPeG"));
+    EXPECT_EQ(AID_MEDIA_VIDEO, MatchExtension("MPEG"));
+}
+
+TEST_F(UtilsTest, MatchExtension_Invalid) {
+    EXPECT_EQ(0, MatchExtension("log"));
+    EXPECT_EQ(0, MatchExtension("3amp"));
+    EXPECT_EQ(0, MatchExtension("fpe"));
+    EXPECT_EQ(0, MatchExtension("docx"));
+}
+
 }  // namespace installd
 }  // namespace android
diff --git a/cmds/lshal/PipeRelay.cpp b/cmds/lshal/PipeRelay.cpp
index 3a17e03..820679f 100644
--- a/cmds/lshal/PipeRelay.cpp
+++ b/cmds/lshal/PipeRelay.cpp
@@ -16,33 +16,75 @@
 
 #include "PipeRelay.h"
 
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <atomic>
+
+#include <android-base/logging.h>
 #include <utils/Thread.h>
 
 namespace android {
 namespace lshal {
 
+static constexpr struct timeval READ_TIMEOUT { .tv_sec = 1, .tv_usec = 0 };
+
 struct PipeRelay::RelayThread : public Thread {
     explicit RelayThread(int fd, std::ostream &os);
 
     bool threadLoop() override;
+    void setFinished();
 
 private:
     int mFd;
     std::ostream &mOutStream;
 
+    // If we were to use requestExit() and exitPending() instead, threadLoop()
+    // may not run at all by the time ~PipeRelay is called (i.e. debug() has
+    // returned from HAL). By using our own flag, we ensure that select() and
+    // read() are executed until data are drained.
+    std::atomic_bool mFinished;
+
     DISALLOW_COPY_AND_ASSIGN(RelayThread);
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 
 PipeRelay::RelayThread::RelayThread(int fd, std::ostream &os)
-    : mFd(fd),
-      mOutStream(os) {
-}
+      : mFd(fd), mOutStream(os), mFinished(false) {}
 
 bool PipeRelay::RelayThread::threadLoop() {
     char buffer[1024];
-    ssize_t n = read(mFd, buffer, sizeof(buffer));
+
+    fd_set set;
+    FD_ZERO(&set);
+    FD_SET(mFd, &set);
+
+    struct timeval timeout = READ_TIMEOUT;
+
+    int res = TEMP_FAILURE_RETRY(select(mFd + 1, &set, nullptr, nullptr, &timeout));
+    if (res < 0) {
+        PLOG(INFO) << "select() failed";
+        return false;
+    }
+
+    if (res == 0 || !FD_ISSET(mFd, &set)) {
+        if (mFinished) {
+            LOG(WARNING) << "debug: timeout reading from pipe, output may be truncated.";
+            return false;
+        }
+        // timeout, but debug() has not returned, so wait for HAL to finish.
+        return true;
+    }
+
+    // FD_ISSET(mFd, &set) == true. Data available, start reading
+    ssize_t n = TEMP_FAILURE_RETRY(read(mFd, buffer, sizeof(buffer)));
+
+    if (n < 0) {
+        PLOG(ERROR) << "read() failed";
+    }
 
     if (n <= 0) {
         return false;
@@ -53,6 +95,10 @@
     return true;
 }
 
+void PipeRelay::RelayThread::setFinished() {
+    mFinished = true;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 PipeRelay::PipeRelay(std::ostream &os)
@@ -77,12 +123,14 @@
 
 PipeRelay::~PipeRelay() {
     CloseFd(&mFds[1]);
-    CloseFd(&mFds[0]);
 
     if (mThread != nullptr) {
+        mThread->setFinished();
         mThread->join();
         mThread.clear();
     }
+
+    CloseFd(&mFds[0]);
 }
 
 status_t PipeRelay::initCheck() const {
diff --git a/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h b/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h
deleted file mode 100644
index b32c92e..0000000
--- a/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IARC_VIDEO_BRIDGE_H
-#define ANDROID_IARC_VIDEO_BRIDGE_H
-
-#include <arc/IArcBridgeService.h>
-#include <binder/IInterface.h>
-#include <utils/Errors.h>
-
-namespace android {
-
-class IArcVideoBridge : public IInterface {
-public:
-    DECLARE_META_INTERFACE(ArcVideoBridge);
-
-    // Returns MojoBootstrapResult for creating mojo ipc channel of
-    // VideoAcceleratorFactory.
-    virtual ::arc::MojoBootstrapResult bootstrapVideoAcceleratorFactory() = 0;
-
-    // Get the version of the remote VideoHost on Chromium side.
-    virtual int32_t hostVersion() = 0;
-};
-
-class BnArcVideoBridge : public BnInterface<IArcVideoBridge> {
-public:
-    virtual status_t onTransact(
-            uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
-};
-
-};  // namespace android
-
-#endif // ANDROID_IARC_VIDEO_BRIDGE_H
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 61b8818..da10687 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -119,6 +119,7 @@
         "liblog",
         "libcutils",
         "libutils",
+        "libbinderthreadstate",
     ],
 
     header_libs: [
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index b2217b5..f052bcb 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "IPCThreadState"
 
 #include <binder/IPCThreadState.h>
+#include <binderthreadstate/IPCThreadStateBase.h>
 
 #include <binder/Binder.h>
 #include <binder/BpBinder.h>
@@ -742,6 +743,7 @@
     clearCaller();
     mIn.setDataCapacity(256);
     mOut.setDataCapacity(256);
+    mIPCThreadStateBase = IPCThreadStateBase::self();
 }
 
 IPCThreadState::~IPCThreadState()
@@ -1082,6 +1084,9 @@
                 "Not enough command data for brTRANSACTION");
             if (result != NO_ERROR) break;
 
+            //Record the fact that we're in a binder call.
+            mIPCThreadStateBase->pushCurrentState(
+                IPCThreadStateBase::CallState::BINDER);
             Parcel buffer;
             buffer.ipcSetDataReference(
                 reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
@@ -1129,6 +1134,7 @@
                 error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
             }
 
+            mIPCThreadStateBase->popCurrentState();
             //ALOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n",
             //     mCallingPid, origPid, origUid);
 
@@ -1192,6 +1198,10 @@
     return result;
 }
 
+bool IPCThreadState::isServingCall() const {
+    return mIPCThreadStateBase->getCurrentBinderCallState() == IPCThreadStateBase::CallState::BINDER;
+}
+
 void IPCThreadState::threadDestructor(void *st)
 {
         IPCThreadState* const self = static_cast<IPCThreadState*>(st);
diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp
index a9d5055..a3f8755 100644
--- a/libs/binder/Status.cpp
+++ b/libs/binder/Status.cpp
@@ -24,11 +24,17 @@
 }
 
 Status Status::fromExceptionCode(int32_t exceptionCode) {
+    if (exceptionCode == EX_TRANSACTION_FAILED) {
+        return Status(exceptionCode, FAILED_TRANSACTION);
+    }
     return Status(exceptionCode, OK);
 }
 
 Status Status::fromExceptionCode(int32_t exceptionCode,
                                  const String8& message) {
+    if (exceptionCode == EX_TRANSACTION_FAILED) {
+        return Status(exceptionCode, FAILED_TRANSACTION, message);
+    }
     return Status(exceptionCode, OK, message);
 }
 
@@ -158,7 +164,7 @@
 
 void Status::setException(int32_t ex, const String8& message) {
     mException = ex;
-    mErrorCode = NO_ERROR;  // an exception, not a transaction failure.
+    mErrorCode = ex == EX_TRANSACTION_FAILED ? FAILED_TRANSACTION : NO_ERROR;
     mMessage.setTo(message);
 }
 
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index dce3f38..40b51ad 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -29,6 +29,8 @@
 // ---------------------------------------------------------------------------
 namespace android {
 
+class IPCThreadStateBase;
+
 class IPCThreadState
 {
 public:
@@ -89,6 +91,33 @@
             // the maximum number of binder threads threads allowed for this process.
             void                blockUntilThreadAvailable();
 
+
+            // Is this thread currently serving a binder call. This method
+            // returns true if while traversing backwards from the function call
+            // stack for this thread, we encounter a function serving a binder
+            // call before encountering a hwbinder call / hitting the end of the
+            // call stack.
+            // Eg: If thread T1 went through the following call pattern
+            //     1) T1 receives and executes hwbinder call H1.
+            //     2) While handling H1, T1 makes binder call B1.
+            //     3) The handler of B1, calls into T1 with a callback B2.
+            // If isServingCall() is called during H1 before 3), this method
+            // will return false, else true.
+            //
+            //  ----
+            // | B2 | ---> While callback B2 is being handled, during 3).
+            //  ----
+            // | H1 | ---> While H1 is being handled.
+            //  ----
+            // Fig: Thread Call stack while handling B2
+            //
+            // This is since after 3), while traversing the thread call stack,
+            // we hit a binder call before a hwbinder call / end of stack. This
+            // method may be typically used to determine whether to use
+            // hardware::IPCThreadState methods or IPCThreadState methods to
+            // infer information about thread state.
+            bool                isServingCall() const;
+
 private:
                                 IPCThreadState();
                                 ~IPCThreadState();
@@ -128,6 +157,7 @@
             uid_t               mCallingUid;
             int32_t             mStrictModePolicy;
             int32_t             mLastTransactionBinderFlags;
+            IPCThreadStateBase  *mIPCThreadStateBase;
 };
 
 }; // namespace android
diff --git a/libs/binder/include/binder/ParcelFileDescriptor.h b/libs/binder/include/binder/ParcelFileDescriptor.h
index 455462b..ad950af 100644
--- a/libs/binder/include/binder/ParcelFileDescriptor.h
+++ b/libs/binder/include/binder/ParcelFileDescriptor.h
@@ -31,6 +31,7 @@
 public:
     ParcelFileDescriptor();
     explicit ParcelFileDescriptor(android::base::unique_fd fd);
+    explicit ParcelFileDescriptor(ParcelFileDescriptor&& other) : mFd(std::move(other.mFd)) { }
     ~ParcelFileDescriptor() override;
 
     int get() const { return mFd.get(); }
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 459b6b5..5461b4f 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -25,6 +25,7 @@
 
     srcs: [
         "ibinder.cpp",
+        "ibinder_jni.cpp",
         "parcel.cpp",
         "process.cpp",
         "status.cpp",
@@ -32,8 +33,25 @@
     ],
 
     shared_libs: [
+        "libandroid_runtime",
         "libbase",
         "libbinder",
         "libutils",
     ],
 }
+
+ndk_headers {
+    name: "libbinder_ndk_headers",
+    from: "include_ndk/android",
+    to: "android",
+    srcs: [
+        "include_ndk/android/*.h",
+    ],
+    license: "NOTICE",
+}
+
+ndk_library {
+    name: "libbinder_ndk",
+    symbol_file: "libbinder_ndk.map.txt",
+    first_version: "29",
+}
diff --git a/libs/binder/ndk/NOTICE b/libs/binder/ndk/NOTICE
new file mode 100644
index 0000000..d1ab54c
--- /dev/null
+++ b/libs/binder/ndk/NOTICE
@@ -0,0 +1,189 @@
+
+   Copyright (c) 2018, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index b1b4194..896c5c1 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -122,7 +122,7 @@
                               binder_flags_t flags) {
     if (isUserCommand(code)) {
         if (!data.checkInterface(this)) {
-            return STATUS_PERMISSION_DENIED;
+            return STATUS_BAD_TYPE;
         }
 
         const AParcel in = AParcel::readOnly(this, &data);
@@ -198,13 +198,8 @@
 
     return new AIBinder_Weak{wp<AIBinder>(binder)};
 }
-void AIBinder_Weak_delete(AIBinder_Weak** weakBinder) {
-    if (weakBinder == nullptr) {
-        return;
-    }
-
-    delete *weakBinder;
-    *weakBinder = nullptr;
+void AIBinder_Weak_delete(AIBinder_Weak* weakBinder) {
+    delete weakBinder;
 }
 AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder) {
     if (weakBinder == nullptr) {
@@ -437,6 +432,11 @@
     return ret;
 }
 
+static void DestroyParcel(AParcel** parcel) {
+    delete *parcel;
+    *parcel = nullptr;
+}
+
 binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
                                   AParcel** out, binder_flags_t flags) {
     if (in == nullptr) {
@@ -447,7 +447,7 @@
     using AutoParcelDestroyer = std::unique_ptr<AParcel*, void (*)(AParcel**)>;
     // This object is the input to the transaction. This function takes ownership of it and deletes
     // it.
-    AutoParcelDestroyer forIn(in, AParcel_delete);
+    AutoParcelDestroyer forIn(in, DestroyParcel);
 
     if (!isUserCommand(code)) {
         LOG(ERROR) << __func__ << ": Only user-defined transactions can be made from the NDK.";
@@ -492,11 +492,6 @@
     return new AIBinder_DeathRecipient(onBinderDied);
 }
 
-void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient** recipient) {
-    if (recipient == nullptr) {
-        return;
-    }
-
-    delete *recipient;
-    *recipient = nullptr;
+void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) {
+    delete recipient;
 }
diff --git a/libs/binder/ndk/ibinder_jni.cpp b/libs/binder/ndk/ibinder_jni.cpp
new file mode 100644
index 0000000..baea2e8
--- /dev/null
+++ b/libs/binder/ndk/ibinder_jni.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/binder_ibinder_jni.h>
+#include "ibinder_internal.h"
+
+#include <android_util_Binder.h>
+
+using ::android::IBinder;
+using ::android::ibinderForJavaObject;
+using ::android::javaObjectForIBinder;
+using ::android::sp;
+
+AIBinder* AIBinder_fromJavaBinder(JNIEnv* env, jobject binder) {
+    sp<IBinder> ibinder = ibinderForJavaObject(env, binder);
+
+    sp<AIBinder> cbinder = ABpBinder::lookupOrCreateFromBinder(ibinder);
+    AIBinder_incStrong(cbinder.get());
+
+    return cbinder.get();
+}
+
+jobject AIBinder_toJavaBinder(JNIEnv* env, AIBinder* binder) {
+    if (binder == nullptr) {
+        return nullptr;
+    }
+
+    return javaObjectForIBinder(env, binder->getBinder());
+}
diff --git a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
new file mode 100644
index 0000000..cc0a29d
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_auto_utils.h
+ * @brief These objects provide a more C++-like thin interface to the .
+ */
+
+#pragma once
+
+#include <android/binder_ibinder.h>
+#include <android/binder_parcel.h>
+#include <android/binder_status.h>
+
+#include <assert.h>
+
+#ifdef __cplusplus
+
+#include <cstddef>
+
+namespace ndk {
+
+/**
+ * Represents one strong pointer to an AIBinder object.
+ */
+class SpAIBinder {
+public:
+    /**
+     * Takes ownership of one strong refcount of binder.
+     */
+    explicit SpAIBinder(AIBinder* binder = nullptr) : mBinder(binder) {}
+
+    /**
+     * Convenience operator for implicitly constructing an SpAIBinder from nullptr. This is not
+     * explicit because it is not taking ownership of anything.
+     */
+    SpAIBinder(std::nullptr_t) : SpAIBinder() {}
+
+    /**
+     * This will delete the underlying object if it exists. See operator=.
+     */
+    SpAIBinder(const SpAIBinder& other) { *this = other; }
+
+    /**
+     * This deletes the underlying object if it exists. See set.
+     */
+    ~SpAIBinder() { set(nullptr); }
+
+    /**
+     * This takes ownership of a binder from another AIBinder object but it does not affect the
+     * ownership of that other object.
+     */
+    SpAIBinder& operator=(const SpAIBinder& other) {
+        AIBinder_incStrong(other.mBinder);
+        set(other.mBinder);
+        return *this;
+    }
+
+    /**
+     * Takes ownership of one strong refcount of binder
+     */
+    void set(AIBinder* binder) {
+        AIBinder* old = *const_cast<AIBinder* volatile*>(&mBinder);
+        if (old != nullptr) AIBinder_decStrong(old);
+        if (old != *const_cast<AIBinder* volatile*>(&mBinder)) {
+            __assert(__FILE__, __LINE__, "Race detected.");
+        }
+        mBinder = binder;
+    }
+
+    /**
+     * This returns the underlying binder object for transactions. If it is used to create another
+     * SpAIBinder object, it should first be incremented.
+     */
+    AIBinder* get() const { return mBinder; }
+
+    /**
+     * This allows the value in this class to be set from beneath it. If you call this method and
+     * then change the value of T*, you must take ownership of the value you are replacing and add
+     * ownership to the object that is put in here.
+     *
+     * Recommended use is like this:
+     *   SpAIBinder a;  // will be nullptr
+     *   SomeInitFunction(a.getR());  // value is initialized with refcount
+     *
+     * Other usecases are discouraged.
+     *
+     */
+    AIBinder** getR() { return &mBinder; }
+
+private:
+    AIBinder* mBinder = nullptr;
+};
+
+/**
+ * This baseclass owns a single object, used to make various classes RAII.
+ */
+template <typename T, void (*Destroy)(T*)>
+class ScopedAResource {
+public:
+    /**
+     * Takes ownership of t.
+     */
+    explicit ScopedAResource(T* t = nullptr) : mT(t) {}
+
+    /**
+     * This deletes the underlying object if it exists. See set.
+     */
+    ~ScopedAResource() { set(nullptr); }
+
+    /**
+     * Takes ownership of t.
+     */
+    void set(T* t) {
+        Destroy(mT);
+        mT = t;
+    }
+
+    /**
+     * This returns the underlying object to be modified but does not affect ownership.
+     */
+    T* get() { return mT; }
+
+    /**
+     * This returns the const underlying object but does not affect ownership.
+     */
+    const T* get() const { return mT; }
+
+    /**
+     * This allows the value in this class to be set from beneath it. If you call this method and
+     * then change the value of T*, you must take ownership of the value you are replacing and add
+     * ownership to the object that is put in here.
+     *
+     * Recommended use is like this:
+     *   ScopedAResource<T> a; // will be nullptr
+     *   SomeInitFunction(a.getR()); // value is initialized with refcount
+     *
+     * Other usecases are discouraged.
+     *
+     */
+    T** getR() { return &mT; }
+
+    // copy-constructing, or move/copy assignment is disallowed
+    ScopedAResource(const ScopedAResource&) = delete;
+    ScopedAResource& operator=(const ScopedAResource&) = delete;
+    ScopedAResource& operator=(ScopedAResource&&) = delete;
+
+    // move-constructing is okay
+    ScopedAResource(ScopedAResource&&) = default;
+
+private:
+    T* mT;
+};
+
+/**
+ * Convenience wrapper. See AParcel.
+ */
+class ScopedAParcel : public ScopedAResource<AParcel, AParcel_delete> {
+public:
+    /**
+     * Takes ownership of a.
+     */
+    explicit ScopedAParcel(AParcel* a = nullptr) : ScopedAResource(a) {}
+    ~ScopedAParcel() {}
+    ScopedAParcel(ScopedAParcel&&) = default;
+};
+
+/**
+ * Convenience wrapper. See AStatus.
+ */
+class ScopedAStatus : public ScopedAResource<AStatus, AStatus_delete> {
+public:
+    /**
+     * Takes ownership of a.
+     */
+    explicit ScopedAStatus(AStatus* a = nullptr) : ScopedAResource(a) {}
+    ~ScopedAStatus() {}
+    ScopedAStatus(ScopedAStatus&&) = default;
+
+    /**
+     * See AStatus_isOk.
+     */
+    bool isOk() { return get() != nullptr && AStatus_isOk(get()); }
+};
+
+/**
+ * Convenience wrapper. See AIBinder_DeathRecipient.
+ */
+class ScopedAIBinder_DeathRecipient
+      : public ScopedAResource<AIBinder_DeathRecipient, AIBinder_DeathRecipient_delete> {
+public:
+    /**
+     * Takes ownership of a.
+     */
+    explicit ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient* a = nullptr)
+          : ScopedAResource(a) {}
+    ~ScopedAIBinder_DeathRecipient() {}
+    ScopedAIBinder_DeathRecipient(ScopedAIBinder_DeathRecipient&&) = default;
+};
+
+/**
+ * Convenience wrapper. See AIBinder_Weak.
+ */
+class ScopedAIBinder_Weak : public ScopedAResource<AIBinder_Weak, AIBinder_Weak_delete> {
+public:
+    /**
+     * Takes ownership of a.
+     */
+    explicit ScopedAIBinder_Weak(AIBinder_Weak* a = nullptr) : ScopedAResource(a) {}
+    ~ScopedAIBinder_Weak() {}
+    ScopedAIBinder_Weak(ScopedAIBinder_Weak&&) = default;
+
+    /**
+     * See AIBinder_Weak_promote.
+     */
+    SpAIBinder promote() { return SpAIBinder(AIBinder_Weak_promote(get())); }
+};
+
+} // namespace ndk
+
+#endif // __cplusplus
+
+/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index 5081248..c222c16 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -33,6 +33,7 @@
 #include <android/binder_status.h>
 
 __BEGIN_DECLS
+#if __ANDROID_API__ >= __ANDROID_API_Q__
 
 // Also see TF_* in kernel's binder.h
 typedef uint32_t binder_flags_t;
@@ -154,7 +155,8 @@
  */
 __attribute__((warn_unused_result)) AIBinder_Class* AIBinder_Class_define(
         const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
-        AIBinder_Class_onDestroy onDestroy, AIBinder_Class_onTransact onTransact);
+        AIBinder_Class_onDestroy onDestroy, AIBinder_Class_onTransact onTransact)
+        __INTRODUCED_IN(29);
 
 /**
  * Creates a new binder object of the appropriate class.
@@ -173,12 +175,13 @@
  * these two objects are actually equal using the AIBinder pointer alone (which they should be able
  * to do). Also see the suggested memory ownership model suggested above.
  */
-__attribute__((warn_unused_result)) AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args);
+__attribute__((warn_unused_result)) AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args)
+        __INTRODUCED_IN(29);
 
 /**
  * If this is hosted in a process other than the current one.
  */
-bool AIBinder_isRemote(const AIBinder* binder);
+bool AIBinder_isRemote(const AIBinder* binder) __INTRODUCED_IN(29);
 
 /**
  * If this binder is known to be alive. This will not send a transaction to a remote process and
@@ -187,14 +190,14 @@
  * updated as the result of a transaction made using AIBinder_transact, but it will also be updated
  * based on the results of bookkeeping or other transactions made internally.
  */
-bool AIBinder_isAlive(const AIBinder* binder);
+bool AIBinder_isAlive(const AIBinder* binder) __INTRODUCED_IN(29);
 
 /**
  * Built-in transaction for all binder objects. This sends a transaction which will immediately
  * return. Usually this is used to make sure that a binder is alive, as a placeholder call, or as a
  * sanity check.
  */
-binder_status_t AIBinder_ping(AIBinder* binder);
+binder_status_t AIBinder_ping(AIBinder* binder) __INTRODUCED_IN(29);
 
 /**
  * Registers for notifications that the associated binder is dead. The same death recipient may be
@@ -204,9 +207,11 @@
  * null. The exact cookie must also be used to unlink this transaction (see AIBinder_linkToDeath).
  * This function may return a binder transaction failure. The cookie can be used both for
  * identification and holding user data.
+ *
+ * If binder is local, this will return STATUS_INVALID_OPERATION.
  */
 binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
-                                     void* cookie);
+                                     void* cookie) __INTRODUCED_IN(29);
 
 /**
  * Stops registration for the associated binder dying. Does not delete the recipient. This function
@@ -214,22 +219,22 @@
  * returns STATUS_NAME_NOT_FOUND.
  */
 binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
-                                       void* cookie);
+                                       void* cookie) __INTRODUCED_IN(29);
 
 /**
  * This can only be called if a strong reference to this object already exists in process.
  */
-void AIBinder_incStrong(AIBinder* binder);
+void AIBinder_incStrong(AIBinder* binder) __INTRODUCED_IN(29);
 
 /**
  * This will delete the object and call onDestroy once the refcount reaches zero.
  */
-void AIBinder_decStrong(AIBinder* binder);
+void AIBinder_decStrong(AIBinder* binder) __INTRODUCED_IN(29);
 
 /**
  * For debugging only!
  */
-int32_t AIBinder_debugGetRefCount(AIBinder* binder);
+int32_t AIBinder_debugGetRefCount(AIBinder* binder) __INTRODUCED_IN(29);
 
 /**
  * This sets the class of an AIBinder object. This checks to make sure the remote object is of
@@ -240,18 +245,18 @@
  * This returns true if the class association succeeds. If it fails, no change is made to the
  * binder object.
  */
-bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz);
+bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz) __INTRODUCED_IN(29);
 
 /**
  * Returns the class that this binder was constructed with or associated with.
  */
-const AIBinder_Class* AIBinder_getClass(AIBinder* binder);
+const AIBinder_Class* AIBinder_getClass(AIBinder* binder) __INTRODUCED_IN(29);
 
 /**
  * Value returned by onCreate for a local binder. For stateless classes (if onCreate returns
  * nullptr), this also returns nullptr. For a remote binder, this will always return nullptr.
  */
-void* AIBinder_getUserData(AIBinder* binder);
+void* AIBinder_getUserData(AIBinder* binder) __INTRODUCED_IN(29);
 
 /**
  * A transaction is a series of calls to these functions which looks this
@@ -274,7 +279,7 @@
  * AIBinder_transact. Alternatively, if there is an error while filling out the parcel, it can be
  * deleted with AParcel_delete.
  */
-binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in);
+binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) __INTRODUCED_IN(29);
 
 /**
  * Transact using a parcel created from AIBinder_prepareTransaction. This actually communicates with
@@ -289,42 +294,45 @@
  * and must be released with AParcel_delete when finished reading.
  */
 binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
-                                  AParcel** out, binder_flags_t flags);
+                                  AParcel** out, binder_flags_t flags) __INTRODUCED_IN(29);
 
 /**
  * This does not take any ownership of the input binder, but it can be used to retrieve it if
  * something else in some process still holds a reference to it.
  */
-__attribute__((warn_unused_result)) AIBinder_Weak* AIBinder_Weak_new(AIBinder* binder);
+__attribute__((warn_unused_result)) AIBinder_Weak* AIBinder_Weak_new(AIBinder* binder)
+        __INTRODUCED_IN(29);
 
 /**
  * Deletes the weak reference. This will have no impact on the lifetime of the binder.
  */
-void AIBinder_Weak_delete(AIBinder_Weak** weakBinder);
+void AIBinder_Weak_delete(AIBinder_Weak* weakBinder) __INTRODUCED_IN(29);
 
 /**
  * If promotion succeeds, result will have one strong refcount added to it. Otherwise, this returns
  * nullptr.
  */
-__attribute__((warn_unused_result)) AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder);
+__attribute__((warn_unused_result)) AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder)
+        __INTRODUCED_IN(29);
 
 /**
  * This function is executed on death receipt. See AIBinder_linkToDeath/AIBinder_unlinkToDeath.
  */
-typedef void (*AIBinder_DeathRecipient_onBinderDied)(void* cookie);
+typedef void (*AIBinder_DeathRecipient_onBinderDied)(void* cookie) __INTRODUCED_IN(29);
 
 /**
  * Creates a new binder death recipient. This can be attached to multiple different binder objects.
  */
 __attribute__((warn_unused_result)) AIBinder_DeathRecipient* AIBinder_DeathRecipient_new(
-        AIBinder_DeathRecipient_onBinderDied onBinderDied);
+        AIBinder_DeathRecipient_onBinderDied onBinderDied) __INTRODUCED_IN(29);
 
 /**
  * Deletes a binder death recipient. It is not necessary to call AIBinder_unlinkToDeath before
  * calling this as these will all be automatically unlinked.
  */
-void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient** recipient);
+void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) __INTRODUCED_IN(29);
 
+#endif //__ANDROID_API__ >= __ANDROID_API_Q__
 __END_DECLS
 
 /** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
new file mode 100644
index 0000000..81fb3c5
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_ibinder_jni.h
+ * @brief Conversions between AIBinder and android.os.IBinder
+ */
+
+#pragma once
+
+#include <android/binder_ibinder.h>
+
+#include <jni.h>
+
+__BEGIN_DECLS
+#if __ANDROID_API__ >= __ANDROID_API_Q__
+
+/**
+ * Converts an android.os.IBinder object into an AIBinder* object.
+ *
+ * If either env or the binder is null, null is returned. If this binder object was originally an
+ * AIBinder object, the original object is returned. The returned object has one refcount
+ * associated with it, and so this should be accompanied with an AIBinder_decStrong call.
+ */
+__attribute__((warn_unused_result)) AIBinder* AIBinder_fromJavaBinder(JNIEnv* env, jobject binder)
+        __INTRODUCED_IN(29);
+
+/**
+ * Converts an AIBinder* object into an android.os.IBinder object.
+ *
+ * If either env or the binder is null, null is returned. If this binder object was originally an
+ * IBinder object, the original java object will be returned.
+ */
+__attribute__((warn_unused_result)) jobject AIBinder_toJavaBinder(JNIEnv* env, AIBinder* binder)
+        __INTRODUCED_IN(29);
+
+#endif //__ANDROID_API__ >= __ANDROID_API_Q__
+__END_DECLS
+
+/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
new file mode 100644
index 0000000..1a9018a
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_interface_utils.h
+ * @brief This provides common C++ classes for common operations and as base classes for C++
+ * interfaces.
+ */
+
+#pragma once
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_ibinder.h>
+
+#include <assert.h>
+
+#ifdef __cplusplus
+
+#include <memory>
+#include <mutex>
+
+namespace ndk {
+
+/**
+ * analog using std::shared_ptr for internally held refcount
+ *
+ * ref must be called at least one time during the lifetime of this object. The recommended way to construct
+ * this object is with SharedRefBase::make.
+ */
+class SharedRefBase {
+public:
+    SharedRefBase() {}
+    virtual ~SharedRefBase() {
+        std::call_once(mFlagThis, [&]() {
+            __assert(__FILE__, __LINE__, "SharedRefBase: no ref created during lifetime");
+        });
+    }
+
+    /**
+     * A shared_ptr must be held to this object when this is called. This must be called once during
+     * the lifetime of this object.
+     */
+    std::shared_ptr<SharedRefBase> ref() {
+        std::shared_ptr<SharedRefBase> thiz = mThis.lock();
+
+        std::call_once(mFlagThis, [&]() { mThis = thiz = std::shared_ptr<SharedRefBase>(this); });
+
+        return thiz;
+    }
+
+    /**
+     * Convenience method for a ref (see above) which automatically casts to the desired child type.
+     */
+    template <typename CHILD>
+    std::shared_ptr<CHILD> ref() {
+        return std::static_pointer_cast<CHILD>(ref());
+    }
+
+    /**
+     * Convenience method for making an object directly with a reference.
+     */
+    template<class T, class... Args>
+    static std::shared_ptr<T> make(Args&&... args) {
+        T* t = new T(std::forward<Args>(args)...);
+        return t->template ref<T>();
+    }
+
+private:
+    std::once_flag mFlagThis;
+    std::weak_ptr<SharedRefBase> mThis;
+};
+
+/**
+ * wrapper analog to IInterface
+ */
+class ICInterface : public SharedRefBase {
+public:
+    ICInterface() {}
+    virtual ~ICInterface() {}
+
+    /**
+     * This either returns the single existing implementation or creates a new implementation.
+     */
+    virtual SpAIBinder asBinder() = 0;
+
+    /**
+     * Returns whether this interface is in a remote process. If it cannot be determined locally,
+     * this will be checked using AIBinder_isRemote.
+     */
+    virtual bool isRemote() = 0;
+};
+
+/**
+ * implementation of IInterface for server (n = native)
+ */
+template <typename INTERFACE>
+class BnCInterface : public INTERFACE {
+public:
+    BnCInterface() {}
+    virtual ~BnCInterface() {}
+
+    SpAIBinder asBinder() override;
+
+    bool isRemote() override { return true; }
+
+protected:
+    /**
+     * This function should only be called by asBinder. Otherwise, there is a possibility of
+     * multiple AIBinder* objects being created for the same instance of an object.
+     */
+    virtual SpAIBinder createBinder() = 0;
+
+private:
+    std::mutex mMutex; // for asBinder
+    ScopedAIBinder_Weak mWeakBinder;
+};
+
+/**
+ * implementation of IInterface for client (p = proxy)
+ */
+template <typename INTERFACE>
+class BpCInterface : public INTERFACE {
+public:
+    BpCInterface(const SpAIBinder& binder) : mBinder(binder) {}
+    virtual ~BpCInterface() {}
+
+    SpAIBinder asBinder() override;
+
+    bool isRemote() override { return AIBinder_isRemote(mBinder.get()); }
+
+private:
+    SpAIBinder mBinder;
+};
+
+template <typename INTERFACE>
+SpAIBinder BnCInterface<INTERFACE>::asBinder() {
+    std::lock_guard<std::mutex> l(mMutex);
+
+    SpAIBinder binder;
+    if (mWeakBinder.get() != nullptr) {
+        binder.set(AIBinder_Weak_promote(mWeakBinder.get()));
+    }
+    if (binder.get() == nullptr) {
+        binder = createBinder();
+        mWeakBinder.set(AIBinder_Weak_new(binder.get()));
+    }
+
+    return binder;
+}
+
+template <typename INTERFACE>
+SpAIBinder BpCInterface<INTERFACE>::asBinder() {
+    return mBinder;
+}
+
+} // namespace ndk
+
+#endif // __cplusplus
+
+/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index e871ed1..0e97b50 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -34,6 +34,7 @@
 typedef struct AIBinder AIBinder;
 
 __BEGIN_DECLS
+#if __ANDROID_API__ >= __ANDROID_API_Q__
 
 /**
  * This object represents a package of data that can be sent between processes. When transacting, an
@@ -45,120 +46,179 @@
 typedef struct AParcel AParcel;
 
 /**
- * Cleans up a parcel and sets it to nullptr.
+ * Cleans up a parcel.
  */
-void AParcel_delete(AParcel** parcel);
+void AParcel_delete(AParcel* parcel) __INTRODUCED_IN(29);
 
 /**
  * Writes an AIBinder to the next location in a non-null parcel. Can be null.
  */
-binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder);
+binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) __INTRODUCED_IN(29);
 
 /**
  * Reads an AIBinder from the next location in a non-null parcel. This will fail if the binder is
  * non-null. One strong ref-count of ownership is passed to the caller of this function.
  */
-binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder);
+binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder)
+        __INTRODUCED_IN(29);
 
 /**
  * Reads an AIBinder from the next location in a non-null parcel. This may read a null. One strong
  * ref-count of ownership is passed to the caller of this function.
  */
-binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder);
+binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder)
+        __INTRODUCED_IN(29);
+
+/**
+ * Writes an AStatus object to the next location in a non-null parcel.
+ *
+ * If the status is considered to be a low-level status and has no additional information other
+ * than a binder_status_t (for instance, if it is created with AStatus_fromStatus), then that
+ * status will be returned from this method and nothing will be written to the parcel. If either
+ * this happens or if writing the status object itself fails, the return value from this function
+ * should be propagated to the client, and AParcel_readStatusHeader shouldn't be called.
+ */
+binder_status_t AParcel_writeStatusHeader(AParcel* parcel, const AStatus* status)
+        __INTRODUCED_IN(29);
+
+/**
+ * Reads an AStatus from the next location in a non-null parcel. Ownership is passed to the caller
+ * of this function.
+ */
+binder_status_t AParcel_readStatusHeader(const AParcel* parcel, AStatus** status)
+        __INTRODUCED_IN(29);
+
+/**
+ * Writes string value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeString(AParcel* parcel, const char* string, size_t length)
+        __INTRODUCED_IN(29);
+
+/**
+ * This is called to allocate a buffer
+ *
+ * The length here includes the space required to insert a '\0' for a properly formed c-str. If the
+ * buffer returned from this function is retStr, it will be filled by AParcel_readString with the
+ * data from the remote process, and it will be filled such that retStr[length] == '\0'.
+ *
+ * If allocation fails, null should be returned.
+ */
+typedef void* (*AParcel_string_reallocator)(void* stringData, size_t length);
+
+/**
+ * This is called to get the buffer from a stringData object.
+ */
+typedef char* (*AParcel_string_getter)(void* stringData);
+
+/**
+ * Reads and allocates string value from the next location in a non-null parcel.
+ *
+ * Data is passed to the string allocator once the string size is known. This data should be used to
+ * point to some kind of string data. For instance, it could be a char*, and the string allocator
+ * could be realloc. Then the getter would simply be a cast to char*. In more complicated cases,
+ * stringData could be a structure containing additional string data.
+ *
+ * If this function returns a success, the buffer returned by allocator when passed stringData will
+ * contain a null-terminated c-str read from the binder.
+ */
+binder_status_t AParcel_readString(const AParcel* parcel, AParcel_string_reallocator reallocator,
+                                   AParcel_string_getter getter, void** stringData)
+        __INTRODUCED_IN(29);
 
 // @START
 /**
  * Writes int32_t value to the next location in a non-null parcel.
  */
-binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value);
+binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value) __INTRODUCED_IN(29);
 
 /**
  * Writes uint32_t value to the next location in a non-null parcel.
  */
-binder_status_t AParcel_writeUint32(AParcel* parcel, uint32_t value);
+binder_status_t AParcel_writeUint32(AParcel* parcel, uint32_t value) __INTRODUCED_IN(29);
 
 /**
  * Writes int64_t value to the next location in a non-null parcel.
  */
-binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value);
+binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value) __INTRODUCED_IN(29);
 
 /**
  * Writes uint64_t value to the next location in a non-null parcel.
  */
-binder_status_t AParcel_writeUint64(AParcel* parcel, uint64_t value);
+binder_status_t AParcel_writeUint64(AParcel* parcel, uint64_t value) __INTRODUCED_IN(29);
 
 /**
  * Writes float value to the next location in a non-null parcel.
  */
-binder_status_t AParcel_writeFloat(AParcel* parcel, float value);
+binder_status_t AParcel_writeFloat(AParcel* parcel, float value) __INTRODUCED_IN(29);
 
 /**
  * Writes double value to the next location in a non-null parcel.
  */
-binder_status_t AParcel_writeDouble(AParcel* parcel, double value);
+binder_status_t AParcel_writeDouble(AParcel* parcel, double value) __INTRODUCED_IN(29);
 
 /**
  * Writes bool value to the next location in a non-null parcel.
  */
-binder_status_t AParcel_writeBool(AParcel* parcel, bool value);
+binder_status_t AParcel_writeBool(AParcel* parcel, bool value) __INTRODUCED_IN(29);
 
 /**
  * Writes char16_t value to the next location in a non-null parcel.
  */
-binder_status_t AParcel_writeChar(AParcel* parcel, char16_t value);
+binder_status_t AParcel_writeChar(AParcel* parcel, char16_t value) __INTRODUCED_IN(29);
 
 /**
  * Writes int8_t value to the next location in a non-null parcel.
  */
-binder_status_t AParcel_writeByte(AParcel* parcel, int8_t value);
+binder_status_t AParcel_writeByte(AParcel* parcel, int8_t value) __INTRODUCED_IN(29);
 
 /**
  * Reads into int32_t value from the next location in a non-null parcel.
  */
-binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value);
+binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value) __INTRODUCED_IN(29);
 
 /**
  * Reads into uint32_t value from the next location in a non-null parcel.
  */
-binder_status_t AParcel_readUint32(const AParcel* parcel, uint32_t* value);
+binder_status_t AParcel_readUint32(const AParcel* parcel, uint32_t* value) __INTRODUCED_IN(29);
 
 /**
  * Reads into int64_t value from the next location in a non-null parcel.
  */
-binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value);
+binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value) __INTRODUCED_IN(29);
 
 /**
  * Reads into uint64_t value from the next location in a non-null parcel.
  */
-binder_status_t AParcel_readUint64(const AParcel* parcel, uint64_t* value);
+binder_status_t AParcel_readUint64(const AParcel* parcel, uint64_t* value) __INTRODUCED_IN(29);
 
 /**
  * Reads into float value from the next location in a non-null parcel.
  */
-binder_status_t AParcel_readFloat(const AParcel* parcel, float* value);
+binder_status_t AParcel_readFloat(const AParcel* parcel, float* value) __INTRODUCED_IN(29);
 
 /**
  * Reads into double value from the next location in a non-null parcel.
  */
-binder_status_t AParcel_readDouble(const AParcel* parcel, double* value);
+binder_status_t AParcel_readDouble(const AParcel* parcel, double* value) __INTRODUCED_IN(29);
 
 /**
  * Reads into bool value from the next location in a non-null parcel.
  */
-binder_status_t AParcel_readBool(const AParcel* parcel, bool* value);
+binder_status_t AParcel_readBool(const AParcel* parcel, bool* value) __INTRODUCED_IN(29);
 
 /**
  * Reads into char16_t value from the next location in a non-null parcel.
  */
-binder_status_t AParcel_readChar(const AParcel* parcel, char16_t* value);
+binder_status_t AParcel_readChar(const AParcel* parcel, char16_t* value) __INTRODUCED_IN(29);
 
 /**
  * Reads into int8_t value from the next location in a non-null parcel.
  */
-binder_status_t AParcel_readByte(const AParcel* parcel, int8_t* value);
+binder_status_t AParcel_readByte(const AParcel* parcel, int8_t* value) __INTRODUCED_IN(29);
 
 // @END
 
+#endif //__ANDROID_API__ >= __ANDROID_API_Q__
 __END_DECLS
 
 /** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
new file mode 100644
index 0000000..d3e6cae
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_parcel_utils.h
+ * @brief A collection of helper wrappers for AParcel.
+ */
+
+#pragma once
+
+#include <android/binder_parcel.h>
+
+#ifdef __cplusplus
+
+#include <string>
+
+namespace ndk {
+
+/**
+ * Takes a std::string and reallocates it to the specified length. For use with AParcel_readString.
+ * See use below in AParcel_readString.
+ */
+static inline void* AParcel_std_string_reallocator(void* stringData, size_t length) {
+    std::string* str = static_cast<std::string*>(stringData);
+    str->resize(length - 1);
+    return stringData;
+}
+
+/**
+ * Takes a std::string and returns the inner char*.
+ */
+static inline char* AParcel_std_string_getter(void* stringData) {
+    std::string* str = static_cast<std::string*>(stringData);
+    return &(*str)[0];
+}
+
+/**
+ * Convenience API for writing a std::string.
+ */
+static inline binder_status_t AParcel_writeString(AParcel* parcel, const std::string& str) {
+    return AParcel_writeString(parcel, str.c_str(), str.size());
+}
+
+/**
+ * Convenience API for reading a std::string.
+ */
+static inline binder_status_t AParcel_readString(const AParcel* parcel, std::string* str) {
+    void* stringData = static_cast<void*>(str);
+    return AParcel_readString(parcel, AParcel_std_string_reallocator, AParcel_std_string_getter,
+                              &stringData);
+}
+
+} // namespace ndk
+
+#endif // __cplusplus
+
+/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h
index bc8e44a..2d8b7fa 100644
--- a/libs/binder/ndk/include_ndk/android/binder_status.h
+++ b/libs/binder/ndk/include_ndk/android/binder_status.h
@@ -30,6 +30,7 @@
 #include <sys/cdefs.h>
 
 __BEGIN_DECLS
+#if __ANDROID_API__ >= __ANDROID_API_Q__
 
 enum {
     STATUS_OK = 0,
@@ -89,6 +90,98 @@
  */
 typedef int32_t binder_exception_t;
 
+/**
+ * This is a helper class that encapsulates a standard way to keep track of and chain binder errors
+ * along with service specific errors.
+ *
+ * It is not required to be used in order to parcel/receive transactions, but it is required in
+ * order to be compatible with standard AIDL transactions.
+ */
+struct AStatus;
+typedef struct AStatus AStatus;
+
+/**
+ * New status which is considered a success.
+ */
+__attribute__((warn_unused_result)) AStatus* AStatus_newOk() __INTRODUCED_IN(29);
+
+/**
+ * New status with exception code.
+ */
+__attribute__((warn_unused_result)) AStatus* AStatus_fromExceptionCode(binder_exception_t exception)
+        __INTRODUCED_IN(29);
+
+/**
+ * New status with exception code and message.
+ */
+__attribute__((warn_unused_result)) AStatus* AStatus_fromExceptionCodeWithMessage(
+        binder_exception_t exception, const char* message) __INTRODUCED_IN(29);
+
+/**
+ * New status with a service speciic error.
+ *
+ * This is considered to be EX_TRANSACTION_FAILED with extra information.
+ */
+__attribute__((warn_unused_result)) AStatus* AStatus_fromServiceSpecificError(
+        int32_t serviceSpecific) __INTRODUCED_IN(29);
+
+/**
+ * New status with a service specific error and message.
+ *
+ * This is considered to be EX_TRANSACTION_FAILED with extra information.
+ */
+__attribute__((warn_unused_result)) AStatus* AStatus_fromServiceSpecificErrorWithMessage(
+        int32_t serviceSpecific, const char* message) __INTRODUCED_IN(29);
+
+/**
+ * New status with binder_status_t. This is typically for low level failures when a binder_status_t
+ * is returned by an API on AIBinder or AParcel, and that is to be returned from a method returning
+ * an AStatus instance.
+ */
+__attribute__((warn_unused_result)) AStatus* AStatus_fromStatus(binder_status_t status)
+        __INTRODUCED_IN(29);
+
+/**
+ * Whether this object represents a successful transaction. If this function returns true, then
+ * AStatus_getExceptionCode will return EX_NONE.
+ */
+bool AStatus_isOk(const AStatus* status) __INTRODUCED_IN(29);
+
+/**
+ * The exception that this status object represents.
+ */
+binder_exception_t AStatus_getExceptionCode(const AStatus* status) __INTRODUCED_IN(29);
+
+/**
+ * The service specific error if this object represents one. This function will only ever return a
+ * non-zero result if AStatus_getExceptionCode returns EX_SERVICE_SPECIFIC. If this function returns
+ * 0, the status object may still represent a different exception or status. To find out if this
+ * transaction as a whole is okay, use AStatus_isOk instead.
+ */
+int32_t AStatus_getServiceSpecificError(const AStatus* status) __INTRODUCED_IN(29);
+
+/**
+ * The status if this object represents one. This function will only ever return a non-zero result
+ * if AStatus_getExceptionCode returns EX_TRANSACTION_FAILED. If this function return 0, the status
+ * object may represent a different exception or a service specific error. To find out if this
+ * transaction as a whole is okay, use AStatus_isOk instead.
+ */
+binder_status_t AStatus_getStatus(const AStatus* status) __INTRODUCED_IN(29);
+
+/**
+ * If there is a message associated with this status, this will return that message. If there is no
+ * message, this will return an empty string.
+ *
+ * The returned string has the lifetime of the status object passed into this function.
+ */
+const char* AStatus_getMessage(const AStatus* status) __INTRODUCED_IN(29);
+
+/**
+ * Deletes memory associated with the status instance.
+ */
+void AStatus_delete(AStatus* status) __INTRODUCED_IN(29);
+
+#endif //__ANDROID_API__ >= __ANDROID_API_Q__
 __END_DECLS
 
 /** @} */
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
new file mode 100644
index 0000000..2a1bff1
--- /dev/null
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -0,0 +1,65 @@
+LIBBINDER_NDK { # introduced=29
+  global:
+    AIBinder_associateClass;
+    AIBinder_Class_define;
+    AIBinder_DeathRecipient_delete;
+    AIBinder_DeathRecipient_new;
+    AIBinder_debugGetRefCount;
+    AIBinder_decStrong;
+    AIBinder_fromJavaBinder;
+    AIBinder_getClass;
+    AIBinder_getUserData;
+    AIBinder_incStrong;
+    AIBinder_isAlive;
+    AIBinder_isRemote;
+    AIBinder_linkToDeath;
+    AIBinder_new;
+    AIBinder_ping;
+    AIBinder_prepareTransaction;
+    AIBinder_toJavaBinder;
+    AIBinder_transact;
+    AIBinder_unlinkToDeath;
+    AIBinder_Weak_delete;
+    AIBinder_Weak_new;
+    AIBinder_Weak_promote;
+    AParcel_delete;
+    AParcel_readBool;
+    AParcel_readByte;
+    AParcel_readChar;
+    AParcel_readDouble;
+    AParcel_readFloat;
+    AParcel_readInt32;
+    AParcel_readInt64;
+    AParcel_readNullableStrongBinder;
+    AParcel_readStatusHeader;
+    AParcel_readString;
+    AParcel_readStrongBinder;
+    AParcel_readUint32;
+    AParcel_readUint64;
+    AParcel_writeBool;
+    AParcel_writeByte;
+    AParcel_writeChar;
+    AParcel_writeDouble;
+    AParcel_writeFloat;
+    AParcel_writeInt32;
+    AParcel_writeInt64;
+    AParcel_writeStatusHeader;
+    AParcel_writeString;
+    AParcel_writeStrongBinder;
+    AParcel_writeUint32;
+    AParcel_writeUint64;
+    AStatus_delete;
+    AStatus_fromExceptionCode;
+    AStatus_fromExceptionCodeWithMessage;
+    AStatus_fromServiceSpecificError;
+    AStatus_fromServiceSpecificErrorWithMessage;
+    AStatus_fromStatus;
+    AStatus_getExceptionCode;
+    AStatus_getMessage;
+    AStatus_getServiceSpecificError;
+    AStatus_getStatus;
+    AStatus_isOk;
+    AStatus_newOk;
+  local:
+    *;
+};
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index e506847..3e03e90 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -20,20 +20,19 @@
 #include "ibinder_internal.h"
 #include "status_internal.h"
 
+#include <limits>
+
+#include <android-base/logging.h>
 #include <binder/Parcel.h>
+#include <utils/Unicode.h>
 
 using ::android::IBinder;
 using ::android::Parcel;
 using ::android::sp;
 using ::android::status_t;
 
-void AParcel_delete(AParcel** parcel) {
-    if (parcel == nullptr) {
-        return;
-    }
-
-    delete *parcel;
-    *parcel = nullptr;
+void AParcel_delete(AParcel* parcel) {
+    delete parcel;
 }
 
 binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) {
@@ -62,6 +61,78 @@
     *binder = ret.get();
     return PruneStatusT(status);
 }
+binder_status_t AParcel_writeStatusHeader(AParcel* parcel, const AStatus* status) {
+    return PruneStatusT(status->get()->writeToParcel(parcel->get()));
+}
+binder_status_t AParcel_readStatusHeader(const AParcel* parcel, AStatus** status) {
+    ::android::binder::Status bstatus;
+    binder_status_t ret = PruneStatusT(bstatus.readFromParcel(*parcel->get()));
+    if (ret == EX_NONE) {
+        *status = new AStatus(std::move(bstatus));
+    }
+    return ret;
+}
+
+binder_status_t AParcel_writeString(AParcel* parcel, const char* string, size_t length) {
+    const uint8_t* str8 = (uint8_t*)string;
+
+    const ssize_t len16 = utf8_to_utf16_length(str8, length);
+
+    if (len16 < 0 || len16 >= std::numeric_limits<int32_t>::max()) {
+        LOG(WARNING) << __func__ << ": Invalid string length: " << len16;
+        return STATUS_BAD_VALUE;
+    }
+
+    status_t err = parcel->get()->writeInt32(len16);
+    if (err) {
+        return PruneStatusT(err);
+    }
+
+    void* str16 = parcel->get()->writeInplace((len16 + 1) * sizeof(char16_t));
+    if (str16 == nullptr) {
+        return STATUS_NO_MEMORY;
+    }
+
+    utf8_to_utf16(str8, length, (char16_t*)str16, (size_t)len16 + 1);
+
+    return STATUS_OK;
+}
+
+binder_status_t AParcel_readString(const AParcel* parcel, AParcel_string_reallocator reallocator,
+                                   AParcel_string_getter getter, void** stringData) {
+    size_t len16;
+    const char16_t* str16 = parcel->get()->readString16Inplace(&len16);
+
+    if (str16 == nullptr) {
+        LOG(WARNING) << __func__ << ": Failed to read string in place.";
+        return STATUS_UNEXPECTED_NULL;
+    }
+
+    ssize_t len8;
+
+    if (len16 == 0) {
+        len8 = 1;
+    } else {
+        len8 = utf16_to_utf8_length(str16, len16) + 1;
+    }
+
+    if (len8 <= 0 || len8 >= std::numeric_limits<int32_t>::max()) {
+        LOG(WARNING) << __func__ << ": Invalid string length: " << len8;
+        return STATUS_BAD_VALUE;
+    }
+
+    *stringData = reallocator(*stringData, len8);
+    char* str8 = getter(*stringData);
+
+    if (str8 == nullptr) {
+        LOG(WARNING) << __func__ << ": AParcel_string_allocator failed to allocate.";
+        return STATUS_NO_MEMORY;
+    }
+
+    utf16_to_utf8(str16, len16, str8, len8);
+
+    return STATUS_OK;
+}
 
 // See gen_parcel_helper.py. These auto-generated read/write methods use the same types for
 // libbinder and this library.
diff --git a/libs/binder/ndk/runtests.sh b/libs/binder/ndk/runtests.sh
index 6c8527d..2257eb2 100755
--- a/libs/binder/ndk/runtests.sh
+++ b/libs/binder/ndk/runtests.sh
@@ -37,4 +37,7 @@
 adb wait-for-device
 adb sync data
 
+# very simple unit tests, tests things outside of the NDK as well
 run_libbinder_ndk_test
+
+atest android.binder.cts.NdkBinderTest
diff --git a/libs/binder/ndk/scripts/gen_parcel_helper.py b/libs/binder/ndk/scripts/gen_parcel_helper.py
index 85ee755..bbd3e5d 100755
--- a/libs/binder/ndk/scripts/gen_parcel_helper.py
+++ b/libs/binder/ndk/scripts/gen_parcel_helper.py
@@ -66,7 +66,7 @@
         header += "/**\n"
         header += " * Writes " + cpp + " value to the next location in a non-null parcel.\n"
         header += " */\n"
-        header += "binder_status_t AParcel_write" + pretty + "(AParcel* parcel, " + cpp + " value);\n\n"
+        header += "binder_status_t AParcel_write" + pretty + "(AParcel* parcel, " + cpp + " value) __INTRODUCED_IN(29);\n\n"
         source += "binder_status_t AParcel_write" + pretty + "(AParcel* parcel, " + cpp + " value) {\n"
         source += "    status_t status = parcel->get()->write" + pretty + "(value);\n"
         source += "    return PruneStatusT(status);\n"
@@ -76,7 +76,7 @@
         header += "/**\n"
         header += " * Reads into " + cpp + " value from the next location in a non-null parcel.\n"
         header += " */\n"
-        header += "binder_status_t AParcel_read" + pretty + "(const AParcel* parcel, " + cpp + "* value);\n\n"
+        header += "binder_status_t AParcel_read" + pretty + "(const AParcel* parcel, " + cpp + "* value) __INTRODUCED_IN(29);\n\n"
         source += "binder_status_t AParcel_read" + pretty + "(const AParcel* parcel, " + cpp + "* value) {\n"
         source += "    status_t status = parcel->get()->read" + pretty + "(value);\n"
         source += "    return PruneStatusT(status);\n"
diff --git a/libs/binder/ndk/scripts/init_map.sh b/libs/binder/ndk/scripts/init_map.sh
new file mode 100755
index 0000000..1f74e43
--- /dev/null
+++ b/libs/binder/ndk/scripts/init_map.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+
+# Simple helper for ease of development until this API is frozen.
+
+echo "LIBBINDER_NDK { # introduced=29"
+echo "  global:"
+{
+    grep -oP "AIBinder_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_ibinder.h;
+    grep -oP "AIBinder_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_ibinder_jni.h;
+    grep -oP "AParcel_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_parcel.h;
+    grep -oP "AStatus_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_status.h;
+} | sort | uniq | awk '{ print "    " $0 ";"; }'
+echo "  local:"
+echo "    *;"
+echo "};"
diff --git a/libs/binder/ndk/status.cpp b/libs/binder/ndk/status.cpp
index 626a9b2..1f75b0b 100644
--- a/libs/binder/ndk/status.cpp
+++ b/libs/binder/ndk/status.cpp
@@ -22,9 +22,55 @@
 using ::android::status_t;
 using ::android::binder::Status;
 
-binder_status_t PruneStatusT(status_t status) {
-    if (status > 0) return status;
+AStatus* AStatus_newOk() {
+    return new AStatus();
+}
 
+AStatus* AStatus_fromExceptionCode(binder_exception_t exception) {
+    return new AStatus(Status::fromExceptionCode(PruneException(exception)));
+}
+
+AStatus* AStatus_fromExceptionCodeWithMessage(binder_exception_t exception, const char* message) {
+    return new AStatus(Status::fromExceptionCode(PruneException(exception), message));
+}
+
+AStatus* AStatus_fromServiceSpecificError(int32_t serviceSpecific) {
+    return new AStatus(Status::fromServiceSpecificError(serviceSpecific));
+}
+
+AStatus* AStatus_fromServiceSpecificErrorWithMessage(int32_t serviceSpecific, const char* message) {
+    return new AStatus(Status::fromServiceSpecificError(serviceSpecific, message));
+}
+
+AStatus* AStatus_fromStatus(binder_status_t status) {
+    return new AStatus(Status::fromStatusT(PruneStatusT(status)));
+}
+
+bool AStatus_isOk(const AStatus* status) {
+    return status->get()->isOk();
+}
+
+binder_exception_t AStatus_getExceptionCode(const AStatus* status) {
+    return PruneException(status->get()->exceptionCode());
+}
+
+int32_t AStatus_getServiceSpecificError(const AStatus* status) {
+    return status->get()->serviceSpecificErrorCode();
+}
+
+binder_status_t AStatus_getStatus(const AStatus* status) {
+    return PruneStatusT(status->get()->transactionError());
+}
+
+const char* AStatus_getMessage(const AStatus* status) {
+    return status->get()->exceptionMessage().c_str();
+}
+
+void AStatus_delete(AStatus* status) {
+    delete status;
+}
+
+binder_status_t PruneStatusT(status_t status) {
     switch (status) {
         case ::android::OK:
             return STATUS_OK;
diff --git a/libs/binder/ndk/status_internal.h b/libs/binder/ndk/status_internal.h
index 41b124c..8c32baf 100644
--- a/libs/binder/ndk/status_internal.h
+++ b/libs/binder/ndk/status_internal.h
@@ -21,6 +21,17 @@
 #include <binder/Status.h>
 #include <utils/Errors.h>
 
+struct AStatus {
+    AStatus() {} // ok
+    AStatus(::android::binder::Status&& status) : mStatus(std::move(status)) {}
+
+    ::android::binder::Status* get() { return &mStatus; }
+    const ::android::binder::Status* get() const { return &mStatus; }
+
+private:
+    ::android::binder::Status mStatus;
+};
+
 // This collapses the statuses into the declared range.
 binder_status_t PruneStatusT(android::status_t status);
 
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
index d242138..8e40a01 100644
--- a/libs/binder/ndk/test/Android.bp
+++ b/libs/binder/ndk/test/Android.bp
@@ -44,6 +44,7 @@
     name: "test_libbinder_ndk_test_defaults",
     defaults: ["test_libbinder_ndk_defaults"],
     shared_libs: [
+        "libandroid_runtime",
         "libbase",
         "libbinder",
         "libutils",
diff --git a/libs/binder/ndk/test/iface.cpp b/libs/binder/ndk/test/iface.cpp
index 80700df..0dc3cc4 100644
--- a/libs/binder/ndk/test/iface.cpp
+++ b/libs/binder/ndk/test/iface.cpp
@@ -81,7 +81,7 @@
         int32_t out;
         CHECK(STATUS_OK == AParcel_readInt32(parcelOut, &out));
 
-        AParcel_delete(&parcelOut);
+        AParcel_delete(parcelOut);
 
         return out;
     }
@@ -92,7 +92,7 @@
 };
 
 IFoo::~IFoo() {
-    AIBinder_Weak_delete(&mWeakBinder);
+    AIBinder_Weak_delete(mWeakBinder);
 }
 
 binder_status_t IFoo::addService(const char* instance) {
@@ -106,7 +106,7 @@
         // or one strong refcount here
         binder = AIBinder_new(IFoo::kClass, static_cast<void*>(new IFoo_Class_Data{this}));
         if (mWeakBinder != nullptr) {
-            AIBinder_Weak_delete(&mWeakBinder);
+            AIBinder_Weak_delete(mWeakBinder);
         }
         mWeakBinder = AIBinder_Weak_new(binder);
     }
diff --git a/libs/binder/ndk/test/main_client.cpp b/libs/binder/ndk/test/main_client.cpp
index 2dcccfe..22bf1e5 100644
--- a/libs/binder/ndk/test/main_client.cpp
+++ b/libs/binder/ndk/test/main_client.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <android-base/logging.h>
+#include <android/binder_ibinder_jni.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 #include <gtest/gtest.h>
@@ -66,7 +67,7 @@
     EXPECT_EQ(STATUS_OK, AIBinder_unlinkToDeath(binder, recipient, nullptr));
     EXPECT_EQ(STATUS_NAME_NOT_FOUND, AIBinder_unlinkToDeath(binder, recipient, nullptr));
 
-    AIBinder_DeathRecipient_delete(&recipient);
+    AIBinder_DeathRecipient_delete(recipient);
     AIBinder_decStrong(binder);
 }
 
@@ -102,6 +103,11 @@
     AIBinder_decStrong(binderB);
 }
 
+TEST(NdkBinder, ToFromJavaNullptr) {
+    EXPECT_EQ(nullptr, AIBinder_toJavaBinder(nullptr, nullptr));
+    EXPECT_EQ(nullptr, AIBinder_fromJavaBinder(nullptr, nullptr));
+}
+
 TEST(NdkBinder, ABpBinderRefCount) {
     AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
     AIBinder_Weak* wBinder = AIBinder_Weak_new(binder);
@@ -114,7 +120,7 @@
     // assert because would need to decStrong if non-null and we shouldn't need to add a no-op here
     ASSERT_NE(nullptr, AIBinder_Weak_promote(wBinder));
 
-    AIBinder_Weak_delete(&wBinder);
+    AIBinder_Weak_delete(wBinder);
 }
 
 TEST(NdkBinder, AddServiceMultipleTimes) {
@@ -125,3 +131,6 @@
     EXPECT_EQ(STATUS_OK, foo->addService(kInstanceName2));
     EXPECT_EQ(IFoo::getService(kInstanceName1), IFoo::getService(kInstanceName2));
 }
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_interface_utils.h>
diff --git a/libs/binder/ndk/update.sh b/libs/binder/ndk/update.sh
index 1eba892..49b4730 100755
--- a/libs/binder/ndk/update.sh
+++ b/libs/binder/ndk/update.sh
@@ -18,5 +18,6 @@
 set -ex
 
 # This script makes sure that the source code is in sync with the various scripts
+./scripts/init_map.sh > libbinder_ndk.map.txt
 ./scripts/gen_parcel_helper.py
 ./scripts/format.sh
diff --git a/libs/binderthreadstate/Android.bp b/libs/binderthreadstate/Android.bp
new file mode 100644
index 0000000..7106cbb
--- /dev/null
+++ b/libs/binderthreadstate/Android.bp
@@ -0,0 +1,44 @@
+// Copyright (C) 2018 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 {
+    name: "libbinderthreadstate",
+    recovery_available: true,
+    vendor_available: false,
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
+    srcs: [
+        "IPCThreadStateBase.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libutils",
+    ],
+
+    export_include_dirs: ["include"],
+
+    sanitize: {
+        misc_undefined: ["integer"],
+    },
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+}
diff --git a/libs/binderthreadstate/IPCThreadStateBase.cpp b/libs/binderthreadstate/IPCThreadStateBase.cpp
new file mode 100644
index 0000000..fede151
--- /dev/null
+++ b/libs/binderthreadstate/IPCThreadStateBase.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "IPCThreadStateBase"
+
+#include <binderthreadstate/IPCThreadStateBase.h>
+#include <android-base/macros.h>
+
+#include <utils/Log.h>
+
+#include <errno.h>
+#include <inttypes.h>
+#include <pthread.h>
+
+namespace android {
+
+static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
+static bool gHaveTLS = false;
+static pthread_key_t gTLS = 0;
+
+IPCThreadStateBase::IPCThreadStateBase() {
+    pthread_setspecific(gTLS, this);
+}
+
+IPCThreadStateBase* IPCThreadStateBase::self()
+{
+    if (gHaveTLS) {
+restart:
+        const pthread_key_t k = gTLS;
+        IPCThreadStateBase* st = (IPCThreadStateBase*)pthread_getspecific(k);
+        if (st) return st;
+        return new IPCThreadStateBase;
+    }
+
+    pthread_mutex_lock(&gTLSMutex);
+    if (!gHaveTLS) {
+        int key_create_value = pthread_key_create(&gTLS, threadDestructor);
+        if (key_create_value != 0) {
+            pthread_mutex_unlock(&gTLSMutex);
+            ALOGW("IPCThreadStateBase::self() unable to create TLS key, expect a crash: %s\n",
+                    strerror(key_create_value));
+            return nullptr;
+        }
+        gHaveTLS = true;
+    }
+    pthread_mutex_unlock(&gTLSMutex);
+    goto restart;
+}
+
+void IPCThreadStateBase::pushCurrentState(CallState callState) {
+    mCallStateStack.emplace(callState);
+}
+
+IPCThreadStateBase::CallState IPCThreadStateBase::popCurrentState() {
+    ALOG_ASSERT(mCallStateStack.size > 0);
+    CallState val = mCallStateStack.top();
+    mCallStateStack.pop();
+    return val;
+}
+
+IPCThreadStateBase::CallState IPCThreadStateBase::getCurrentBinderCallState() {
+    if (mCallStateStack.size() > 0) {
+        return mCallStateStack.top();
+    }
+    return CallState::NONE;
+}
+
+void IPCThreadStateBase::threadDestructor(void *st)
+{
+    IPCThreadStateBase* const self = static_cast<IPCThreadStateBase*>(st);
+    if (self) {
+        delete self;
+    }
+}
+
+}; // namespace android
diff --git a/libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h b/libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h
new file mode 100644
index 0000000..6fdcc84
--- /dev/null
+++ b/libs/binderthreadstate/include/binderthreadstate/IPCThreadStateBase.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 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 BINDER_THREADSTATE_IPC_THREADSTATE_BASE_H
+#define BINDER_THREADSTATE_IPC_THREADSTATE_BASE_H
+
+#include <stack>
+namespace android {
+
+class IPCThreadStateBase {
+public:
+    enum CallState {
+        HWBINDER,
+        BINDER,
+        NONE,
+    };
+    static IPCThreadStateBase* self();
+    void pushCurrentState(CallState callState);
+    CallState popCurrentState();
+    CallState getCurrentBinderCallState();
+
+private:
+    IPCThreadStateBase();
+    static void threadDestructor(void *st);
+
+    std::stack<CallState> mCallStateStack;
+};
+
+}; // namespace android
+
+#endif // BINDER_THREADSTATE_IPC_THREADSTATE_BASE_H
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index a379ad6..85ae433 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -621,7 +621,7 @@
 // ============================================================================
 
 FrameEventHistoryDelta& FrameEventHistoryDelta::operator=(
-        FrameEventHistoryDelta&& src) {
+        FrameEventHistoryDelta&& src) noexcept {
     mCompositorTiming = src.mCompositorTiming;
 
     if (CC_UNLIKELY(!mDeltas.empty())) {
diff --git a/libs/gui/include/gui/FrameTimestamps.h b/libs/gui/include/gui/FrameTimestamps.h
index 9716be4..e06e40f 100644
--- a/libs/gui/include/gui/FrameTimestamps.h
+++ b/libs/gui/include/gui/FrameTimestamps.h
@@ -311,7 +311,7 @@
 
     // Movable.
     FrameEventHistoryDelta(FrameEventHistoryDelta&& src) = default;
-    FrameEventHistoryDelta& operator=(FrameEventHistoryDelta&& src);
+    FrameEventHistoryDelta& operator=(FrameEventHistoryDelta&& src) noexcept;
     // Not copyable.
     FrameEventHistoryDelta(const FrameEventHistoryDelta& src) = delete;
     FrameEventHistoryDelta& operator=(
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index aca9521..f06119f 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -1,7 +1,6 @@
 // Build the unit tests.
 cc_test {
     name: "libinput_tests",
-    test_per_src: true,
     srcs: [
         "InputChannel_test.cpp",
         "InputEvent_test.cpp",
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
index 43b6012..9da2e2a 100644
--- a/libs/input/tests/VelocityTracker_test.cpp
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "VelocityTracker_test"
 
+#include <array>
 #include <math.h>
 
 #include <android-base/stringprintf.h>
@@ -32,29 +33,35 @@
 // here EV = expected value, tol = VELOCITY_TOLERANCE
 constexpr float VELOCITY_TOLERANCE = 0.2;
 
+// estimate coefficients must be within 0.001% of the target value
+constexpr float COEFFICIENT_TOLERANCE = 0.00001;
+
 // --- VelocityTrackerTest ---
 class VelocityTrackerTest : public testing::Test { };
 
-static void checkVelocity(float Vactual, float Vtarget) {
-    // Compare directions
-    if ((Vactual > 0 && Vtarget <= 0) || (Vactual < 0 && Vtarget >= 0)) {
-        FAIL() << StringPrintf("Velocity %f does not have the same direction"
-                " as the target velocity %f", Vactual, Vtarget);
-    }
+/*
+ * Similar to EXPECT_NEAR, but ensures that the difference between the two float values
+ * is at most a certain fraction of the target value.
+ * If fraction is zero, require exact match.
+ */
+static void EXPECT_NEAR_BY_FRACTION(float actual, float target, float fraction) {
+    float tolerance = fabsf(target * fraction);
 
-    // Compare magnitudes
-    const float Vlower = fabsf(Vtarget * (1 - VELOCITY_TOLERANCE));
-    const float Vupper = fabsf(Vtarget * (1 + VELOCITY_TOLERANCE));
-    if (fabsf(Vactual) < Vlower) {
-        FAIL() << StringPrintf("Velocity %f is more than %.0f%% below target velocity %f",
-                Vactual, VELOCITY_TOLERANCE * 100, Vtarget);
+    if (target == 0 && fraction != 0) {
+        // If target is zero, this would force actual == target, which is too harsh.
+        // Relax this requirement a little. The value is determined empirically from the
+        // coefficients computed by the quadratic least squares algorithms.
+        tolerance = 1E-6;
     }
-    if (fabsf(Vactual) > Vupper) {
-        FAIL() << StringPrintf("Velocity %f is more than %.0f%% above target velocity %f",
-                Vactual, VELOCITY_TOLERANCE * 100, Vtarget);
-    }
-    SUCCEED() << StringPrintf("Velocity %f within %.0f%% of target %f)",
-            Vactual, VELOCITY_TOLERANCE * 100, Vtarget);
+    EXPECT_NEAR(actual, target, tolerance);
+}
+
+static void checkVelocity(float Vactual, float Vtarget) {
+    EXPECT_NEAR_BY_FRACTION(Vactual, Vtarget, VELOCITY_TOLERANCE);
+}
+
+static void checkCoefficient(float actual, float target) {
+    EXPECT_NEAR_BY_FRACTION(actual, target, COEFFICIENT_TOLERANCE);
 }
 
 void failWithMessage(std::string message) {
@@ -123,6 +130,19 @@
     delete event;
 }
 
+static void computeAndCheckQuadraticEstimate(const Position* positions, size_t numSamples,
+        const std::array<float, 3>& coefficients) {
+    VelocityTracker vt("lsq2");
+    MotionEvent* event = createSimpleMotionEvent(positions, numSamples);
+    vt.addMovement(event);
+    VelocityTracker::Estimator estimator;
+    EXPECT_TRUE(vt.getEstimator(0, &estimator));
+    for (size_t i = 0; i< coefficients.size(); i++) {
+        checkCoefficient(estimator.xCoeff[i], coefficients[i]);
+        checkCoefficient(estimator.yCoeff[i], coefficients[i]);
+    }
+}
+
 /*
  * ================== VelocityTracker tests generated manually =====================================
  */
@@ -660,5 +680,114 @@
     computeAndCheckVelocity(values, count, AMOTION_EVENT_AXIS_Y, 28354.796875); // lsq2
 }
 
+/*
+ * Special care must be taken when constructing tests for LeastSquaresVelocityTrackerStrategy
+ * getEstimator function. In particular:
+ * - inside the function, time gets converted from nanoseconds to seconds
+ *   before being used in the fit.
+ * - any values that are older than 100 ms are being discarded.
+ * - the newest time gets subtracted from all of the other times before being used in the fit.
+ * So these tests have to be designed with those limitations in mind.
+ *
+ * General approach for the tests below:
+ * We only used timestamps in milliseconds, 0 ms, 1 ms, and 2 ms, to be sure that
+ * we are well within the HORIZON range.
+ * When specifying the expected values of the coefficients, we treat the x values as if
+ * they were in ms. Then, to adjust for the time units, the coefficients get progressively
+ * multiplied by powers of 1E3.
+ * For example:
+ * data: t(ms), x
+ *        1 ms, 1
+ *        2 ms, 4
+ *        3 ms, 9
+ * The coefficients are (0, 0, 1).
+ * In the test, we would convert these coefficients to (0*(1E3)^0, 0*(1E3)^1, 1*(1E3)^2).
+ */
+TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Constant) {
+    Position values[] = {
+        { 0000000, 1, 1 }, // 0 s
+        { 1000000, 1, 1 }, // 0.001 s
+        { 2000000, 1, 1 }, // 0.002 s
+    };
+    // The data used for the fit will be as follows:
+    // time(s), position
+    // -0.002, 1
+    // -0.001, 1
+    // -0.000, 1
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({1, 0, 0}));
+}
+
+/*
+ * Straight line y = x :: the constant and quadratic coefficients are zero.
+ */
+TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Linear) {
+    Position values[] = {
+        { 0000000, -2, -2 },
+        { 1000000, -1, -1 },
+        { 2000000, -0, -0 },
+    };
+    // The data used for the fit will be as follows:
+    // time(s), position
+    // -0.002, -2
+    // -0.001, -1
+    // -0.000,  0
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({0, 1E3, 0}));
+}
+
+/*
+ * Parabola
+ */
+TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Parabolic) {
+    Position values[] = {
+        { 0000000, 1, 1 },
+        { 1000000, 4, 4 },
+        { 2000000, 8, 8 },
+    };
+    // The data used for the fit will be as follows:
+    // time(s), position
+    // -0.002, 1
+    // -0.001, 4
+    // -0.000, 8
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({8, 4.5E3, 0.5E6}));
+}
+
+/*
+ * Parabola
+ */
+TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Parabolic2) {
+    Position values[] = {
+        { 0000000, 1, 1 },
+        { 1000000, 4, 4 },
+        { 2000000, 9, 9 },
+    };
+    // The data used for the fit will be as follows:
+    // time(s), position
+    // -0.002, 1
+    // -0.001, 4
+    // -0.000, 9
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({9, 6E3, 1E6}));
+}
+
+/*
+ * Parabola :: y = x^2 :: the constant and linear coefficients are zero.
+ */
+TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Parabolic3) {
+    Position values[] = {
+        { 0000000, 4, 4 },
+        { 1000000, 1, 1 },
+        { 2000000, 0, 0 },
+    };
+    // The data used for the fit will be as follows:
+    // time(s), position
+    // -0.002, 4
+    // -0.001, 1
+    // -0.000, 0
+    size_t count = sizeof(values) / sizeof(Position);
+    computeAndCheckQuadraticEstimate(values, count, std::array<float, 3>({0, 0E3, 1E6}));
+}
 
 } // namespace android
diff --git a/libs/ui/HdrCapabilities.cpp b/libs/ui/HdrCapabilities.cpp
index a36911d..a5b3e89 100644
--- a/libs/ui/HdrCapabilities.cpp
+++ b/libs/ui/HdrCapabilities.cpp
@@ -24,8 +24,8 @@
 #endif
 
 HdrCapabilities::~HdrCapabilities() = default;
-HdrCapabilities::HdrCapabilities(HdrCapabilities&& other) = default;
-HdrCapabilities& HdrCapabilities::operator=(HdrCapabilities&& other) = default;
+HdrCapabilities::HdrCapabilities(HdrCapabilities&& other) noexcept = default;
+HdrCapabilities& HdrCapabilities::operator=(HdrCapabilities&& other) noexcept = default;
 
 size_t HdrCapabilities::getFlattenedSize() const {
     return  sizeof(mMaxLuminance) +
diff --git a/libs/ui/include/ui/HdrCapabilities.h b/libs/ui/include/ui/HdrCapabilities.h
index 4e98c28..65ac26c 100644
--- a/libs/ui/include/ui/HdrCapabilities.h
+++ b/libs/ui/include/ui/HdrCapabilities.h
@@ -37,8 +37,8 @@
         mMinLuminance(minLuminance) {}
 
     // Make this move-constructable and move-assignable
-    HdrCapabilities(HdrCapabilities&& other);
-    HdrCapabilities& operator=(HdrCapabilities&& other);
+    HdrCapabilities(HdrCapabilities&& other) noexcept;
+    HdrCapabilities& operator=(HdrCapabilities&& other) noexcept;
 
     HdrCapabilities()
       : mSupportedHdrTypes(),
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index f4918c4..04f4fb4 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -103,8 +103,8 @@
       opaque_ints_.push_back(buffer.handle()->data[fd_count + i]);
     }
   }
-  NativeBufferHandle(NativeBufferHandle&& other) = default;
-  NativeBufferHandle& operator=(NativeBufferHandle&& other) = default;
+  NativeBufferHandle(NativeBufferHandle&& other) noexcept = default;
+  NativeBufferHandle& operator=(NativeBufferHandle&& other) noexcept = default;
 
   // Imports the native handle into the given IonBuffer instance.
   int Import(IonBuffer* buffer) {
@@ -174,8 +174,8 @@
         acquire_fence_fd_(acquire_fence_fd.Borrow()),
         release_fence_fd_(release_fence_fd.Borrow()) {}
 
-  BufferDescription(BufferDescription&& other) = default;
-  BufferDescription& operator=(BufferDescription&& other) = default;
+  BufferDescription(BufferDescription&& other) noexcept = default;
+  BufferDescription& operator=(BufferDescription&& other) noexcept = default;
 
   // ID of the buffer client. All BufferHubBuffer clients derived from the same
   // buffer in bufferhubd share the same buffer id.
@@ -219,8 +219,8 @@
   FenceHandle() = default;
   explicit FenceHandle(int fence) : fence_{fence} {}
   explicit FenceHandle(FileHandleType&& fence) : fence_{std::move(fence)} {}
-  FenceHandle(FenceHandle&&) = default;
-  FenceHandle& operator=(FenceHandle&&) = default;
+  FenceHandle(FenceHandle&&) noexcept = default;
+  FenceHandle& operator=(FenceHandle&&) noexcept = default;
 
   explicit operator bool() const { return fence_.IsValid(); }
 
diff --git a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
index f6bc547..860f08a 100644
--- a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
@@ -20,8 +20,8 @@
             uint64_t usage);
   ~IonBuffer();
 
-  IonBuffer(IonBuffer&& other);
-  IonBuffer& operator=(IonBuffer&& other);
+  IonBuffer(IonBuffer&& other) noexcept;
+  IonBuffer& operator=(IonBuffer&& other) noexcept;
 
   // Returns check this IonBuffer holds a valid Gralloc buffer.
   bool IsValid() const { return buffer_ && buffer_->initCheck() == NO_ERROR; }
diff --git a/libs/vr/libbufferhub/ion_buffer.cpp b/libs/vr/libbufferhub/ion_buffer.cpp
index cbaa24a..1295531 100644
--- a/libs/vr/libbufferhub/ion_buffer.cpp
+++ b/libs/vr/libbufferhub/ion_buffer.cpp
@@ -49,11 +49,11 @@
   FreeHandle();
 }
 
-IonBuffer::IonBuffer(IonBuffer&& other) : IonBuffer() {
+IonBuffer::IonBuffer(IonBuffer&& other) noexcept : IonBuffer() {
   *this = std::move(other);
 }
 
-IonBuffer& IonBuffer::operator=(IonBuffer&& other) {
+IonBuffer& IonBuffer::operator=(IonBuffer&& other) noexcept {
   ALOGD_IF(TRACE, "IonBuffer::operator=: handle_=%p other.handle_=%p", handle(),
            other.handle());
 
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
index 4dea9b2..ad3f56b 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
@@ -28,8 +28,8 @@
  public:
   BufferHubQueueParcelable() = default;
 
-  BufferHubQueueParcelable(BufferHubQueueParcelable&& other) = default;
-  BufferHubQueueParcelable& operator=(BufferHubQueueParcelable&& other) {
+  BufferHubQueueParcelable(BufferHubQueueParcelable&& other) noexcept = default;
+  BufferHubQueueParcelable& operator=(BufferHubQueueParcelable&& other) noexcept {
     channel_parcelable_ = std::move(other.channel_parcelable_);
     return *this;
   }
diff --git a/libs/vr/libdvrcommon/include/private/dvr/ring_buffer.h b/libs/vr/libdvrcommon/include/private/dvr/ring_buffer.h
index 44485a7..1824241 100644
--- a/libs/vr/libdvrcommon/include/private/dvr/ring_buffer.h
+++ b/libs/vr/libdvrcommon/include/private/dvr/ring_buffer.h
@@ -23,9 +23,9 @@
   explicit RingBuffer(size_t capacity) { Reset(capacity); }
 
   RingBuffer(const RingBuffer& other) = default;
-  RingBuffer(RingBuffer&& other) = default;
+  RingBuffer(RingBuffer&& other) noexcept = default;
   RingBuffer& operator=(const RingBuffer& other) = default;
-  RingBuffer& operator=(RingBuffer&& other) = default;
+  RingBuffer& operator=(RingBuffer&& other) noexcept = default;
 
   void Append(const T& val) {
     if (IsFull())
diff --git a/libs/vr/libpdx/private/pdx/channel_handle.h b/libs/vr/libpdx/private/pdx/channel_handle.h
index 1e62d25..daa08f4 100644
--- a/libs/vr/libpdx/private/pdx/channel_handle.h
+++ b/libs/vr/libpdx/private/pdx/channel_handle.h
@@ -50,14 +50,14 @@
  public:
   ChannelHandle() = default;
   using ChannelHandleBase::ChannelHandleBase;
-  ChannelHandle(ChannelHandle&& other) : ChannelHandleBase{other.value_} {
+  ChannelHandle(ChannelHandle&& other) noexcept : ChannelHandleBase{other.value_} {
     other.value_ = kEmptyHandle;
   }
   ~ChannelHandle() = default;
 
   ChannelHandle Duplicate() const { return ChannelHandle{value_}; }
 
-  ChannelHandle& operator=(ChannelHandle&& other) {
+  ChannelHandle& operator=(ChannelHandle&& other) noexcept {
     value_ = other.value_;
     other.value_ = kEmptyHandle;
     return *this;
@@ -74,13 +74,13 @@
   ChannelHandle(const ChannelHandle&) = delete;
   ChannelHandle& operator=(const ChannelHandle&) = delete;
 
-  ChannelHandle(ChannelHandle&& other)
+  ChannelHandle(ChannelHandle&& other) noexcept
       : ChannelHandleBase{other.value_}, manager_{other.manager_} {
     other.manager_ = nullptr;
     other.value_ = kEmptyHandle;
   }
 
-  ChannelHandle& operator=(ChannelHandle&& other) {
+  ChannelHandle& operator=(ChannelHandle&& other) noexcept {
     value_ = other.value_;
     manager_ = other.manager_;
     other.value_ = kEmptyHandle;
diff --git a/libs/vr/libpdx/private/pdx/file_handle.h b/libs/vr/libpdx/private/pdx/file_handle.h
index b3c3ad7..fed1529 100644
--- a/libs/vr/libpdx/private/pdx/file_handle.h
+++ b/libs/vr/libpdx/private/pdx/file_handle.h
@@ -43,7 +43,7 @@
 
   // Move constructor that assumes ownership of the file descriptor, leaving the
   // other FileHandle object empty.
-  FileHandle(FileHandle&& other) {
+  FileHandle(FileHandle&& other) noexcept {
     fd_ = other.fd_;
     other.fd_ = kEmptyFileHandle;
   }
@@ -62,7 +62,7 @@
 
   // Move assignment operator that assumes ownership of the underlying file
   // descriptor, leaving the other FileHandle object empty.
-  FileHandle& operator=(FileHandle&& other) {
+  FileHandle& operator=(FileHandle&& other) noexcept {
     if (this != &other) {
       Reset(other.fd_);
       other.fd_ = kEmptyFileHandle;
diff --git a/libs/vr/libpdx/private/pdx/rpc/array_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/array_wrapper.h
index 93d87f3..d835c57 100644
--- a/libs/vr/libpdx/private/pdx/rpc/array_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/array_wrapper.h
@@ -39,7 +39,7 @@
 
   ArrayWrapper(const ArrayWrapper& other) { *this = other; }
 
-  ArrayWrapper(ArrayWrapper&& other) { *this = std::move(other); }
+  ArrayWrapper(ArrayWrapper&& other) noexcept { *this = std::move(other); }
 
   ArrayWrapper& operator=(const ArrayWrapper& other) {
     if (&other == this) {
@@ -53,7 +53,7 @@
     return *this;
   }
 
-  ArrayWrapper& operator=(ArrayWrapper&& other) {
+  ArrayWrapper& operator=(ArrayWrapper&& other) noexcept {
     if (&other == this) {
       return *this;
     } else {
diff --git a/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h
index aa86531..0421220 100644
--- a/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h
@@ -39,7 +39,7 @@
 
   BufferWrapper(const BufferWrapper& other) { *this = other; }
 
-  BufferWrapper(BufferWrapper&& other) { *this = std::move(other); }
+  BufferWrapper(BufferWrapper&& other) noexcept { *this = std::move(other); }
 
   BufferWrapper& operator=(const BufferWrapper& other) {
     if (&other == this) {
@@ -53,7 +53,7 @@
     return *this;
   }
 
-  BufferWrapper& operator=(BufferWrapper&& other) {
+  BufferWrapper& operator=(BufferWrapper&& other) noexcept {
     if (&other == this) {
       return *this;
     } else {
@@ -117,9 +117,9 @@
   BufferWrapper(BufferType&& buffer, const Allocator& allocator)
       : buffer_(std::move(buffer), allocator) {}
   BufferWrapper(const BufferWrapper&) = default;
-  BufferWrapper(BufferWrapper&&) = default;
+  BufferWrapper(BufferWrapper&&) noexcept = default;
   BufferWrapper& operator=(const BufferWrapper&) = default;
-  BufferWrapper& operator=(BufferWrapper&&) = default;
+  BufferWrapper& operator=(BufferWrapper&&) noexcept = default;
 
   pointer data() { return buffer_.data(); }
   const_pointer data() const { return buffer_.data(); }
diff --git a/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h
index d496719..1cb85de 100644
--- a/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h
@@ -15,9 +15,9 @@
 
   PointerWrapper(T* pointer) : pointer_(pointer) {}
   PointerWrapper(const PointerWrapper&) = default;
-  PointerWrapper(PointerWrapper&&) = default;
+  PointerWrapper(PointerWrapper&&) noexcept = default;
   PointerWrapper& operator=(const PointerWrapper&) = default;
-  PointerWrapper& operator=(PointerWrapper&&) = default;
+  PointerWrapper& operator=(PointerWrapper&&) noexcept = default;
 
   T& Dereference() { return *pointer_; }
   const T& Dereference() const { return *pointer_; }
diff --git a/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h
index 19fc4c1..2d0a4ea 100644
--- a/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/string_wrapper.h
@@ -44,7 +44,7 @@
 
   StringWrapper(const StringWrapper& other) { *this = other; }
 
-  StringWrapper(StringWrapper&& other) { *this = std::move(other); }
+  StringWrapper(StringWrapper&& other) noexcept { *this = std::move(other); }
 
   StringWrapper& operator=(const StringWrapper& other) {
     if (&other == this) {
@@ -58,7 +58,7 @@
     return *this;
   }
 
-  StringWrapper& operator=(StringWrapper&& other) {
+  StringWrapper& operator=(StringWrapper&& other) noexcept {
     if (&other == this) {
       return *this;
     } else {
diff --git a/libs/vr/libpdx/private/pdx/rpc/variant.h b/libs/vr/libpdx/private/pdx/rpc/variant.h
index bdcb293..a1292b0 100644
--- a/libs/vr/libpdx/private/pdx/rpc/variant.h
+++ b/libs/vr/libpdx/private/pdx/rpc/variant.h
@@ -447,7 +447,7 @@
 
   Variant(const Variant& other)
       : index_{other.index_}, value_{other.value_, other.index_} {}
-  Variant(Variant&& other)
+  Variant(Variant&& other) noexcept
       : index_{other.index_}, value_{std::move(other.value_), other.index_} {}
 
 // Recent Clang versions has a regression that produces bogus
@@ -472,7 +472,7 @@
     other.Visit([this](const auto& value) { *this = value; });
     return *this;
   }
-  Variant& operator=(Variant&& other) {
+  Variant& operator=(Variant&& other) noexcept {
     other.Visit([this](auto&& value) { *this = std::move(value); });
     return *this;
   }
@@ -553,7 +553,7 @@
   template <typename T>
   constexpr std::int32_t index_of() const {
     static_assert(HasType<T>::value, "T is not an element type of Variant.");
-    return value_.template index(DecayedTypeTag<T>{});
+    return value_.index(DecayedTypeTag<T>{});
   }
 
   // Returns the index of the active type. If the Variant is empty -1 is
@@ -575,7 +575,7 @@
   template <typename T>
   T* get() {
     if (is<T>())
-      return &value_.template get(DecayedTypeTag<T>{});
+      return &value_.get(DecayedTypeTag<T>{});
     else
       return nullptr;
   }
@@ -589,7 +589,7 @@
   template <std::size_t I>
   TypeForIndex<I>* get() {
     if (is<TypeForIndex<I>>())
-      return &value_.template get(TypeTagForIndex<I>{});
+      return &value_.get(TypeTagForIndex<I>{});
     else
       return nullptr;
   }
diff --git a/libs/vr/libpdx/private/pdx/service.h b/libs/vr/libpdx/private/pdx/service.h
index 13aa3e9..234b24a 100644
--- a/libs/vr/libpdx/private/pdx/service.h
+++ b/libs/vr/libpdx/private/pdx/service.h
@@ -92,8 +92,8 @@
   /*
    * Message objects support move construction and assignment.
    */
-  Message(Message&& other);
-  Message& operator=(Message&& other);
+  Message(Message&& other) noexcept;
+  Message& operator=(Message&& other) noexcept;
 
   /*
    * Read/write payload, in either single buffer or iovec form.
diff --git a/libs/vr/libpdx/private/pdx/status.h b/libs/vr/libpdx/private/pdx/status.h
index 067fe25..7e51a52 100644
--- a/libs/vr/libpdx/private/pdx/status.h
+++ b/libs/vr/libpdx/private/pdx/status.h
@@ -41,14 +41,14 @@
   // Copy/move constructors. Move constructor leaves |other| object in empty
   // state.
   Status(const Status& other) = default;
-  Status(Status&& other)
+  Status(Status&& other) noexcept
       : value_{std::move(other.value_)}, error_{other.error_} {
     other.error_ = -1;
   }
 
   // Assignment operators.
   Status& operator=(const Status& other) = default;
-  Status& operator=(Status&& other) {
+  Status& operator=(Status&& other) noexcept {
     error_ = other.error_;
     value_ = std::move(other.value_);
     other.error_ = -1;
diff --git a/libs/vr/libpdx/private/pdx/utility.h b/libs/vr/libpdx/private/pdx/utility.h
index 08fcaea..c9a0c21 100644
--- a/libs/vr/libpdx/private/pdx/utility.h
+++ b/libs/vr/libpdx/private/pdx/utility.h
@@ -33,7 +33,7 @@
     return *this;
   }
 
-  ByteBuffer& operator=(ByteBuffer&& other) {
+  ByteBuffer& operator=(ByteBuffer&& other) noexcept {
     std::swap(data_, other.data_);
     std::swap(size_, other.size_);
     std::swap(capacity_, other.capacity_);
diff --git a/libs/vr/libpdx/service.cpp b/libs/vr/libpdx/service.cpp
index 1d3b62a..68b8dd7 100644
--- a/libs/vr/libpdx/service.cpp
+++ b/libs/vr/libpdx/service.cpp
@@ -31,9 +31,9 @@
 
 // C++11 specifies the move semantics for shared_ptr but not weak_ptr. This
 // means we have to manually implement the desired move semantics for Message.
-Message::Message(Message&& other) { *this = std::move(other); }
+Message::Message(Message&& other) noexcept { *this = std::move(other); }
 
-Message& Message::operator=(Message&& other) {
+Message& Message::operator=(Message&& other) noexcept {
   Destroy();
   auto base = reinterpret_cast<std::uint8_t*>(&info_);
   std::fill(&base[0], &base[sizeof(info_)], 0);
diff --git a/libs/vr/libvrflinger/acquired_buffer.cpp b/libs/vr/libvrflinger/acquired_buffer.cpp
index 9614c6d..5d873d1 100644
--- a/libs/vr/libvrflinger/acquired_buffer.cpp
+++ b/libs/vr/libvrflinger/acquired_buffer.cpp
@@ -31,13 +31,13 @@
   }
 }
 
-AcquiredBuffer::AcquiredBuffer(AcquiredBuffer&& other) {
+AcquiredBuffer::AcquiredBuffer(AcquiredBuffer&& other) noexcept {
   *this = std::move(other);
 }
 
 AcquiredBuffer::~AcquiredBuffer() { Release(LocalHandle(kEmptyFence)); }
 
-AcquiredBuffer& AcquiredBuffer::operator=(AcquiredBuffer&& other) {
+AcquiredBuffer& AcquiredBuffer::operator=(AcquiredBuffer&& other) noexcept {
   if (this != &other) {
     Release();
 
diff --git a/libs/vr/libvrflinger/acquired_buffer.h b/libs/vr/libvrflinger/acquired_buffer.h
index 32e912a..1a200aa 100644
--- a/libs/vr/libvrflinger/acquired_buffer.h
+++ b/libs/vr/libvrflinger/acquired_buffer.h
@@ -31,7 +31,7 @@
   AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer, int* error);
 
   // Move constructor. Behaves similarly to the move assignment operator below.
-  AcquiredBuffer(AcquiredBuffer&& other);
+  AcquiredBuffer(AcquiredBuffer&& other) noexcept;
 
   ~AcquiredBuffer();
 
@@ -39,7 +39,7 @@
   // |other| into this instance after RELEASING the current BufferConsumer and
   // closing the acquire fence. After the move |other| is left in the empty
   // state.
-  AcquiredBuffer& operator=(AcquiredBuffer&& other);
+  AcquiredBuffer& operator=(AcquiredBuffer&& other) noexcept;
 
   // Accessors for the underlying BufferConsumer, the acquire fence, and the
   // use-case specific sequence value from the acquisition (see
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 44ce78c..b8d5e2b 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -1272,9 +1272,9 @@
 
 Layer::~Layer() { Reset(); }
 
-Layer::Layer(Layer&& other) { *this = std::move(other); }
+Layer::Layer(Layer&& other) noexcept { *this = std::move(other); }
 
-Layer& Layer::operator=(Layer&& other) {
+Layer& Layer::operator=(Layer&& other) noexcept {
   if (this != &other) {
     Reset();
     using std::swap;
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index 1d8d463..539a7fb 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -86,8 +86,8 @@
         const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
         HWC::Composition composition_type, size_t z_order);
 
-  Layer(Layer&&);
-  Layer& operator=(Layer&&);
+  Layer(Layer&&) noexcept;
+  Layer& operator=(Layer&&) noexcept;
 
   ~Layer();
 
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index dd19800..afaf139 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -6,7 +6,6 @@
         "InputReader_test.cpp",
         "InputDispatcher_test.cpp",
     ],
-    test_per_src: true,
     cflags: [
         "-Wall",
         "-Werror",
diff --git a/services/media/arcvideobridge/Android.bp b/services/media/arcvideobridge/Android.bp
deleted file mode 100644
index ca5b896..0000000
--- a/services/media/arcvideobridge/Android.bp
+++ /dev/null
@@ -1,28 +0,0 @@
-cc_library_shared {
-    name: "libarcvideobridge",
-    product_variables: {
-        arc: {
-            srcs: [
-                "IArcVideoBridge.cpp",
-            ],
-            shared_libs: [
-                "libarcbridge",
-                "libarcbridgeservice",
-                "libbinder",
-                "libchrome",
-                "liblog",
-                "libmojo",
-                "libutils",
-            ],
-            cflags: [
-                "-Wall",
-                "-Werror",
-                "-Wunused",
-                "-Wunreachable-code",
-            ],
-            include_dirs: [
-                "frameworks/native/include/media/arcvideobridge",
-            ]
-        }
-    }
-}
diff --git a/services/media/arcvideobridge/IArcVideoBridge.cpp b/services/media/arcvideobridge/IArcVideoBridge.cpp
deleted file mode 100644
index 468b76b..0000000
--- a/services/media/arcvideobridge/IArcVideoBridge.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "IArcVideoBridge"
-//#define LOG_NDEBUG 0
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include "IArcVideoBridge.h"
-#include <binder/Parcel.h>
-#include <utils/Log.h>
-
-namespace android {
-
-enum {
-    BOOTSTRAP_VIDEO_ACCELERATOR_FACTORY = IBinder::FIRST_CALL_TRANSACTION,
-    HOST_VERSION,
-};
-
-class BpArcVideoBridge : public BpInterface<IArcVideoBridge> {
-public:
-    BpArcVideoBridge(const sp<IBinder>& impl) : BpInterface<IArcVideoBridge>(impl) { }
-
-    virtual ::arc::MojoBootstrapResult bootstrapVideoAcceleratorFactory() {
-        Parcel data, reply;
-        ALOGV("bootstrapVideoAcceleratorFactory");
-        data.writeInterfaceToken(IArcVideoBridge::getInterfaceDescriptor());
-        status_t status = remote()->transact(
-                BOOTSTRAP_VIDEO_ACCELERATOR_FACTORY, data, &reply, 0);
-        if (status != 0) {
-            ALOGE("transact failed: %d", status);
-            return arc::MojoBootstrapResult();
-        }
-        return arc::MojoBootstrapResult::createFromParcel(reply);
-    }
-
-    virtual int32_t hostVersion() {
-        Parcel data, reply;
-        ALOGV("hostVersion");
-        data.writeInterfaceToken(IArcVideoBridge::getInterfaceDescriptor());
-        status_t status = remote()->transact(HOST_VERSION, data, &reply, 0);
-        if (status != 0) {
-            ALOGE("transact failed: %d", status);
-            return false;
-        }
-        return reply.readInt32();
-    }
-};
-
-IMPLEMENT_META_INTERFACE(ArcVideoBridge, "android.os.IArcVideoBridge");
-
-status_t BnArcVideoBridge::onTransact(
-        uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
-    switch(code) {
-        case BOOTSTRAP_VIDEO_ACCELERATOR_FACTORY: {
-            ALOGV("BOOTSTRAP_VIDEO_ACCELERATOR_FACTORY");
-            CHECK_INTERFACE(IArcVideoBridge, data, reply);
-            arc::MojoBootstrapResult result = bootstrapVideoAcceleratorFactory();
-            return result.writeToParcel(reply);
-        }
-        case HOST_VERSION: {
-            ALOGV("HOST_VERSION");
-            CHECK_INTERFACE(IArcVideoBridge, data, reply);
-            reply->writeInt32(hostVersion());
-            return OK;
-        }
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-}  // namespace android
diff --git a/services/surfaceflinger/LayerStats.cpp b/services/surfaceflinger/LayerStats.cpp
index 04ab121..2a67955 100644
--- a/services/surfaceflinger/LayerStats.cpp
+++ b/services/surfaceflinger/LayerStats.cpp
@@ -68,7 +68,7 @@
         base::StringAppendF(&key, ",%s", layerCompositionType(layer->hwcCompositionType));
         base::StringAppendF(&key, ",%d", layer->isProtected);
         base::StringAppendF(&key, ",%s", layerTransform(layer->hwcTransform));
-        base::StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format));
+        base::StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format).c_str());
         base::StringAppendF(&key, ",%s", layer->dataspace.c_str());
         base::StringAppendF(&key, ",%s",
                             destinationLocation(layer->hwcFrame.left, layerGlobal.resolution[0],
@@ -162,8 +162,8 @@
     return getCompositionName(static_cast<hwc2_composition_t>(compositionType));
 }
 
-const char* LayerStats::layerPixelFormat(int32_t pixelFormat) {
-    return decodePixelFormat(pixelFormat).c_str();
+std::string LayerStats::layerPixelFormat(int32_t pixelFormat) {
+    return decodePixelFormat(pixelFormat);
 }
 
 std::string LayerStats::scaleRatioWH(const LayerProtoParser::Layer* layer) {
diff --git a/services/surfaceflinger/LayerStats.h b/services/surfaceflinger/LayerStats.h
index 7a190fd..bd17d82 100644
--- a/services/surfaceflinger/LayerStats.h
+++ b/services/surfaceflinger/LayerStats.h
@@ -50,7 +50,7 @@
     // Return the name of the composition type
     static const char* layerCompositionType(int32_t compositionType);
     // Return the name of the pixel format
-    static const char* layerPixelFormat(int32_t pixelFormat);
+    static std::string layerPixelFormat(int32_t pixelFormat);
     // Calculate scale ratios of layer's width/height with rotation information
     static std::string scaleRatioWH(const LayerProtoParser::Layer* layer);
     // Calculate scale ratio from source to destination and convert to string
diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
index 36424b9..cca84e5 100644
--- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter
+++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
@@ -1,5 +1,5 @@
 {
         "presubmit": {
-            "filter": "LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*"
+            "filter": "LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*:-CropLatchingTest.FinalCropLatchingBufferOldSize"
         }
 }
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index f1556d8..eec505e 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -211,13 +211,20 @@
             return *this;
         }
 
-        auto& addCapability(HWC2::Capability cap) {
-            mCapabilities.emplace(cap);
+        auto& setCapabilities(const std::unordered_set<HWC2::Capability>* capabilities) {
+            mCapabilities = capabilities;
             return *this;
         }
 
         void inject(TestableSurfaceFlinger* flinger, Hwc2::Composer* composer) {
-            auto display = std::make_unique<HWC2Display>(*composer, mCapabilities, mHwcDisplayId,
+            static const std::unordered_set<HWC2::Capability> defaultCapabilities;
+            if (mCapabilities == nullptr) mCapabilities = &defaultCapabilities;
+
+            // Caution - Make sure that any values passed by reference here do
+            // not refer to an instance owned by FakeHwcDisplayInjector. This
+            // class has temporary lifetime, while the constructed HWC2::Display
+            // is much longer lived.
+            auto display = std::make_unique<HWC2Display>(*composer, *mCapabilities, mHwcDisplayId,
                                                          mHwcDisplayType);
 
             auto config = HWC2::Display::Config::Builder(*display, mActiveConfig);
@@ -247,7 +254,7 @@
         int32_t mDpiX = DEFAULT_DPI;
         int32_t mDpiY = DEFAULT_DPI;
         int32_t mActiveConfig = DEFAULT_ACTIVE_CONFIG;
-        std::unordered_set<HWC2::Capability> mCapabilities;
+        const std::unordered_set<HWC2::Capability>* mCapabilities = nullptr;
     };
 
     class FakeDisplayDeviceInjector {
diff --git a/services/vr/performanced/task.cpp b/services/vr/performanced/task.cpp
index c2f078e..bda1682 100644
--- a/services/vr/performanced/task.cpp
+++ b/services/vr/performanced/task.cpp
@@ -115,7 +115,7 @@
     std::istream file_stream(&filebuf);
 
     for (std::string line; std::getline(file_stream, line);) {
-      auto offset = line.find(":");
+      auto offset = line.find(':');
       if (offset == std::string::npos) {
         ALOGW("ReadStatusFields: Failed to find delimiter \":\" in line=\"%s\"",
               line.c_str());
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index 8817e8d..5722810 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 1
-define VERSION_PATCH 84
+define VERSION_PATCH 86
 
 // API limits
 define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
@@ -45,6 +45,10 @@
 define VK_QUEUE_FAMILY_EXTERNAL         -2
 @extension("VK_EXT_queue_family_foreign")
 define VK_QUEUE_FAMILY_FOREIGN_EXT      -3
+@extension("VK_MAX_DRIVER_NAME_SIZE_KHR") // 197
+define VK_MAX_DRIVER_NAME_SIZE_KHR      256
+@extension("VK_MAX_DRIVER_NAME_SIZE_KHR") // 197
+define VK_MAX_DRIVER_INFO_SIZE_KHR      256
 
 // API keywords
 define VK_TRUE        1
@@ -173,6 +177,10 @@
 @extension("VK_AMD_shader_image_load_store_lod") define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION 1
 @extension("VK_AMD_shader_image_load_store_lod") define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME "VK_AMD_shader_image_load_store_lod"
 
+// 51
+@extension("VK_NV_corner_sampled_image") define VK_NV_CORNER_SAMPLED_IMAGE_SPEC_VERSION 2
+@extension("VK_NV_corner_sampled_image") define VK_NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME "VK_NV_corner_sampled_image"
+
 // 54
 @extension("VK_KHR_multiview") define VK_KHR_MULTIVIEW_SPEC_VERSION 1
 @extension("VK_KHR_multiview") define VK_KHR_MULTIVIEW_EXTENSION_NAME "VK_KHR_multiview"
@@ -501,10 +509,22 @@
 @extension("VK_EXT_descriptor_indexing") define VK_EXT_DESCRIPTOR_INDEXING_SPEC_VERSION 2
 @extension("VK_EXT_descriptor_indexing") define VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME "VK_EXT_descriptor_indexing"
 
-// 165
+// 163
 @extension("VK_EXT_shader_viewport_index_layer") define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION 1
 @extension("VK_EXT_shader_viewport_index_layer") define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME "VK_EXT_shader_viewport_index_layer"
 
+// 165
+@extension("VK_NV_shading_rate_image") define VK_NV_SHADING_RATE_IMAGE_SPEC_VERSION 3
+@extension("VK_NV_shading_rate_image") define VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME "VK_NV_shading_rate_image"
+
+// 166
+@extension("VK_NVX_raytracing") define VK_NVX_RAYTRACING_SPEC_VERSION 1
+@extension("VK_NVX_raytracing") define VK_NVX_RAYTRACING_EXTENSION_NAME "VK_NVX_raytracing"
+
+// 167
+@extension("VK_NV_representative_fragment_test") define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION 1
+@extension("VK_NV_representative_fragment_test") define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME "VK_NV_representative_fragment_test"
+
 // 169
 @extension("VK_KHR_maintenance3") define VK_KHR_MAINTENANCE3_SPEC_VERSION 1
 @extension("VK_KHR_maintenance3") define VK_KHR_MAINTENANCE3_EXTENSION_NAME "VK_KHR_maintenance3"
@@ -529,6 +549,10 @@
 @extension("VK_AMD_buffer_marker") define VK_AMD_BUFFER_MARKER_SPEC_VERSION 1
 @extension("VK_AMD_buffer_marker") define VK_AMD_BUFFER_MARKER_EXTENSION_NAME "VK_AMD_buffer_marker"
 
+// 181
+@extension("VK_KHR_shader_atomic_int64") define VK_KHR_SHADER_ATOMIC_INT64_SPEC_VERSION 1
+@extension("VK_KHR_shader_atomic_int64") define VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME "VK_KHR_shader_atomic_int64"
+
 // 186
 @extension("VK_AMD_shader_core_properties") define VK_AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION 1
 @extension("VK_AMD_shader_core_properties") define VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_AMD_shader_core_properties"
@@ -537,10 +561,34 @@
 @extension("VK_EXT_vertex_attribute_divisor") define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 2
 @extension("VK_EXT_vertex_attribute_divisor") define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor"
 
+// 197
+@extension("VK_KHR_driver_properties") define VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION 1
+@extension("VK_KHR_driver_properties") define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME "VK_KHR_driver_properties"
+
 // 199
 @extension("VK_NV_shader_subgroup_partitioned") define VK_NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION 1
 @extension("VK_NV_shader_subgroup_partitioned") define VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_NV_shader_subgroup_partitioned"
 
+// 202
+@extension("VK_NV_compute_shader_derivatives") define VK_NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION 1
+@extension("VK_NV_compute_shader_derivatives") define VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME "VK_NV_compute_shader_derivatives"
+
+// 203
+@extension("VK_NV_mesh_shader") define VK_NV_MESH_SHADER_SPEC_VERSION 1
+@extension("VK_NV_mesh_shader") define VK_NV_MESH_SHADER_EXTENSION_NAME "VK_NV_mesh_shader"
+
+// 204
+@extension("VK_NV_fragment_shader_barycentric") define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1
+@extension("VK_NV_fragment_shader_barycentric") define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_NV_fragment_shader_barycentric"
+
+// 205
+@extension("VK_NV_shader_image_footprint") define VK_NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION 1
+@extension("VK_NV_shader_image_footprint") define VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME "VK_NV_shader_image_footprint"
+
+// 206
+@extension("VK_NV_scissor_exclusive") define VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION 1
+@extension("VK_NV_scissor_exclusive") define VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME "VK_NV_scissor_exclusive"
+
 // 207
 @extension("VK_NV_device_diagnostic_checkpoints") define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION 2
 @extension("VK_NV_device_diagnostic_checkpoints") define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME "VK_NV_device_diagnostic_checkpoints"
@@ -620,6 +668,9 @@
 // 161
 @extension("VK_EXT_validation_cache") @nonDispatchHandle type u64 VkValidationCacheEXT
 
+// 166
+@extension("VK_NVX_raytracing") @nonDispatchHandle type u64 VkAccelerationStructureNVX
+
 /////////////
 //  Enums  //
 /////////////
@@ -648,6 +699,9 @@
     //@extension("VK_KHR_maintenance2") // 118
     VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR  = 1000117000,
     VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR  = 1000117001,
+
+    //@extension("VK_NV_shading_rate_image") // 165
+    VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV                 = 1000164003,
 }
 
 enum VkAttachmentLoadOp {
@@ -712,12 +766,18 @@
 
     //@extension("VK_EXT_inline_uniform_block") // 139
     VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT             = 1000138000,
+
+    //@extension("VK_NVX_raytracing") // 166
+    VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NVX           = 1000165000,
 }
 
 enum VkQueryType {
     VK_QUERY_TYPE_OCCLUSION                                 = 0x00000000,
     VK_QUERY_TYPE_PIPELINE_STATISTICS                       = 0x00000001, /// Optional
     VK_QUERY_TYPE_TIMESTAMP                                 = 0x00000002,
+
+    //@extension("VK_NVX_raytracing") // 166
+    VK_QUERY_TYPE_COMPACTED_SIZE_NVX                        = 1000165000,
 }
 
 enum VkBorderColor {
@@ -732,6 +792,9 @@
 enum VkPipelineBindPoint {
     VK_PIPELINE_BIND_POINT_GRAPHICS                         = 0x00000000,
     VK_PIPELINE_BIND_POINT_COMPUTE                          = 0x00000001,
+
+    //@extension("VK_NVX_raytracing") // 166
+    VK_PIPELINE_BIND_POINT_RAYTRACING_NVX                   = 1000165000,
 }
 
 enum VkPrimitiveTopology {
@@ -1387,6 +1450,9 @@
     //@extension("VK_AMD_texture_gather_bias_lod") // 42
     VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD  = 1000041000,
 
+    //@extension("VK_NV_corner_sampled_image") // 51
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV  = 1000050000,
+
     //@extension("VK_KHR_multiview") // 54
     VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR     = 1000053000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR    = 1000053001,
@@ -1671,6 +1737,29 @@
     VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT    = 1000161003,
     VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT   = 1000161004,
 
+    //@extension("VK_NV_shading_rate_image") // 165
+    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV = 1000164000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV = 1000164001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV = 1000164002,
+    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV = 1000164005,
+
+    //@extension("VK_NVX_raytracing") // 166
+    VK_STRUCTURE_TYPE_RAYTRACING_PIPELINE_CREATE_INFO_NVX = 1000165000,
+    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NVX = 1000165001,
+    VK_STRUCTURE_TYPE_GEOMETRY_INSTANCE_NVX = 1000165002,
+    VK_STRUCTURE_TYPE_GEOMETRY_NVX = 1000165003,
+    VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NVX = 1000165004,
+    VK_STRUCTURE_TYPE_GEOMETRY_AABB_NVX = 1000165005,
+    VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NVX = 1000165006,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_ACCELERATION_STRUCTURE_INFO_NVX = 1000165007,
+    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NVX = 1000165008,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAYTRACING_PROPERTIES_NVX = 1000165009,
+    VK_STRUCTURE_TYPE_HIT_SHADER_MODULE_CREATE_INFO_NVX = 1000165010,
+
+    //@extension("VK_NV_representative_fragment_test") // 167
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV = 1000166000,
+    VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV = 1000166001,
+
     //@extension("VK_KHR_maintenance3") // 169
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR      = 1000168000,
     VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR                 = 1000168001,
@@ -1686,6 +1775,12 @@
     VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT                    = 1000178001,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT   = 1000178002,
 
+    //@extension("VK_KHR_shader_atomic_int64") // 181
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR  = 1000180000,
+
+    //@extension("VK_KHR_driver_properties") // 197
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR             = 1000196000,
+
     //@extension("VK_AMD_shader_core_properties") // 186
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD        = 1000185000,
 
@@ -1791,6 +1886,13 @@
 
     //@extension("VK_EXT_sample_locations") // 144
     VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT                   = 1000143000,
+
+    //@extension("VK_NV_shading_rate_image") // 165
+    VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV       = 1000164004,
+    VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV        = 1000164006,
+
+    //@extension("VK_NV_scissor_exclusive") // 206
+    VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV                   = 1000205001,
 }
 
 enum VkObjectType {
@@ -1853,6 +1955,9 @@
 
     //@extension("VK_EXT_validation_cache") // 161
     VK_OBJECT_TYPE_VALIDATION_CACHE_EXT                     = 1000160000,
+
+    //@extension("VK_NVX_raytracing") // 166
+    VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NVX               = 1000165000,
 }
 
 
@@ -1974,6 +2079,9 @@
 
     //@extension("VK_KHR_sampler_ycbcr_conversion") // 157
     VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = 1000156000,
+
+    //@extension("VK_NVX_raytracing") // 166
+    VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NVX_EXT  = 1000165000,
 }
 
 @extension("VK_AMD_rasterization_order") // 19
@@ -2124,6 +2232,48 @@
     VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT              = 1,
 }
 
+@extension("VK_NV_shading_rate_image") // 165
+enum VkShadingRatePaletteEntryNV {
+    VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV                 = 0,
+    VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV       = 1,
+    VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV        = 2,
+    VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV        = 3,
+    VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV        = 4,
+    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV         = 5,
+    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV    = 6,
+    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV    = 7,
+    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV    = 8,
+    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV    = 9,
+    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV    = 10,
+    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV    = 11,
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+enum VkCoarseSampleOrderTypeNV {
+    VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV                  = 0,
+    VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV                   = 1,
+    VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV              = 2,
+    VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV             = 3,
+}
+
+@extension("VK_NVX_raytracing") // 166
+enum VkGeometryTypeNVX {
+    VK_GEOMETRY_TYPE_TRIANGLES_NVX                          = 0,
+    VK_GEOMETRY_TYPE_AABBS_NVX                              = 1,
+}
+
+@extension("VK_NVX_raytracing") // 166
+enum VkAccelerationStructureTypeNVX {
+    VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NVX            = 0,
+    VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NVX         = 1,
+}
+
+@extension("VK_NVX_raytracing") // 166
+enum VkCopyAccelerationStructureModeNVX {
+    VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NVX           = 0,
+    VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NVX         = 1,
+}
+
 @extension("VK_EXT_global_priority") // 175
 enum VkQueueGlobalPriorityEXT {
     VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT                        = 128,
@@ -2132,6 +2282,19 @@
     VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT                   = 1024,
 }
 
+@extension("VK_KHR_driver_properties") // 197
+enum VkDriverIdKHR {
+    VK_DRIVER_ID_AMD_PROPRIETARY_KHR                        = 1,
+    VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR                        = 2,
+    VK_DRIVER_ID_MESA_RADV_KHR                              = 3,
+    VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR                     = 4,
+    VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR              = 5,
+    VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR                 = 6,
+    VK_DRIVER_ID_IMAGINATION_PROPRIETARY_KHR                = 7,
+    VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR                   = 8,
+    VK_DRIVER_ID_ARM_PROPRIETARY_KHR                        = 9,
+}
+
 /////////////////
 //  Bitfields  //
 /////////////////
@@ -2203,6 +2366,13 @@
 
     //@extension("VK_EXT_conditional_rendering") // 82
     VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT            = 0x00100000,
+
+    //@extension("VK_NV_shading_rate_image") // 165
+    VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV                = 0x00800000,
+
+    //@extension("VK_NVX_raytracing") // 166
+    VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NVX           = 0x00200000,
+    VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NVX          = 0x00400000,
 }
 
 /// Buffer usage flags
@@ -2220,6 +2390,9 @@
 
     //@extension("VK_EXT_conditional_rendering") // 82
     VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT           = 0x00000200,
+
+    //@extension("VK_NVX_raytracing") // 166
+    VK_BUFFER_USAGE_RAYTRACING_BIT_NVX                      = 0x00000400,
 }
 
 /// Buffer creation flags
@@ -2245,6 +2418,18 @@
     VK_SHADER_STAGE_ALL_GRAPHICS                            = 0x0000001F,
 
     VK_SHADER_STAGE_ALL                                     = 0x7FFFFFFF,
+
+    //@extension("VK_NVX_raytracing") // 166
+    VK_SHADER_STAGE_RAYGEN_BIT_NVX                          = 0x00000100,
+    VK_SHADER_STAGE_ANY_HIT_BIT_NVX                         = 0x00000200,
+    VK_SHADER_STAGE_CLOSEST_HIT_BIT_NVX                     = 0x00000400,
+    VK_SHADER_STAGE_MISS_BIT_NVX                            = 0x00000800,
+    VK_SHADER_STAGE_INTERSECTION_BIT_NVX                    = 0x00001000,
+    VK_SHADER_STAGE_CALLABLE_BIT_NVX                        = 0x00002000,
+
+    //@extension("VK_NV_mesh_shader") // 203
+    VK_SHADER_STAGE_TASK_BIT_NV                             = 0x00000040,
+    VK_SHADER_STAGE_MESH_BIT_NV                             = 0x00000080,
 }
 
 /// Descriptor pool create flags
@@ -2272,6 +2457,9 @@
     VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT             = 0x00000020,    /// Can be used as framebuffer depth/stencil attachment
     VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT                 = 0x00000040,    /// Image data not needed outside of rendering
     VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT                     = 0x00000080,    /// Can be used as framebuffer input attachment
+
+    //@extension("VK_NV_shading_rate_image") // 165
+    VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV                = 0x00000100,
 }
 
 /// Image creation flags
@@ -2310,6 +2498,9 @@
 
     //@extension("VK_EXT_sample_locations") // 144
     VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000,
+
+    //@extension("VK_NV_corner_sampled_image") // 51
+    VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV                   = 0x00002000,
 }
 
 /// Image view creation flags
@@ -2331,6 +2522,9 @@
     //@extension("VK_KHR_device_group") // 61
     VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = 0x00000008,
     VK_PIPELINE_CREATE_DISPATCH_BASE_KHR                    = 0x00000010,
+
+    //@extension("VK_NVX_raytracing") // 166
+    VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NVX                = 0x00000020,
 }
 
 /// Color component flags
@@ -2515,6 +2709,16 @@
 
     //@extension("VK_EXT_conditional_rendering") // 82
     VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT         = 0x00040000,
+
+    //@extension("VK_NV_shading_rate_image") // 165
+    VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV             = 0x00400000,
+
+    //@extension("VK_NVX_raytracing") // 166
+    VK_PIPELINE_STAGE_RAYTRACING_BIT_NVX                    = 0x00200000,
+
+    //@extension("VK_NV_mesh_shader") // 203
+    VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV                    = 0x00080000,
+    VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV                    = 0x00100000,
 }
 
 /// Render pass attachment description flags
@@ -3193,6 +3397,35 @@
     VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT     = 0x00000008,
 }
 
+@extension("VK_NVX_raytracing") // 166
+type VkFlags VkGeometryFlagsNVX
+@extension("VK_NVX_raytracing") // 166
+bitfield VkGeometryFlagBitsNVX {
+    VK_GEOMETRY_OPAQUE_BIT_NVX                          = 0x00000001,
+    VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NVX = 0x00000002,
+}
+
+@extension("VK_NVX_raytracing") // 166
+type VkFlags VkGeometryInstanceFlagsNVX
+@extension("VK_NVX_raytracing") // 166
+bitfield VkGeometryInstanceFlagBitsNVX {
+    VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NVX      = 0x00000001,
+    VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_FLIP_WINDING_BIT_NVX = 0x00000002,
+    VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NVX               = 0x00000004,
+    VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NVX            = 0x00000008,
+}
+
+@extension("VK_NVX_raytracing") // 166
+type VkFlags VkBuildAccelerationStructureFlagsNVX
+@extension("VK_NVX_raytracing") // 166
+bitfield VkBuildAccelerationStructureFlagBitsNVX {
+    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NVX        = 0x00000001,
+    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NVX    = 0x00000002,
+    VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NVX   = 0x00000004,
+    VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NVX   = 0x00000008,
+    VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NVX          = 0x00000010,
+}
+
 //////////////////
 //  Structures  //
 //////////////////
@@ -5154,6 +5387,13 @@
     u32[3]                                      computeWorkGroupSize
 }
 
+@extension("VK_NV_corner_sampled_image") // 51
+class VkPhysicalDeviceCornerSampledImageFeaturesNV {
+    VkStructureType                             sType
+    void*                                       pNext
+    VkBool32                                    cornerSampledImage
+}
+
 @extension("VK_KHR_multiview") // 54
 class VkRenderPassMultiviewCreateInfoKHR {
     VkStructureType                             sType
@@ -6779,6 +7019,179 @@
     u32                                             maxVariableDescriptorCount
 }
 
+@extension("VK_NV_shading_rate_image") // 165
+class VkShadingRatePaletteNV {
+    u32                                             shadingRatePaletteEntryCount
+    const VkShadingRatePaletteEntryNV*              pShadingRatePaletteEntries
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+class VkPipelineViewportShadingRateImageStateCreateInfoNV {
+    VkStructureType                                 sType
+    const void*                                     pNext
+    VkBool32                                        shadingRateImageEnable
+    u32                                             viewportCount
+    const VkShadingRatePaletteNV*                   pShadingRatePalettes
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+class VkPhysicalDeviceShadingRateImageFeaturesNV {
+    VkStructureType                                 sType
+    void*                                           pNext
+    VkBool32                                        shadingRateImage
+    VkBool32                                        shadingRateCoarseSampleOrder
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+class VkPhysicalDeviceShadingRateImagePropertiesNV {
+    VkStructureType                                 sType
+    void*                                           pNext
+    VkExtent2D                                      shadingRateTexelSize
+    u32                                             shadingRatePaletteSize
+    u32                                             shadingRateMaxCoarseSamples
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+class VkCoarseSampleLocationNV {
+    u32                                             pixelX
+    u32                                             pixelY
+    u32                                             sample
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+class VkCoarseSampleOrderCustomNV {
+    VkShadingRatePaletteEntryNV                     shadingRate
+    u32                                             sampleCount
+    u32                                             sampleLocationCount
+    const VkCoarseSampleLocationNV*                 pSampleLocations
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+class VkPipelineViewportCoarseSampleOrderStateCreateInfoNV {
+    VkStructureType                                 sType
+    const void*                                     pNext
+    VkCoarseSampleOrderTypeNV                       sampleOrderType
+    u32                                             customSampleOrderCount
+    const VkCoarseSampleOrderCustomNV*              pCustomSampleOrders
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkRaytracingPipelineCreateInfoNVX {
+    VkStructureType                                 sType
+    const void*                                     pNext
+    VkPipelineCreateFlags                           flags
+    u32                                             stageCount
+    const VkPipelineShaderStageCreateInfo*          pStages
+    const u32*                                      pGroupNumbers
+    u32                                             maxRecursionDepth
+    VkPipelineLayout                                layout
+    VkPipeline                                      basePipelineHandle
+    s32                                             basePipelineIndex
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkGeometryTrianglesNVX {
+    VkStructureType                                 sType
+    const void*                                     pNext
+    VkBuffer                                        vertexData
+    VkDeviceSize                                    vertexOffset
+    u32                                             vertexCount
+    VkDeviceSize                                    vertexStride
+    VkFormat                                        vertexFormat
+    VkBuffer                                        indexData
+    VkDeviceSize                                    indexOffset
+    u32                                             indexCount
+    VkIndexType                                     indexType
+    VkBuffer                                        transformData
+    VkDeviceSize                                    transformOffset
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkGeometryAABBNVX {
+    VkStructureType                                 sType
+    const void*                                     pNext
+    VkBuffer                                        aabbData
+    u32                                             numAABBs
+    u32                                             stride
+    VkDeviceSize                                    offset
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkGeometryDataNVX {
+    VkGeometryTrianglesNVX                          triangles
+    VkGeometryAABBNVX                               aabbs
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkGeometryNVX {
+    VkStructureType                                 sType
+    const void*                                     pNext
+    VkGeometryTypeNVX                               geometryType
+    VkGeometryDataNVX                               geometry
+    VkGeometryFlagsNVX                              flags
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkAccelerationStructureCreateInfoNVX {
+    VkStructureType                                 sType
+    const void*                                     pNext
+    VkAccelerationStructureTypeNVX                  type
+    VkBuildAccelerationStructureFlagsNVX            flags
+    VkDeviceSize                                    compactedSize
+    u32                                             instanceCount
+    u32                                             geometryCount
+    const VkGeometryNVX*                            pGeometries
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkBindAccelerationStructureMemoryInfoNVX {
+    VkStructureType                                 sType
+    const void*                                     pNext
+    VkAccelerationStructureNVX                      accelerationStructure
+    VkDeviceMemory                                  memory
+    VkDeviceSize                                    memoryOffset
+    u32                                             deviceIndexCount
+    const u32*                                      pDeviceIndices
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkDescriptorAccelerationStructureInfoNVX {
+    VkStructureType                                 sType
+    const void*                                     pNext
+    u32                                             accelerationStructureCount
+    const VkAccelerationStructureNVX*               pAccelerationStructures
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkAccelerationStructureMemoryRequirementsInfoNVX {
+    VkStructureType                                 sType
+    const void*                                     pNext
+    VkAccelerationStructureNVX                      accelerationStructure
+}
+
+@extension("VK_NVX_raytracing") // 166
+class VkPhysicalDeviceRaytracingPropertiesNVX {
+    VkStructureType                                 sType
+    void*                                           pNext
+    u32                                             shaderHeaderSize
+    u32                                             maxRecursionDepth
+    u32                                             maxGeometryCount
+}
+
+@extension("VK_NV_representative_fragment_test") // 167
+class VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV {
+    VkStructureType                                 sType
+    void*                                           pNext
+    VkBool32                                        representativeFragmentTest
+}
+
+@extension("VK_NV_representative_fragment_test") // 167
+class VkPipelineRepresentativeFragmentTestStateCreateInfoNV {
+    VkStructureType                                 sType
+    const void*                                     pNext
+    VkBool32                                        representativeFragmentTestEnable
+}
+
 @extension("VK_KHR_maintenance3") // 169
 class VkPhysicalDeviceMaintenance3PropertiesKHR {
     VkStructureType                                 sType
@@ -6832,6 +7245,14 @@
     VkDeviceSize                                    minImportedHostPointerAlignment
 }
 
+@extension("VK_KHR_shader_atomic_int64") // 181
+class VkPhysicalDeviceShaderAtomicInt64FeaturesKHR {
+    VkStructureType                                 sType
+    void*                                           pNext
+    VkBool32                                        shaderBufferInt64Atomics
+    VkBool32                                        shaderSharedInt64Atomics
+}
+
 @extension("VK_AMD_shader_core_properties") // 186
 class VkPhysicalDeviceShaderCorePropertiesAMD {
     VkStructureType                                 sType
@@ -6881,6 +7302,94 @@
     VkBool32                                        vertexAttributeInstanceRateZeroDivisor
 }
 
+@extension("VK_KHR_driver_properties") // 197
+class VkConformanceVersionKHR {
+    u8                                              major
+    u8                                              minor
+    u8                                              subminor
+    u8                                              patch
+}
+
+@extension("VK_KHR_driver_properties") // 197
+class VkPhysicalDeviceDriverPropertiesKHR {
+    VkStructureType                                 sType
+    void*                                           pNext
+    u32                                             driverID
+    char[VK_MAX_DRIVER_NAME_SIZE_KHR]               driverName
+    char[VK_MAX_DRIVER_INFO_SIZE_KHR]               driverInfo
+    VkConformanceVersionKHR                         conformanceVersion
+}
+
+@extension("VK_NV_compute_shader_derivatives") // 202
+class VkPhysicalDeviceComputeShaderDerivativesFeaturesNV {
+    VkStructureType                                 sType
+    void*                                           pNext
+    VkBool32                                        computeDerivativeGroupQuads
+    VkBool32                                        computeDerivativeGroupLinear
+}
+
+@extension("VK_NV_mesh_shader") // 203
+class VkPhysicalDeviceMeshShaderFeaturesNV {
+    VkStructureType                                 sType
+    void*                                           pNext
+    VkBool32                                        taskShader
+    VkBool32                                        meshShader
+}
+
+@extension("VK_NV_mesh_shader") // 203
+class VkPhysicalDeviceMeshShaderPropertiesNV {
+    VkStructureType                                 sType
+    void*                                           pNext
+    u32                                             maxDrawMeshTasksCount
+    u32                                             maxTaskWorkGroupInvocations
+    u32[3]                                          maxTaskWorkGroupSize
+    u32                                             maxTaskTotalMemorySize
+    u32                                             maxTaskOutputCount
+    u32                                             maxMeshWorkGroupInvocations
+    u32[3]                                          maxMeshWorkGroupSize
+    u32                                             maxMeshTotalMemorySize
+    u32                                             maxMeshOutputVertices
+    u32                                             maxMeshOutputPrimitives
+    u32                                             maxMeshMultiviewViewCount
+    u32                                             meshOutputPerVertexGranularity
+    u32                                             meshOutputPerPrimitiveGranularity
+}
+
+@extension("VK_NV_mesh_shader") // 203
+class VkDrawMeshTasksIndirectCommandNV {
+    u32                                             taskCount
+    u32                                             firstTask
+}
+
+@extension("VK_NV_fragment_shader_barycentric") // 204
+class VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV {
+    VkStructureType                                 sType
+    void*                                           pNext
+    VkBool32                                        fragmentShaderBarycentric
+}
+
+@extension("VK_NV_shader_image_footprint") // 205
+class VkPhysicalDeviceShaderImageFootprintFeaturesNV {
+    VkStructureType                                 sType
+    void*                                           pNext
+    VkBool32                                        imageFootprint
+}
+
+@extension("VK_NV_scissor_exclusive") // 206
+class VkPipelineViewportExclusiveScissorStateCreateInfoNV {
+    VkStructureType                                 sType
+    const void*                                     pNext
+    u32                                             exclusiveScissorCount
+    const VkRect2D*                                 pExclusiveScissors
+}
+
+@extension("VK_NV_scissor_exclusive") // 206
+class VkPhysicalDeviceExclusiveScissorFeaturesNV {
+    VkStructureType                                 sType
+    void*                                           pNext
+    VkBool32                                        exclusiveScissor
+}
+
 @extension("VK_NV_device_diagnostic_checkpoints") // 207
 class VkQueueFamilyCheckpointPropertiesNV {
     VkStructureType                                 sType
@@ -10653,6 +11162,155 @@
     return ?
 }
 
+@extension("VK_NV_shading_rate_image") // 165
+cmd void vkCmdBindShadingRateImageNV(
+        VkCommandBuffer                             commandBuffer,
+        VkImageView                                 imageView,
+        VkImageLayout                               imageLayout) {
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+cmd void vkCmdSetViewportShadingRatePaletteNV(
+        VkCommandBuffer                             commandBuffer,
+        u32                                         firstViewport,
+        u32                                         viewportCount,
+        const VkShadingRatePaletteNV*               pShadingRatePalettes) {
+}
+
+@extension("VK_NV_shading_rate_image") // 165
+cmd void vkCmdSetCoarseSampleOrderNV(
+        VkCommandBuffer                             commandBuffer,
+        VkCoarseSampleOrderTypeNV                   sampleOrderType,
+        u32                                         customSampleOrderCount,
+        const VkCoarseSampleOrderCustomNV*          pCustomSampleOrders) {
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd VkResult vkCreateAccelerationStructureNVX(
+        VkDevice                                    device,
+        const VkAccelerationStructureCreateInfoNVX* pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkAccelerationStructureNVX*                 pAccelerationStructure) {
+    return ?
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd void vkDestroyAccelerationStructureNVX(
+        VkDevice                                    device,
+        VkAccelerationStructureNVX                  accelerationStructure,
+        const VkAllocationCallbacks*                pAllocator) {
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd void vkGetAccelerationStructureMemoryRequirementsNVX(
+        VkDevice                                                device,
+        const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo,
+        VkMemoryRequirements2KHR*                               pMemoryRequirements) {
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd void vkGetAccelerationStructureScratchMemoryRequirementsNVX(
+        VkDevice                                                device,
+        const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo,
+        VkMemoryRequirements2KHR*                               pMemoryRequirements) {
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd VkResult vkBindAccelerationStructureMemoryNVX(
+        VkDevice                                        device,
+        u32                                             bindInfoCount,
+        const VkBindAccelerationStructureMemoryInfoNVX* pBindInfos) {
+    return ?
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd void vkCmdBuildAccelerationStructureNVX(
+        VkCommandBuffer                             commandBuffer,
+        VkAccelerationStructureTypeNVX              type,
+        u32                                         instanceCount,
+        VkBuffer                                    instanceData,
+        VkDeviceSize                                instanceOffset,
+        u32                                         geometryCount,
+        const VkGeometryNVX*                        pGeometries,
+        VkBuildAccelerationStructureFlagsNVX        flags,
+        VkBool32                                    update,
+        VkAccelerationStructureNVX                  dst,
+        VkAccelerationStructureNVX                  src,
+        VkBuffer                                    scratch,
+        VkDeviceSize                                scratchOffset) {
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd void vkCmdCopyAccelerationStructureNVX(
+        VkCommandBuffer                             commandBuffer,
+        VkAccelerationStructureNVX                  dst,
+        VkAccelerationStructureNVX                  src,
+        VkCopyAccelerationStructureModeNVX          mode) {
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd void vkCmdTraceRaysNVX(
+        VkCommandBuffer                             commandBuffer,
+        VkBuffer                                    raygenShaderBindingTableBuffer,
+        VkDeviceSize                                raygenShaderBindingOffset,
+        VkBuffer                                    missShaderBindingTableBuffer,
+        VkDeviceSize                                missShaderBindingOffset,
+        VkDeviceSize                                missShaderBindingStride,
+        VkBuffer                                    hitShaderBindingTableBuffer,
+        VkDeviceSize                                hitShaderBindingOffset,
+        VkDeviceSize                                hitShaderBindingStride,
+        u32                                         width,
+        u32                                         height) {
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd VkResult vkCreateRaytracingPipelinesNVX(
+        VkDevice                                    device,
+        VkPipelineCache                             pipelineCache,
+        u32                                         createInfoCount,
+        const VkRaytracingPipelineCreateInfoNVX*    pCreateInfos,
+        const VkAllocationCallbacks*                pAllocator,
+        VkPipeline*                                 pPipelines) {
+    return ?
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd VkResult vkGetRaytracingShaderHandlesNVX(
+        VkDevice                                    device,
+        VkPipeline                                  pipeline,
+        u32                                         firstGroup,
+        u32                                         groupCount,
+        platform.size_t                             dataSize,
+        void*                                       pData) {
+    return ?
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd VkResult vkGetAccelerationStructureHandleNVX(
+        VkDevice                                    device,
+        VkAccelerationStructureNVX                  accelerationStructure,
+        platform.size_t                             dataSize,
+        void*                                       pData) {
+    return ?
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd void vkCmdWriteAccelerationStructurePropertiesNVX(
+        VkCommandBuffer                             commandBuffer,
+        VkAccelerationStructureNVX                  accelerationStructure,
+        VkQueryType                                 queryType,
+        VkQueryPool                                 queryPool,
+        u32                                         query) {
+}
+
+@extension("VK_NVX_raytracing") // 166
+cmd VkResult vkCompileDeferredNVX(
+        VkDevice                                    device,
+        VkPipeline                                  pipeline,
+        u32                                         shader) {
+    return ?
+}
+
 @extension("VK_KHR_maintenance3") // 169
 cmd void vkGetDescriptorSetLayoutSupportKHR(
         VkDevice                                    device,
@@ -10700,6 +11358,41 @@
         u32                                         marker) {
 }
 
+@extension("VK_NV_mesh_shader") // 203
+cmd void vkCmdDrawMeshTasksNV(
+        VkCommandBuffer                             commandBuffer,
+        u32                                         taskCount,
+        u32                                         firstTask) {
+}
+
+@extension("VK_NV_mesh_shader") // 203
+cmd void vkCmdDrawMeshTasksIndirectNV(
+        VkCommandBuffer                             commandBuffer,
+        VkBuffer                                    buffer,
+        VkDeviceSize                                offset,
+        u32                                         drawCount,
+        u32                                         stride) {
+}
+
+@extension("VK_NV_mesh_shader") // 203
+cmd void vkCmdDrawMeshTasksIndirectCountNV(
+        VkCommandBuffer                             commandBuffer,
+        VkBuffer                                    buffer,
+        VkDeviceSize                                offset,
+        VkBuffer                                    countBuffer,
+        VkDeviceSize                                countBufferOffset,
+        u32                                         maxDrawCount,
+        u32                                         stride) {
+}
+
+@extension("VK_NV_scissor_exclusive") // 206
+cmd void vkCmdSetExclusiveScissorNV(
+        VkCommandBuffer                             commandBuffer,
+        u32                                         firstExclusiveScissor,
+        u32                                         exclusiveScissorCount,
+        const VkRect2D*                             pExclusiveScissors) {
+}
+
 @extension("VK_NV_device_diagnostic_checkpoints") // 207
 cmd void vkCmdSetCheckpointNV(
         VkCommandBuffer                             commandBuffer,
diff --git a/vulkan/include/vulkan/vulkan_core.h b/vulkan/include/vulkan/vulkan_core.h
index fe45014..39f4dc6 100644
--- a/vulkan/include/vulkan/vulkan_core.h
+++ b/vulkan/include/vulkan/vulkan_core.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 84
+#define VK_HEADER_VERSION 86
 
 
 #define VK_NULL_HANDLE 0
@@ -298,6 +298,7 @@
     VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001,
     VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002,
     VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000,
     VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000,
     VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV = 1000056001,
     VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000,
@@ -404,15 +405,41 @@
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT = 1000161002,
     VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT = 1000161003,
     VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT = 1000161004,
+    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV = 1000164000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV = 1000164001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV = 1000164002,
+    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV = 1000164005,
+    VK_STRUCTURE_TYPE_RAYTRACING_PIPELINE_CREATE_INFO_NVX = 1000165000,
+    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NVX = 1000165001,
+    VK_STRUCTURE_TYPE_GEOMETRY_INSTANCE_NVX = 1000165002,
+    VK_STRUCTURE_TYPE_GEOMETRY_NVX = 1000165003,
+    VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NVX = 1000165004,
+    VK_STRUCTURE_TYPE_GEOMETRY_AABB_NVX = 1000165005,
+    VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NVX = 1000165006,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_ACCELERATION_STRUCTURE_INFO_NVX = 1000165007,
+    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NVX = 1000165008,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAYTRACING_PROPERTIES_NVX = 1000165009,
+    VK_STRUCTURE_TYPE_HIT_SHADER_MODULE_CREATE_INFO_NVX = 1000165010,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV = 1000166000,
+    VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV = 1000166001,
     VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT = 1000174000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR = 1000177000,
     VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT = 1000178000,
     VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT = 1000178001,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT = 1000178002,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR = 1000180000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000,
     VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = 1000196000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV = 1000201000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV = 1000202000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV = 1000202001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV = 1000203000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV = 1000204000,
+    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_EXCLUSIVE_SCISSOR_STATE_CREATE_INFO_NV = 1000205000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV = 1000205002,
     VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV = 1000206000,
     VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV = 1000206001,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = 1000211000,
@@ -806,6 +833,7 @@
     VK_QUERY_TYPE_OCCLUSION = 0,
     VK_QUERY_TYPE_PIPELINE_STATISTICS = 1,
     VK_QUERY_TYPE_TIMESTAMP = 2,
+    VK_QUERY_TYPE_COMPACTED_SIZE_NVX = 1000165000,
     VK_QUERY_TYPE_BEGIN_RANGE = VK_QUERY_TYPE_OCCLUSION,
     VK_QUERY_TYPE_END_RANGE = VK_QUERY_TYPE_TIMESTAMP,
     VK_QUERY_TYPE_RANGE_SIZE = (VK_QUERY_TYPE_TIMESTAMP - VK_QUERY_TYPE_OCCLUSION + 1),
@@ -835,6 +863,7 @@
     VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001,
     VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002,
     VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR = 1000111000,
+    VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV = 1000164003,
     VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL,
     VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL,
     VK_IMAGE_LAYOUT_BEGIN_RANGE = VK_IMAGE_LAYOUT_UNDEFINED,
@@ -1068,6 +1097,9 @@
     VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV = 1000087000,
     VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT = 1000099000,
     VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT = 1000143000,
+    VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV = 1000164004,
+    VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV = 1000164006,
+    VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV = 1000205001,
     VK_DYNAMIC_STATE_BEGIN_RANGE = VK_DYNAMIC_STATE_VIEWPORT,
     VK_DYNAMIC_STATE_END_RANGE = VK_DYNAMIC_STATE_STENCIL_REFERENCE,
     VK_DYNAMIC_STATE_RANGE_SIZE = (VK_DYNAMIC_STATE_STENCIL_REFERENCE - VK_DYNAMIC_STATE_VIEWPORT + 1),
@@ -1131,6 +1163,7 @@
     VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9,
     VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10,
     VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000,
+    VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NVX = 1000165000,
     VK_DESCRIPTOR_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_TYPE_SAMPLER,
     VK_DESCRIPTOR_TYPE_END_RANGE = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
     VK_DESCRIPTOR_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT - VK_DESCRIPTOR_TYPE_SAMPLER + 1),
@@ -1159,6 +1192,7 @@
 typedef enum VkPipelineBindPoint {
     VK_PIPELINE_BIND_POINT_GRAPHICS = 0,
     VK_PIPELINE_BIND_POINT_COMPUTE = 1,
+    VK_PIPELINE_BIND_POINT_RAYTRACING_NVX = 1000165000,
     VK_PIPELINE_BIND_POINT_BEGIN_RANGE = VK_PIPELINE_BIND_POINT_GRAPHICS,
     VK_PIPELINE_BIND_POINT_END_RANGE = VK_PIPELINE_BIND_POINT_COMPUTE,
     VK_PIPELINE_BIND_POINT_RANGE_SIZE = (VK_PIPELINE_BIND_POINT_COMPUTE - VK_PIPELINE_BIND_POINT_GRAPHICS + 1),
@@ -1230,6 +1264,7 @@
     VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX = 1000086001,
     VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000,
     VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000,
+    VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NVX = 1000165000,
     VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE,
     VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION,
     VK_OBJECT_TYPE_BEGIN_RANGE = VK_OBJECT_TYPE_UNKNOWN,
@@ -1297,6 +1332,7 @@
     VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020,
     VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040,
     VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080,
+    VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00000100,
     VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkImageUsageFlagBits;
 typedef VkFlags VkImageUsageFlags;
@@ -1314,6 +1350,7 @@
     VK_IMAGE_CREATE_EXTENDED_USAGE_BIT = 0x00000100,
     VK_IMAGE_CREATE_PROTECTED_BIT = 0x00000800,
     VK_IMAGE_CREATE_DISJOINT_BIT = 0x00000200,
+    VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV = 0x00002000,
     VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT = 0x00001000,
     VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT,
     VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT,
@@ -1393,6 +1430,10 @@
     VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000,
     VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000,
     VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX = 0x00020000,
+    VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00400000,
+    VK_PIPELINE_STAGE_RAYTRACING_BIT_NVX = 0x00200000,
+    VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = 0x00080000,
+    VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = 0x00100000,
     VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkPipelineStageFlagBits;
 typedef VkFlags VkPipelineStageFlags;
@@ -1481,6 +1522,7 @@
     VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080,
     VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100,
     VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200,
+    VK_BUFFER_USAGE_RAYTRACING_BIT_NVX = 0x00000400,
     VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkBufferUsageFlagBits;
 typedef VkFlags VkBufferUsageFlags;
@@ -1495,6 +1537,7 @@
     VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004,
     VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008,
     VK_PIPELINE_CREATE_DISPATCH_BASE = 0x00000010,
+    VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NVX = 0x00000020,
     VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT,
     VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = VK_PIPELINE_CREATE_DISPATCH_BASE,
     VK_PIPELINE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
@@ -1511,6 +1554,14 @@
     VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020,
     VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F,
     VK_SHADER_STAGE_ALL = 0x7FFFFFFF,
+    VK_SHADER_STAGE_RAYGEN_BIT_NVX = 0x00000100,
+    VK_SHADER_STAGE_ANY_HIT_BIT_NVX = 0x00000200,
+    VK_SHADER_STAGE_CLOSEST_HIT_BIT_NVX = 0x00000400,
+    VK_SHADER_STAGE_MISS_BIT_NVX = 0x00000800,
+    VK_SHADER_STAGE_INTERSECTION_BIT_NVX = 0x00001000,
+    VK_SHADER_STAGE_CALLABLE_BIT_NVX = 0x00002000,
+    VK_SHADER_STAGE_TASK_BIT_NV = 0x00000040,
+    VK_SHADER_STAGE_MESH_BIT_NV = 0x00000080,
     VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkShaderStageFlagBits;
 typedef VkFlags VkPipelineVertexInputStateCreateFlags;
@@ -1596,6 +1647,9 @@
     VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX = 0x00020000,
     VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX = 0x00040000,
     VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000,
+    VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000,
+    VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NVX = 0x00200000,
+    VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NVX = 0x00400000,
     VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkAccessFlagBits;
 typedef VkFlags VkAccessFlags;
@@ -4062,6 +4116,8 @@
     VkMemoryRequirements    memoryRequirements;
 } VkMemoryRequirements2;
 
+typedef VkMemoryRequirements2 VkMemoryRequirements2KHR;
+
 typedef struct VkSparseImageMemoryRequirements2 {
     VkStructureType                    sType;
     void*                              pNext;
@@ -5826,8 +5882,6 @@
 
 typedef VkImageSparseMemoryRequirementsInfo2 VkImageSparseMemoryRequirementsInfo2KHR;
 
-typedef VkMemoryRequirements2 VkMemoryRequirements2KHR;
-
 typedef VkSparseImageMemoryRequirements2 VkSparseImageMemoryRequirements2KHR;
 
 
@@ -5992,6 +6046,60 @@
 
 
 
+#define VK_KHR_shader_atomic_int64 1
+#define VK_KHR_SHADER_ATOMIC_INT64_SPEC_VERSION 1
+#define VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME "VK_KHR_shader_atomic_int64"
+
+typedef struct VkPhysicalDeviceShaderAtomicInt64FeaturesKHR {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           shaderBufferInt64Atomics;
+    VkBool32           shaderSharedInt64Atomics;
+} VkPhysicalDeviceShaderAtomicInt64FeaturesKHR;
+
+
+
+#define VK_KHR_driver_properties 1
+#define VK_MAX_DRIVER_NAME_SIZE_KHR       256
+#define VK_MAX_DRIVER_INFO_SIZE_KHR       256
+#define VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION 1
+#define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME "VK_KHR_driver_properties"
+
+
+typedef enum VkDriverIdKHR {
+    VK_DRIVER_ID_AMD_PROPRIETARY_KHR = 1,
+    VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR = 2,
+    VK_DRIVER_ID_MESA_RADV_KHR = 3,
+    VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR = 4,
+    VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR = 5,
+    VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR = 6,
+    VK_DRIVER_ID_IMAGINATION_PROPRIETARY_KHR = 7,
+    VK_DRIVER_ID_QUALCOMM_PROPRIETARY_KHR = 8,
+    VK_DRIVER_ID_ARM_PROPRIETARY_KHR = 9,
+    VK_DRIVER_ID_BEGIN_RANGE_KHR = VK_DRIVER_ID_AMD_PROPRIETARY_KHR,
+    VK_DRIVER_ID_END_RANGE_KHR = VK_DRIVER_ID_ARM_PROPRIETARY_KHR,
+    VK_DRIVER_ID_RANGE_SIZE_KHR = (VK_DRIVER_ID_ARM_PROPRIETARY_KHR - VK_DRIVER_ID_AMD_PROPRIETARY_KHR + 1),
+    VK_DRIVER_ID_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkDriverIdKHR;
+
+typedef struct VkConformanceVersionKHR {
+    uint8_t    major;
+    uint8_t    minor;
+    uint8_t    subminor;
+    uint8_t    patch;
+} VkConformanceVersionKHR;
+
+typedef struct VkPhysicalDeviceDriverPropertiesKHR {
+    VkStructureType            sType;
+    void*                      pNext;
+    uint32_t                   driverID;
+    char                       driverName[VK_MAX_DRIVER_NAME_SIZE_KHR];
+    char                       driverInfo[VK_MAX_DRIVER_INFO_SIZE_KHR];
+    VkConformanceVersionKHR    conformanceVersion;
+} VkPhysicalDeviceDriverPropertiesKHR;
+
+
+
 #define VK_KHR_vulkan_memory_model 1
 #define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 2
 #define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model"
@@ -6049,6 +6157,7 @@
     VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT = 33,
     VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000,
     VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000,
+    VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NVX_EXT = 1000165000,
     VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT,
     VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT,
     VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT,
@@ -6355,6 +6464,18 @@
 #define VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME "VK_AMD_shader_image_load_store_lod"
 
 
+#define VK_NV_corner_sampled_image 1
+#define VK_NV_CORNER_SAMPLED_IMAGE_SPEC_VERSION 2
+#define VK_NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME "VK_NV_corner_sampled_image"
+
+typedef struct VkPhysicalDeviceCornerSampledImageFeaturesNV {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           cornerSampledImage;
+} VkPhysicalDeviceCornerSampledImageFeaturesNV;
+
+
+
 #define VK_IMG_format_pvrtc 1
 #define VK_IMG_FORMAT_PVRTC_SPEC_VERSION  1
 #define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc"
@@ -7711,6 +7832,397 @@
 #define VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME "VK_EXT_shader_viewport_index_layer"
 
 
+#define VK_NV_shading_rate_image 1
+#define VK_NV_SHADING_RATE_IMAGE_SPEC_VERSION 3
+#define VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME "VK_NV_shading_rate_image"
+
+
+typedef enum VkShadingRatePaletteEntryNV {
+    VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV = 0,
+    VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV = 1,
+    VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV = 2,
+    VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV = 3,
+    VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV = 4,
+    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV = 5,
+    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV = 6,
+    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV = 7,
+    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV = 8,
+    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV = 9,
+    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV = 10,
+    VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV = 11,
+    VK_SHADING_RATE_PALETTE_ENTRY_BEGIN_RANGE_NV = VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV,
+    VK_SHADING_RATE_PALETTE_ENTRY_END_RANGE_NV = VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV,
+    VK_SHADING_RATE_PALETTE_ENTRY_RANGE_SIZE_NV = (VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV - VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV + 1),
+    VK_SHADING_RATE_PALETTE_ENTRY_MAX_ENUM_NV = 0x7FFFFFFF
+} VkShadingRatePaletteEntryNV;
+
+typedef enum VkCoarseSampleOrderTypeNV {
+    VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV = 0,
+    VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV = 1,
+    VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV = 2,
+    VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV = 3,
+    VK_COARSE_SAMPLE_ORDER_TYPE_BEGIN_RANGE_NV = VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV,
+    VK_COARSE_SAMPLE_ORDER_TYPE_END_RANGE_NV = VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV,
+    VK_COARSE_SAMPLE_ORDER_TYPE_RANGE_SIZE_NV = (VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV - VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV + 1),
+    VK_COARSE_SAMPLE_ORDER_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkCoarseSampleOrderTypeNV;
+
+typedef struct VkShadingRatePaletteNV {
+    uint32_t                              shadingRatePaletteEntryCount;
+    const VkShadingRatePaletteEntryNV*    pShadingRatePaletteEntries;
+} VkShadingRatePaletteNV;
+
+typedef struct VkPipelineViewportShadingRateImageStateCreateInfoNV {
+    VkStructureType                  sType;
+    const void*                      pNext;
+    VkBool32                         shadingRateImageEnable;
+    uint32_t                         viewportCount;
+    const VkShadingRatePaletteNV*    pShadingRatePalettes;
+} VkPipelineViewportShadingRateImageStateCreateInfoNV;
+
+typedef struct VkPhysicalDeviceShadingRateImageFeaturesNV {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           shadingRateImage;
+    VkBool32           shadingRateCoarseSampleOrder;
+} VkPhysicalDeviceShadingRateImageFeaturesNV;
+
+typedef struct VkPhysicalDeviceShadingRateImagePropertiesNV {
+    VkStructureType    sType;
+    void*              pNext;
+    VkExtent2D         shadingRateTexelSize;
+    uint32_t           shadingRatePaletteSize;
+    uint32_t           shadingRateMaxCoarseSamples;
+} VkPhysicalDeviceShadingRateImagePropertiesNV;
+
+typedef struct VkCoarseSampleLocationNV {
+    uint32_t    pixelX;
+    uint32_t    pixelY;
+    uint32_t    sample;
+} VkCoarseSampleLocationNV;
+
+typedef struct VkCoarseSampleOrderCustomNV {
+    VkShadingRatePaletteEntryNV        shadingRate;
+    uint32_t                           sampleCount;
+    uint32_t                           sampleLocationCount;
+    const VkCoarseSampleLocationNV*    pSampleLocations;
+} VkCoarseSampleOrderCustomNV;
+
+typedef struct VkPipelineViewportCoarseSampleOrderStateCreateInfoNV {
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkCoarseSampleOrderTypeNV             sampleOrderType;
+    uint32_t                              customSampleOrderCount;
+    const VkCoarseSampleOrderCustomNV*    pCustomSampleOrders;
+} VkPipelineViewportCoarseSampleOrderStateCreateInfoNV;
+
+
+typedef void (VKAPI_PTR *PFN_vkCmdBindShadingRateImageNV)(VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout);
+typedef void (VKAPI_PTR *PFN_vkCmdSetViewportShadingRatePaletteNV)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkShadingRatePaletteNV* pShadingRatePalettes);
+typedef void (VKAPI_PTR *PFN_vkCmdSetCoarseSampleOrderNV)(VkCommandBuffer commandBuffer, VkCoarseSampleOrderTypeNV sampleOrderType, uint32_t customSampleOrderCount, const VkCoarseSampleOrderCustomNV* pCustomSampleOrders);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdBindShadingRateImageNV(
+    VkCommandBuffer                             commandBuffer,
+    VkImageView                                 imageView,
+    VkImageLayout                               imageLayout);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetViewportShadingRatePaletteNV(
+    VkCommandBuffer                             commandBuffer,
+    uint32_t                                    firstViewport,
+    uint32_t                                    viewportCount,
+    const VkShadingRatePaletteNV*               pShadingRatePalettes);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetCoarseSampleOrderNV(
+    VkCommandBuffer                             commandBuffer,
+    VkCoarseSampleOrderTypeNV                   sampleOrderType,
+    uint32_t                                    customSampleOrderCount,
+    const VkCoarseSampleOrderCustomNV*          pCustomSampleOrders);
+#endif
+
+#define VK_NVX_raytracing 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureNVX)
+
+#define VK_NVX_RAYTRACING_SPEC_VERSION    1
+#define VK_NVX_RAYTRACING_EXTENSION_NAME  "VK_NVX_raytracing"
+
+
+typedef enum VkGeometryTypeNVX {
+    VK_GEOMETRY_TYPE_TRIANGLES_NVX = 0,
+    VK_GEOMETRY_TYPE_AABBS_NVX = 1,
+    VK_GEOMETRY_TYPE_BEGIN_RANGE_NVX = VK_GEOMETRY_TYPE_TRIANGLES_NVX,
+    VK_GEOMETRY_TYPE_END_RANGE_NVX = VK_GEOMETRY_TYPE_AABBS_NVX,
+    VK_GEOMETRY_TYPE_RANGE_SIZE_NVX = (VK_GEOMETRY_TYPE_AABBS_NVX - VK_GEOMETRY_TYPE_TRIANGLES_NVX + 1),
+    VK_GEOMETRY_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkGeometryTypeNVX;
+
+typedef enum VkAccelerationStructureTypeNVX {
+    VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NVX = 0,
+    VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NVX = 1,
+    VK_ACCELERATION_STRUCTURE_TYPE_BEGIN_RANGE_NVX = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NVX,
+    VK_ACCELERATION_STRUCTURE_TYPE_END_RANGE_NVX = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NVX,
+    VK_ACCELERATION_STRUCTURE_TYPE_RANGE_SIZE_NVX = (VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NVX - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NVX + 1),
+    VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkAccelerationStructureTypeNVX;
+
+typedef enum VkCopyAccelerationStructureModeNVX {
+    VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NVX = 0,
+    VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NVX = 1,
+    VK_COPY_ACCELERATION_STRUCTURE_MODE_BEGIN_RANGE_NVX = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NVX,
+    VK_COPY_ACCELERATION_STRUCTURE_MODE_END_RANGE_NVX = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NVX,
+    VK_COPY_ACCELERATION_STRUCTURE_MODE_RANGE_SIZE_NVX = (VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NVX - VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NVX + 1),
+    VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkCopyAccelerationStructureModeNVX;
+
+
+typedef enum VkGeometryFlagBitsNVX {
+    VK_GEOMETRY_OPAQUE_BIT_NVX = 0x00000001,
+    VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NVX = 0x00000002,
+    VK_GEOMETRY_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkGeometryFlagBitsNVX;
+typedef VkFlags VkGeometryFlagsNVX;
+
+typedef enum VkGeometryInstanceFlagBitsNVX {
+    VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NVX = 0x00000001,
+    VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_FLIP_WINDING_BIT_NVX = 0x00000002,
+    VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NVX = 0x00000004,
+    VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NVX = 0x00000008,
+    VK_GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkGeometryInstanceFlagBitsNVX;
+typedef VkFlags VkGeometryInstanceFlagsNVX;
+
+typedef enum VkBuildAccelerationStructureFlagBitsNVX {
+    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NVX = 0x00000001,
+    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NVX = 0x00000002,
+    VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NVX = 0x00000004,
+    VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NVX = 0x00000008,
+    VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NVX = 0x00000010,
+    VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkBuildAccelerationStructureFlagBitsNVX;
+typedef VkFlags VkBuildAccelerationStructureFlagsNVX;
+
+typedef struct VkRaytracingPipelineCreateInfoNVX {
+    VkStructureType                           sType;
+    const void*                               pNext;
+    VkPipelineCreateFlags                     flags;
+    uint32_t                                  stageCount;
+    const VkPipelineShaderStageCreateInfo*    pStages;
+    const uint32_t*                           pGroupNumbers;
+    uint32_t                                  maxRecursionDepth;
+    VkPipelineLayout                          layout;
+    VkPipeline                                basePipelineHandle;
+    int32_t                                   basePipelineIndex;
+} VkRaytracingPipelineCreateInfoNVX;
+
+typedef struct VkGeometryTrianglesNVX {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkBuffer           vertexData;
+    VkDeviceSize       vertexOffset;
+    uint32_t           vertexCount;
+    VkDeviceSize       vertexStride;
+    VkFormat           vertexFormat;
+    VkBuffer           indexData;
+    VkDeviceSize       indexOffset;
+    uint32_t           indexCount;
+    VkIndexType        indexType;
+    VkBuffer           transformData;
+    VkDeviceSize       transformOffset;
+} VkGeometryTrianglesNVX;
+
+typedef struct VkGeometryAABBNVX {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkBuffer           aabbData;
+    uint32_t           numAABBs;
+    uint32_t           stride;
+    VkDeviceSize       offset;
+} VkGeometryAABBNVX;
+
+typedef struct VkGeometryDataNVX {
+    VkGeometryTrianglesNVX    triangles;
+    VkGeometryAABBNVX         aabbs;
+} VkGeometryDataNVX;
+
+typedef struct VkGeometryNVX {
+    VkStructureType       sType;
+    const void*           pNext;
+    VkGeometryTypeNVX     geometryType;
+    VkGeometryDataNVX     geometry;
+    VkGeometryFlagsNVX    flags;
+} VkGeometryNVX;
+
+typedef struct VkAccelerationStructureCreateInfoNVX {
+    VkStructureType                         sType;
+    const void*                             pNext;
+    VkAccelerationStructureTypeNVX          type;
+    VkBuildAccelerationStructureFlagsNVX    flags;
+    VkDeviceSize                            compactedSize;
+    uint32_t                                instanceCount;
+    uint32_t                                geometryCount;
+    const VkGeometryNVX*                    pGeometries;
+} VkAccelerationStructureCreateInfoNVX;
+
+typedef struct VkBindAccelerationStructureMemoryInfoNVX {
+    VkStructureType               sType;
+    const void*                   pNext;
+    VkAccelerationStructureNVX    accelerationStructure;
+    VkDeviceMemory                memory;
+    VkDeviceSize                  memoryOffset;
+    uint32_t                      deviceIndexCount;
+    const uint32_t*               pDeviceIndices;
+} VkBindAccelerationStructureMemoryInfoNVX;
+
+typedef struct VkDescriptorAccelerationStructureInfoNVX {
+    VkStructureType                      sType;
+    const void*                          pNext;
+    uint32_t                             accelerationStructureCount;
+    const VkAccelerationStructureNVX*    pAccelerationStructures;
+} VkDescriptorAccelerationStructureInfoNVX;
+
+typedef struct VkAccelerationStructureMemoryRequirementsInfoNVX {
+    VkStructureType               sType;
+    const void*                   pNext;
+    VkAccelerationStructureNVX    accelerationStructure;
+} VkAccelerationStructureMemoryRequirementsInfoNVX;
+
+typedef struct VkPhysicalDeviceRaytracingPropertiesNVX {
+    VkStructureType    sType;
+    void*              pNext;
+    uint32_t           shaderHeaderSize;
+    uint32_t           maxRecursionDepth;
+    uint32_t           maxGeometryCount;
+} VkPhysicalDeviceRaytracingPropertiesNVX;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureNVX)(VkDevice device, const VkAccelerationStructureCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNVX* pAccelerationStructure);
+typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNVX)(VkDevice device, VkAccelerationStructureNVX accelerationStructure, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsNVX)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureScratchMemoryRequirementsNVX)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements);
+typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNVX)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNVX* pBindInfos);
+typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNVX)(VkCommandBuffer commandBuffer, VkAccelerationStructureTypeNVX type, uint32_t instanceCount, VkBuffer instanceData, VkDeviceSize instanceOffset, uint32_t geometryCount, const VkGeometryNVX* pGeometries, VkBuildAccelerationStructureFlagsNVX flags, VkBool32 update, VkAccelerationStructureNVX dst, VkAccelerationStructureNVX src, VkBuffer scratch, VkDeviceSize scratchOffset);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNVX)(VkCommandBuffer commandBuffer, VkAccelerationStructureNVX dst, VkAccelerationStructureNVX src, VkCopyAccelerationStructureModeNVX mode);
+typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysNVX)(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, uint32_t width, uint32_t height);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateRaytracingPipelinesNVX)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRaytracingPipelineCreateInfoNVX* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
+typedef VkResult (VKAPI_PTR *PFN_vkGetRaytracingShaderHandlesNVX)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData);
+typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNVX)(VkDevice device, VkAccelerationStructureNVX accelerationStructure, size_t dataSize, void* pData);
+typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructurePropertiesNVX)(VkCommandBuffer commandBuffer, VkAccelerationStructureNVX accelerationStructure, VkQueryType queryType, VkQueryPool queryPool, uint32_t query);
+typedef VkResult (VKAPI_PTR *PFN_vkCompileDeferredNVX)(VkDevice device, VkPipeline pipeline, uint32_t shader);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureNVX(
+    VkDevice                                    device,
+    const VkAccelerationStructureCreateInfoNVX* pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkAccelerationStructureNVX*                 pAccelerationStructure);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureNVX(
+    VkDevice                                    device,
+    VkAccelerationStructureNVX                  accelerationStructure,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsNVX(
+    VkDevice                                    device,
+    const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo,
+    VkMemoryRequirements2KHR*                   pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureScratchMemoryRequirementsNVX(
+    VkDevice                                    device,
+    const VkAccelerationStructureMemoryRequirementsInfoNVX* pInfo,
+    VkMemoryRequirements2KHR*                   pMemoryRequirements);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryNVX(
+    VkDevice                                    device,
+    uint32_t                                    bindInfoCount,
+    const VkBindAccelerationStructureMemoryInfoNVX* pBindInfos);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNVX(
+    VkCommandBuffer                             commandBuffer,
+    VkAccelerationStructureTypeNVX              type,
+    uint32_t                                    instanceCount,
+    VkBuffer                                    instanceData,
+    VkDeviceSize                                instanceOffset,
+    uint32_t                                    geometryCount,
+    const VkGeometryNVX*                        pGeometries,
+    VkBuildAccelerationStructureFlagsNVX        flags,
+    VkBool32                                    update,
+    VkAccelerationStructureNVX                  dst,
+    VkAccelerationStructureNVX                  src,
+    VkBuffer                                    scratch,
+    VkDeviceSize                                scratchOffset);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureNVX(
+    VkCommandBuffer                             commandBuffer,
+    VkAccelerationStructureNVX                  dst,
+    VkAccelerationStructureNVX                  src,
+    VkCopyAccelerationStructureModeNVX          mode);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNVX(
+    VkCommandBuffer                             commandBuffer,
+    VkBuffer                                    raygenShaderBindingTableBuffer,
+    VkDeviceSize                                raygenShaderBindingOffset,
+    VkBuffer                                    missShaderBindingTableBuffer,
+    VkDeviceSize                                missShaderBindingOffset,
+    VkDeviceSize                                missShaderBindingStride,
+    VkBuffer                                    hitShaderBindingTableBuffer,
+    VkDeviceSize                                hitShaderBindingOffset,
+    VkDeviceSize                                hitShaderBindingStride,
+    uint32_t                                    width,
+    uint32_t                                    height);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateRaytracingPipelinesNVX(
+    VkDevice                                    device,
+    VkPipelineCache                             pipelineCache,
+    uint32_t                                    createInfoCount,
+    const VkRaytracingPipelineCreateInfoNVX*    pCreateInfos,
+    const VkAllocationCallbacks*                pAllocator,
+    VkPipeline*                                 pPipelines);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetRaytracingShaderHandlesNVX(
+    VkDevice                                    device,
+    VkPipeline                                  pipeline,
+    uint32_t                                    firstGroup,
+    uint32_t                                    groupCount,
+    size_t                                      dataSize,
+    void*                                       pData);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureHandleNVX(
+    VkDevice                                    device,
+    VkAccelerationStructureNVX                  accelerationStructure,
+    size_t                                      dataSize,
+    void*                                       pData);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructurePropertiesNVX(
+    VkCommandBuffer                             commandBuffer,
+    VkAccelerationStructureNVX                  accelerationStructure,
+    VkQueryType                                 queryType,
+    VkQueryPool                                 queryPool,
+    uint32_t                                    query);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCompileDeferredNVX(
+    VkDevice                                    device,
+    VkPipeline                                  pipeline,
+    uint32_t                                    shader);
+#endif
+
+#define VK_NV_representative_fragment_test 1
+#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_SPEC_VERSION 1
+#define VK_NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME "VK_NV_representative_fragment_test"
+
+typedef struct VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           representativeFragmentTest;
+} VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV;
+
+typedef struct VkPipelineRepresentativeFragmentTestStateCreateInfoNV {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkBool32           representativeFragmentTestEnable;
+} VkPipelineRepresentativeFragmentTestStateCreateInfoNV;
+
+
+
 #define VK_EXT_global_priority 1
 #define VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION 2
 #define VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME "VK_EXT_global_priority"
@@ -7845,6 +8357,133 @@
 #define VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_NV_shader_subgroup_partitioned"
 
 
+#define VK_NV_compute_shader_derivatives 1
+#define VK_NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION 1
+#define VK_NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME "VK_NV_compute_shader_derivatives"
+
+typedef struct VkPhysicalDeviceComputeShaderDerivativesFeaturesNV {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           computeDerivativeGroupQuads;
+    VkBool32           computeDerivativeGroupLinear;
+} VkPhysicalDeviceComputeShaderDerivativesFeaturesNV;
+
+
+
+#define VK_NV_mesh_shader 1
+#define VK_NV_MESH_SHADER_SPEC_VERSION    1
+#define VK_NV_MESH_SHADER_EXTENSION_NAME  "VK_NV_mesh_shader"
+
+typedef struct VkPhysicalDeviceMeshShaderFeaturesNV {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           taskShader;
+    VkBool32           meshShader;
+} VkPhysicalDeviceMeshShaderFeaturesNV;
+
+typedef struct VkPhysicalDeviceMeshShaderPropertiesNV {
+    VkStructureType    sType;
+    void*              pNext;
+    uint32_t           maxDrawMeshTasksCount;
+    uint32_t           maxTaskWorkGroupInvocations;
+    uint32_t           maxTaskWorkGroupSize[3];
+    uint32_t           maxTaskTotalMemorySize;
+    uint32_t           maxTaskOutputCount;
+    uint32_t           maxMeshWorkGroupInvocations;
+    uint32_t           maxMeshWorkGroupSize[3];
+    uint32_t           maxMeshTotalMemorySize;
+    uint32_t           maxMeshOutputVertices;
+    uint32_t           maxMeshOutputPrimitives;
+    uint32_t           maxMeshMultiviewViewCount;
+    uint32_t           meshOutputPerVertexGranularity;
+    uint32_t           meshOutputPerPrimitiveGranularity;
+} VkPhysicalDeviceMeshShaderPropertiesNV;
+
+typedef struct VkDrawMeshTasksIndirectCommandNV {
+    uint32_t    taskCount;
+    uint32_t    firstTask;
+} VkDrawMeshTasksIndirectCommandNV;
+
+
+typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksNV)(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawMeshTasksIndirectCountNV)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksNV(
+    VkCommandBuffer                             commandBuffer,
+    uint32_t                                    taskCount,
+    uint32_t                                    firstTask);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectNV(
+    VkCommandBuffer                             commandBuffer,
+    VkBuffer                                    buffer,
+    VkDeviceSize                                offset,
+    uint32_t                                    drawCount,
+    uint32_t                                    stride);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawMeshTasksIndirectCountNV(
+    VkCommandBuffer                             commandBuffer,
+    VkBuffer                                    buffer,
+    VkDeviceSize                                offset,
+    VkBuffer                                    countBuffer,
+    VkDeviceSize                                countBufferOffset,
+    uint32_t                                    maxDrawCount,
+    uint32_t                                    stride);
+#endif
+
+#define VK_NV_fragment_shader_barycentric 1
+#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION 1
+#define VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME "VK_NV_fragment_shader_barycentric"
+
+typedef struct VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           fragmentShaderBarycentric;
+} VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV;
+
+
+
+#define VK_NV_shader_image_footprint 1
+#define VK_NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION 1
+#define VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME "VK_NV_shader_image_footprint"
+
+typedef struct VkPhysicalDeviceShaderImageFootprintFeaturesNV {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           imageFootprint;
+} VkPhysicalDeviceShaderImageFootprintFeaturesNV;
+
+
+
+#define VK_NV_scissor_exclusive 1
+#define VK_NV_SCISSOR_EXCLUSIVE_SPEC_VERSION 1
+#define VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME "VK_NV_scissor_exclusive"
+
+typedef struct VkPipelineViewportExclusiveScissorStateCreateInfoNV {
+    VkStructureType    sType;
+    const void*        pNext;
+    uint32_t           exclusiveScissorCount;
+    const VkRect2D*    pExclusiveScissors;
+} VkPipelineViewportExclusiveScissorStateCreateInfoNV;
+
+typedef struct VkPhysicalDeviceExclusiveScissorFeaturesNV {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           exclusiveScissor;
+} VkPhysicalDeviceExclusiveScissorFeaturesNV;
+
+
+typedef void (VKAPI_PTR *PFN_vkCmdSetExclusiveScissorNV)(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor, uint32_t exclusiveScissorCount, const VkRect2D* pExclusiveScissors);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdSetExclusiveScissorNV(
+    VkCommandBuffer                             commandBuffer,
+    uint32_t                                    firstExclusiveScissor,
+    uint32_t                                    exclusiveScissorCount,
+    const VkRect2D*                             pExclusiveScissors);
+#endif
+
 #define VK_NV_device_diagnostic_checkpoints 1
 #define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION 2
 #define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME "VK_NV_device_diagnostic_checkpoints"
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 56bc35e..fdbd969 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -1165,27 +1165,28 @@
         result = EnumeratePhysicalDevices(instance, &device_count, nullptr);
         if (result < 0)
             return result;
+
         if (!pPhysicalDeviceGroupProperties) {
             *pPhysicalDeviceGroupCount = device_count;
             return result;
         }
 
-        device_count = std::min(device_count, *pPhysicalDeviceGroupCount);
         if (!device_count) {
             *pPhysicalDeviceGroupCount = 0;
             return result;
         }
+        device_count = std::min(device_count, *pPhysicalDeviceGroupCount);
+        if (!device_count)
+            return VK_INCOMPLETE;
 
         android::Vector<VkPhysicalDevice> devices;
         devices.resize(device_count);
-
+        *pPhysicalDeviceGroupCount = device_count;
         result = EnumeratePhysicalDevices(instance, &device_count,
                                           devices.editArray());
         if (result < 0)
             return result;
 
-        devices.resize(device_count);
-        *pPhysicalDeviceGroupCount = device_count;
         for (uint32_t i = 0; i < device_count; ++i) {
             pPhysicalDeviceGroupProperties[i].physicalDeviceCount = 1;
             pPhysicalDeviceGroupProperties[i].physicalDevices[0] = devices[i];
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index b32977a..009b257 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -78,7 +78,7 @@
           native_bridge_(false),
           refcount_(0) {}
 
-    LayerLibrary(LayerLibrary&& other)
+    LayerLibrary(LayerLibrary&& other) noexcept
         : path_(std::move(other.path_)),
           filename_(std::move(other.filename_)),
           dlhandle_(other.dlhandle_),
@@ -545,7 +545,7 @@
     }
 }
 
-LayerRef::LayerRef(LayerRef&& other) : layer_(other.layer_) {
+LayerRef::LayerRef(LayerRef&& other) noexcept : layer_(other.layer_) {
     other.layer_ = nullptr;
 }
 
diff --git a/vulkan/libvulkan/layers_extensions.h b/vulkan/libvulkan/layers_extensions.h
index 07ac1a3..1dae456 100644
--- a/vulkan/libvulkan/layers_extensions.h
+++ b/vulkan/libvulkan/layers_extensions.h
@@ -27,7 +27,7 @@
 class LayerRef {
    public:
     explicit LayerRef(const Layer* layer);
-    LayerRef(LayerRef&& other);
+    LayerRef(LayerRef&& other) noexcept;
     ~LayerRef();
     LayerRef(const LayerRef&) = delete;
     LayerRef& operator=(const LayerRef&) = delete;