Merge "libbase: add Fdopen that takes a unique_fd."
diff --git a/adb/Android.bp b/adb/Android.bp
index 3685687..1469e77 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -142,6 +142,8 @@
         "client/fastdeploycallbacks.cpp",
     ],
 
+    generated_headers: ["platform_tools_version"],
+
     target: {
         linux: {
             srcs: ["client/usb_linux.cpp"],
@@ -311,6 +313,8 @@
         "daemon/include",
     ],
 
+    generated_headers: ["platform_tools_version"],
+
     static_libs: [
         "libdiagnose_usb",
         "libqemu_pipe",
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 8e028f4..791899e 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -45,6 +45,7 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <build/version.h>
+#include <platform_tools_version.h>
 
 #include "adb_auth.h"
 #include "adb_io.h"
@@ -65,10 +66,11 @@
     // Don't change the format of this --- it's parsed by ddmlib.
     return android::base::StringPrintf(
         "Android Debug Bridge version %d.%d.%d\n"
-        "Version %s\n"
+        "Version %s-%s\n"
         "Installed as %s\n",
         ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION,
-        android::build::GetBuildNumber().c_str(), android::base::GetExecutablePath().c_str());
+        PLATFORM_TOOLS_VERSION, android::build::GetBuildNumber().c_str(),
+        android::base::GetExecutablePath().c_str());
 }
 
 void fatal(const char *fmt, ...) {
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index f764a0e..f6ce8e2 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -24,7 +24,7 @@
 
 #include <android-base/macros.h>
 
-int syntax_error(const char*, ...);
+int syntax_error(const char*, ...) __attribute__((__format__(__printf__, 1, 2)));
 
 void close_stdin();
 
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index b55ae95..451422f 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -130,7 +130,7 @@
         " pull [-a] REMOTE... LOCAL\n"
         "     copy files/dirs from device\n"
         "     -a: preserve file timestamp and mode\n"
-        " sync [all|data|odm|oem|product|system|vendor]\n"
+        " sync [all|data|odm|oem|product_services|product|system|vendor]\n"
         "     sync a local build from $ANDROID_PRODUCT_OUT to the device (default all)\n"
         "     -l: list but don't copy\n"
         "\n"
@@ -1713,7 +1713,8 @@
         }
 
         if (src.empty()) src = "all";
-        std::vector<std::string> partitions{"data", "odm", "oem", "product", "system", "vendor"};
+        std::vector<std::string> partitions{"data",   "odm",   "oem", "product", "product_services",
+                                            "system", "vendor"};
         bool found = false;
         for (const auto& partition : partitions) {
             if (src == "all" || src == partition) {
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 095ad98..a7e454d 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -56,15 +56,6 @@
     LOG(INFO) << adb_version();
 }
 
-#if defined(_WIN32)
-static BOOL WINAPI ctrlc_handler(DWORD type) {
-    // TODO: Consider trying to kill a starting up adb server (if we're in
-    // launch_server) by calling GenerateConsoleCtrlEvent().
-    exit(STATUS_CONTROL_C_EXIT);
-    return TRUE;
-}
-#endif
-
 void adb_server_cleanup() {
     // Upon exit, we want to clean up in the following order:
     //   1. close_smartsockets, so that we don't get any new clients
@@ -97,12 +88,16 @@
         }
     }
 
-    SetConsoleCtrlHandler(ctrlc_handler, TRUE);
-#else
+    // TODO: On Ctrl-C, consider trying to kill a starting up adb server (if we're in
+    // launch_server) by calling GenerateConsoleCtrlEvent().
+
+    // On Windows, SIGBREAK is when Ctrl-Break is pressed or the console window is closed. It should
+    // act like Ctrl-C.
+    signal(SIGBREAK, [](int) { raise(SIGINT); });
+#endif
     signal(SIGINT, [](int) {
         fdevent_run_on_main_thread([]() { exit(0); });
     });
-#endif
 
     char* leak = getenv("ADB_LEAK");
     if (leak && strcmp(leak, "1") == 0) {
diff --git a/adb/daemon/remount_service.cpp b/adb/daemon/remount_service.cpp
index ed5f944..76500d4 100644
--- a/adb/daemon/remount_service.cpp
+++ b/adb/daemon/remount_service.cpp
@@ -209,7 +209,7 @@
     bool system_verified = !(android::base::GetProperty("partition.system.verified", "").empty());
     bool vendor_verified = !(android::base::GetProperty("partition.vendor.verified", "").empty());
 
-    std::vector<std::string> partitions = {"/odm", "/oem", "/product", "/vendor"};
+    std::vector<std::string> partitions{"/odm", "/oem", "/product_services", "/product", "/vendor"};
     if (android::base::GetBoolProperty("ro.build.system_root_image", false)) {
         partitions.push_back("/");
     } else {
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index f32b5d5..3b91ddd 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -21,67 +21,66 @@
 
     compile_multilib: "first",
     srcs: [
-      "bootimg_utils.cpp",
-      "fs.cpp",
-      "socket.cpp",
-      "tcp.cpp",
-      "udp.cpp",
-      "util.cpp",
-      "fastboot_driver.cpp",
+        "bootimg_utils.cpp",
+        "fs.cpp",
+        "socket.cpp",
+        "tcp.cpp",
+        "udp.cpp",
+        "util.cpp",
+        "fastboot_driver.cpp",
     ],
 
     static_libs: [
-      "libziparchive",
-      "libsparse",
-      "libutils",
-      "liblog",
-      "libz",
-      "libdiagnose_usb",
-      "libbase",
-      "libcutils",
-      "libgtest",
-      "libgtest_main",
-      "libbase",
-      "libadb_host"
+        "libziparchive",
+        "libsparse",
+        "libutils",
+        "liblog",
+        "libz",
+        "libdiagnose_usb",
+        "libbase",
+        "libcutils",
+        "libgtest",
+        "libgtest_main",
+        "libbase",
+        "libadb_host",
     ],
 
     header_libs: [
-      "bootimg_headers"
+        "bootimg_headers",
     ],
 
     export_header_lib_headers: [
-      "bootimg_headers"
+        "bootimg_headers",
     ],
 
-
     target: {
-      linux: {
-        srcs: ["usb_linux.cpp"],
-      },
+        linux: {
+            srcs: ["usb_linux.cpp"],
+        },
 
-      darwin: {
-        srcs: ["usb_osx.cpp"],
+        darwin: {
+            srcs: ["usb_osx.cpp"],
 
-        host_ldlibs: [
-            "-framework CoreFoundation",
-            "-framework IOKit",
-        ],
-      },
+            host_ldlibs: [
+                "-framework CoreFoundation",
+                "-framework IOKit",
+            ],
+        },
 
-      windows: {
-        srcs: ["usb_windows.cpp"],
+        windows: {
+            srcs: ["usb_windows.cpp"],
 
-        host_ldlibs: [
-            "-lws2_32",
-        ],
-      },
+            host_ldlibs: [
+                "-lws2_32",
+            ],
+        },
     },
 
     cflags: [
-      "-Wall",
-      "-Wextra",
-      "-Werror",
-      "-Wunreachable-code",
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wunreachable-code",
     ],
 
     export_include_dirs: ["."],
@@ -141,3 +140,154 @@
 
     cpp_std: "c++17",
 }
+
+cc_defaults {
+    name: "fastboot_host_defaults",
+
+    use_version_lib: true,
+
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wunreachable-code",
+    ],
+
+    target: {
+        darwin: {
+            cflags: ["-Wno-unused-parameter"],
+            host_ldlibs: [
+                "-lpthread",
+                "-framework CoreFoundation",
+                "-framework IOKit",
+            ],
+        },
+        windows: {
+            enabled: true,
+
+            host_ldlibs: ["-lws2_32"],
+        },
+    },
+
+    stl: "libc++_static",
+
+    // Don't add anything here, we don't want additional shared dependencies
+    // on the host fastboot tool, and shared libraries that link against libc++
+    // will violate ODR.
+    shared_libs: [],
+
+    header_libs: ["bootimg_headers"],
+    static_libs: [
+        "libziparchive",
+        "libsparse",
+        "libutils",
+        "liblog",
+        "libz",
+        "libdiagnose_usb",
+        "libbase",
+        "libcutils",
+        "libgtest_host",
+    ],
+}
+
+//
+// Build host libfastboot.
+//
+
+cc_library_host_static {
+    name: "libfastboot",
+    defaults: ["fastboot_host_defaults"],
+
+    cpp_std: "c++17",
+    srcs: [
+        "bootimg_utils.cpp",
+        "engine.cpp",
+        "fastboot.cpp",
+        "fs.cpp",
+        "socket.cpp",
+        "tcp.cpp",
+        "udp.cpp",
+        "util.cpp",
+        "fastboot_driver.cpp",
+    ],
+
+    // Only version the final binaries
+    use_version_lib: false,
+    static_libs: ["libbuildversion"],
+
+    generated_headers: ["platform_tools_version"],
+
+    target: {
+        windows: {
+            srcs: ["usb_windows.cpp"],
+
+            include_dirs: ["development/host/windows/usb/api"],
+        },
+        darwin: {
+            srcs: ["usb_osx.cpp"],
+        },
+        linux_glibc: {
+            srcs: ["usb_linux.cpp"],
+        },
+    },
+}
+
+//
+// Build host fastboot / fastboot.exe
+//
+
+cc_binary_host {
+    name: "fastboot",
+    defaults: ["fastboot_host_defaults"],
+
+    srcs: ["main.cpp"],
+    static_libs: ["libfastboot"],
+
+    required: [
+        "mke2fs",
+        "make_f2fs",
+    ],
+
+    target: {
+        not_windows: {
+            required: [
+                "e2fsdroid",
+                "mke2fs.conf",
+                "sload_f2fs",
+            ],
+        },
+        windows: {
+            required: ["AdbWinUsbApi"],
+            shared_libs: ["AdbWinApi"],
+        },
+    },
+}
+
+//
+// Build host fastboot_test.
+//
+
+cc_test_host {
+    name: "fastboot_test",
+    defaults: ["fastboot_host_defaults"],
+
+    srcs: [
+        "fastboot_test.cpp",
+        "socket_mock.cpp",
+        "socket_test.cpp",
+        "tcp_test.cpp",
+        "udp_test.cpp",
+    ],
+
+    static_libs: ["libfastboot"],
+
+    target: {
+        windows: {
+            shared_libs: ["AdbWinApi"],
+        },
+        windows_x86_64: {
+            // Avoid trying to build for win64
+            enabled: false,
+        },
+    },
+}
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index 7da0a9f..e4c1317 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -14,89 +14,6 @@
 
 LOCAL_PATH:= $(call my-dir)
 
-include $(LOCAL_PATH)/../platform_tools_tool_version.mk
-
-fastboot_cflags := -Wall -Wextra -Werror -Wunreachable-code
-fastboot_cflags += -DFASTBOOT_VERSION="\"$(tool_version)\""
-fastboot_cflags_darwin := -Wno-unused-parameter
-fastboot_ldlibs_darwin := -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
-fastboot_ldlibs_windows := -lws2_32
-# Don't add anything here, we don't want additional shared dependencies
-# on the host fastboot tool, and shared libraries that link against libc++
-# will violate ODR.
-fastboot_shared_libs :=
-fastboot_static_libs := \
-    libziparchive \
-    libsparse \
-    libutils \
-    liblog \
-    libz \
-    libdiagnose_usb \
-    libbase \
-    libcutils \
-    libgtest_host \
-
-fastboot_stl := libc++_static
-
-#
-# Build host libfastboot.
-#
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libfastboot
-LOCAL_MODULE_HOST_OS := darwin linux windows
-
-LOCAL_SRC_FILES := \
-    bootimg_utils.cpp \
-    engine.cpp \
-    fastboot.cpp \
-    fs.cpp \
-    socket.cpp \
-    tcp.cpp \
-    udp.cpp \
-    util.cpp \
-    fastboot_driver.cpp \
-
-LOCAL_SRC_FILES_darwin := usb_osx.cpp
-LOCAL_SRC_FILES_linux := usb_linux.cpp
-LOCAL_SRC_FILES_windows := usb_windows.cpp
-
-LOCAL_C_INCLUDES_windows := development/host/windows/usb/api
-LOCAL_CFLAGS := $(fastboot_cflags)
-LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin)
-LOCAL_CPP_STD := c++17
-LOCAL_CXX_STL := $(fastboot_stl)
-LOCAL_HEADER_LIBRARIES := bootimg_headers
-LOCAL_LDLIBS_darwin := $(fastboot_ldlibs_darwin)
-LOCAL_LDLIBS_windows := $(fastboot_ldlibs_windows)
-LOCAL_SHARED_LIBRARIES := $(fastboot_shared_libs)
-LOCAL_STATIC_LIBRARIES := $(fastboot_static_libs)
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-#
-# Build host fastboot / fastboot.exe
-#
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := fastboot
-LOCAL_MODULE_HOST_OS := darwin linux windows
-
-LOCAL_CFLAGS := $(fastboot_cflags)
-LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin)
-LOCAL_CXX_STL := $(fastboot_stl)
-LOCAL_HEADER_LIBRARIES := bootimg_headers
-LOCAL_LDLIBS_darwin := $(fastboot_ldlibs_darwin)
-LOCAL_LDLIBS_windows := $(fastboot_ldlibs_windows)
-LOCAL_REQUIRED_MODULES := mke2fs make_f2fs
-LOCAL_REQUIRED_MODULES_darwin := e2fsdroid mke2fs.conf sload_f2fs
-LOCAL_REQUIRED_MODULES_linux := e2fsdroid mke2fs.conf sload_f2fs
-LOCAL_REQUIRED_MODULES_windows := AdbWinUsbApi
-LOCAL_SRC_FILES := main.cpp
-LOCAL_SHARED_LIBRARIES := $(fastboot_shared_libs)
-LOCAL_SHARED_LIBRARIES_windows := AdbWinApi
-LOCAL_STATIC_LIBRARIES := libfastboot $(fastboot_static_libs)
-include $(BUILD_HOST_EXECUTABLE)
-
 #
 # Package fastboot-related executables.
 #
@@ -111,30 +28,3 @@
 $(call dist-for-goals,dist_files sdk win_sdk,$(ALL_MODULES.host_cross_fastboot.BUILT))
 endif
 my_dist_files :=
-
-#
-# Build host fastboot_test.
-#
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := fastboot_test
-LOCAL_MODULE_HOST_OS := darwin linux windows
-LOCAL_MODULE_HOST_CROSS_ARCH := x86 # Avoid trying to build for win64.
-
-LOCAL_SRC_FILES := \
-    fastboot_test.cpp \
-    socket_mock.cpp \
-    socket_test.cpp \
-    tcp_test.cpp \
-    udp_test.cpp \
-
-LOCAL_CFLAGS := $(fastboot_cflags)
-LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin)
-LOCAL_CXX_STL := $(fastboot_stl)
-LOCAL_HEADER_LIBRARIES := bootimg_headers
-LOCAL_LDLIBS_darwin := $(fastboot_ldlibs_darwin)
-LOCAL_LDLIBS_windows := $(fastboot_ldlibs_windows)
-LOCAL_SHARED_LIBRARIES := $(fastboot_shared_libs)
-LOCAL_SHARED_LIBRARIES_windows := AdbWinApi
-LOCAL_STATIC_LIBRARIES := libfastboot $(fastboot_static_libs)
-include $(BUILD_HOST_NATIVE_TEST)
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index 1e853bf..b1c2958 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -42,34 +42,79 @@
 using ::android::hardware::boot::V1_0::Slot;
 using namespace android::fs_mgr;
 
+struct VariableHandlers {
+    // Callback to retrieve the value of a single variable.
+    std::function<bool(FastbootDevice*, const std::vector<std::string>&, std::string*)> get;
+    // Callback to retrieve all possible argument combinations, for getvar all.
+    std::function<std::vector<std::vector<std::string>>(FastbootDevice*)> get_all_args;
+};
+
+static void GetAllVars(FastbootDevice* device, const std::string& name,
+                       const VariableHandlers& handlers) {
+    if (!handlers.get_all_args) {
+        std::string message;
+        if (!handlers.get(device, std::vector<std::string>(), &message)) {
+            return;
+        }
+        device->WriteInfo(android::base::StringPrintf("%s:%s", name.c_str(), message.c_str()));
+        return;
+    }
+
+    auto all_args = handlers.get_all_args(device);
+    for (const auto& args : all_args) {
+        std::string message;
+        if (!handlers.get(device, args, &message)) {
+            continue;
+        }
+        std::string arg_string = android::base::Join(args, ":");
+        device->WriteInfo(android::base::StringPrintf("%s:%s:%s", name.c_str(), arg_string.c_str(),
+                                                      message.c_str()));
+    }
+}
+
 bool GetVarHandler(FastbootDevice* device, const std::vector<std::string>& args) {
-    using VariableHandler = std::function<bool(FastbootDevice*, const std::vector<std::string>&)>;
-    const std::unordered_map<std::string, VariableHandler> kVariableMap = {
-            {FB_VAR_VERSION, GetVersion},
-            {FB_VAR_VERSION_BOOTLOADER, GetBootloaderVersion},
-            {FB_VAR_VERSION_BASEBAND, GetBasebandVersion},
-            {FB_VAR_PRODUCT, GetProduct},
-            {FB_VAR_SERIALNO, GetSerial},
-            {FB_VAR_SECURE, GetSecure},
-            {FB_VAR_UNLOCKED, GetUnlocked},
-            {FB_VAR_MAX_DOWNLOAD_SIZE, GetMaxDownloadSize},
-            {FB_VAR_CURRENT_SLOT, ::GetCurrentSlot},
-            {FB_VAR_SLOT_COUNT, GetSlotCount},
-            {FB_VAR_HAS_SLOT, GetHasSlot},
-            {FB_VAR_SLOT_SUCCESSFUL, GetSlotSuccessful},
-            {FB_VAR_SLOT_UNBOOTABLE, GetSlotUnbootable},
-            {FB_VAR_PARTITION_SIZE, GetPartitionSize},
-            {FB_VAR_IS_LOGICAL, GetPartitionIsLogical},
-            {FB_VAR_IS_USERSPACE, GetIsUserspace}};
+    const std::unordered_map<std::string, VariableHandlers> kVariableMap = {
+            {FB_VAR_VERSION, {GetVersion, nullptr}},
+            {FB_VAR_VERSION_BOOTLOADER, {GetBootloaderVersion, nullptr}},
+            {FB_VAR_VERSION_BASEBAND, {GetBasebandVersion, nullptr}},
+            {FB_VAR_PRODUCT, {GetProduct, nullptr}},
+            {FB_VAR_SERIALNO, {GetSerial, nullptr}},
+            {FB_VAR_SECURE, {GetSecure, nullptr}},
+            {FB_VAR_UNLOCKED, {GetUnlocked, nullptr}},
+            {FB_VAR_MAX_DOWNLOAD_SIZE, {GetMaxDownloadSize, nullptr}},
+            {FB_VAR_CURRENT_SLOT, {::GetCurrentSlot, nullptr}},
+            {FB_VAR_SLOT_COUNT, {GetSlotCount, nullptr}},
+            {FB_VAR_HAS_SLOT, {GetHasSlot, GetAllPartitionArgsNoSlot}},
+            {FB_VAR_SLOT_SUCCESSFUL, {GetSlotSuccessful, nullptr}},
+            {FB_VAR_SLOT_UNBOOTABLE, {GetSlotUnbootable, nullptr}},
+            {FB_VAR_PARTITION_SIZE, {GetPartitionSize, GetAllPartitionArgsWithSlot}},
+            {FB_VAR_IS_LOGICAL, {GetPartitionIsLogical, GetAllPartitionArgsWithSlot}},
+            {FB_VAR_IS_USERSPACE, {GetIsUserspace, nullptr}}};
+
+    if (args.size() < 2) {
+        return device->WriteFail("Missing argument");
+    }
+
+    // Special case: return all variables that we can.
+    if (args[1] == "all") {
+        for (const auto& [name, handlers] : kVariableMap) {
+            GetAllVars(device, name, handlers);
+        }
+        return device->WriteOkay("");
+    }
 
     // args[0] is command name, args[1] is variable.
     auto found_variable = kVariableMap.find(args[1]);
     if (found_variable == kVariableMap.end()) {
-        return device->WriteStatus(FastbootResult::FAIL, "Unknown variable");
+        return device->WriteFail("Unknown variable");
     }
 
+    std::string message;
     std::vector<std::string> getvar_args(args.begin() + 2, args.end());
-    return found_variable->second(device, getvar_args);
+    if (!found_variable->second.get(device, getvar_args, &message)) {
+        return device->WriteFail(message);
+    }
+    return device->WriteOkay(message);
 }
 
 bool EraseHandler(FastbootDevice* device, const std::vector<std::string>& args) {
diff --git a/fastboot/device/fastboot_device.cpp b/fastboot/device/fastboot_device.cpp
index 6ed6d32..55aca9c 100644
--- a/fastboot/device/fastboot_device.cpp
+++ b/fastboot/device/fastboot_device.cpp
@@ -137,3 +137,7 @@
 bool FastbootDevice::WriteFail(const std::string& message) {
     return WriteStatus(FastbootResult::FAIL, message);
 }
+
+bool FastbootDevice::WriteInfo(const std::string& message) {
+    return WriteStatus(FastbootResult::INFO, message);
+}
diff --git a/fastboot/device/fastboot_device.h b/fastboot/device/fastboot_device.h
index addc2ef..171e7ae 100644
--- a/fastboot/device/fastboot_device.h
+++ b/fastboot/device/fastboot_device.h
@@ -39,9 +39,10 @@
     bool HandleData(bool read, std::vector<char>* data);
     std::string GetCurrentSlot();
 
-    // Shortcuts for writing OKAY and FAIL status results.
+    // Shortcuts for writing status results.
     bool WriteOkay(const std::string& message);
     bool WriteFail(const std::string& message);
+    bool WriteInfo(const std::string& message);
 
     std::vector<char>& download_data() { return download_data_; }
     Transport* get_transport() { return transport_.get(); }
diff --git a/fastboot/device/utility.cpp b/fastboot/device/utility.cpp
index ec84576..0157e7f 100644
--- a/fastboot/device/utility.cpp
+++ b/fastboot/device/utility.cpp
@@ -16,6 +16,11 @@
 
 #include "utility.h"
 
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
 #include <android-base/logging.h>
 #include <fs_mgr_dm_linear.h>
 #include <liblp/liblp.h>
@@ -123,3 +128,33 @@
     *number = slot[0] - 'a';
     return true;
 }
+
+std::vector<std::string> ListPartitions(FastbootDevice* device) {
+    std::vector<std::string> partitions;
+
+    // First get physical partitions.
+    struct dirent* de;
+    std::unique_ptr<DIR, decltype(&closedir)> by_name(opendir("/dev/block/by-name"), closedir);
+    while ((de = readdir(by_name.get())) != nullptr) {
+        if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
+            continue;
+        }
+        struct stat s;
+        std::string path = "/dev/block/by-name/" + std::string(de->d_name);
+        if (!stat(path.c_str(), &s) && S_ISBLK(s.st_mode)) {
+            partitions.emplace_back(de->d_name);
+        }
+    }
+
+    // Next get logical partitions.
+    if (auto path = FindPhysicalPartition(LP_METADATA_PARTITION_NAME)) {
+        uint32_t slot_number = SlotNumberForSlotSuffix(device->GetCurrentSlot());
+        if (auto metadata = ReadMetadata(path->c_str(), slot_number)) {
+            for (const auto& partition : metadata->partitions) {
+                std::string partition_name = GetPartitionName(partition);
+                partitions.emplace_back(partition_name);
+            }
+        }
+    }
+    return partitions;
+}
diff --git a/fastboot/device/utility.h b/fastboot/device/utility.h
index 0931fc3..4f0d079 100644
--- a/fastboot/device/utility.h
+++ b/fastboot/device/utility.h
@@ -56,5 +56,5 @@
 bool LogicalPartitionExists(const std::string& name, const std::string& slot_suffix,
                             bool* is_zero_length = nullptr);
 bool OpenPartition(FastbootDevice* device, const std::string& name, PartitionHandle* handle);
-
 bool GetSlotNumber(const std::string& slot, android::hardware::boot::V1_0::Slot* number);
+std::vector<std::string> ListPartitions(FastbootDevice* device);
diff --git a/fastboot/device/variables.cpp b/fastboot/device/variables.cpp
index 65cfea3..91e844a 100644
--- a/fastboot/device/variables.cpp
+++ b/fastboot/device/variables.cpp
@@ -35,141 +35,224 @@
 constexpr int kMaxDownloadSizeDefault = 0x20000000;
 constexpr char kFastbootProtocolVersion[] = "0.4";
 
-bool GetVersion(FastbootDevice* device, const std::vector<std::string>& /* args */) {
-    return device->WriteOkay(kFastbootProtocolVersion);
+bool GetVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+                std::string* message) {
+    *message = kFastbootProtocolVersion;
+    return true;
 }
 
-bool GetBootloaderVersion(FastbootDevice* device, const std::vector<std::string>& /* args */) {
-    return device->WriteOkay(android::base::GetProperty("ro.bootloader", ""));
+bool GetBootloaderVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+                          std::string* message) {
+    *message = android::base::GetProperty("ro.bootloader", "");
+    return true;
 }
 
-bool GetBasebandVersion(FastbootDevice* device, const std::vector<std::string>& /* args */) {
-    return device->WriteOkay(android::base::GetProperty("ro.build.expect.baseband", ""));
+bool GetBasebandVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+                        std::string* message) {
+    *message = android::base::GetProperty("ro.build.expect.baseband", "");
+    return true;
 }
 
-bool GetProduct(FastbootDevice* device, const std::vector<std::string>& /* args */) {
-    return device->WriteOkay(android::base::GetProperty("ro.product.device", ""));
+bool GetProduct(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+                std::string* message) {
+    *message = android::base::GetProperty("ro.product.device", "");
+    return true;
 }
 
-bool GetSerial(FastbootDevice* device, const std::vector<std::string>& /* args */) {
-    return device->WriteOkay(android::base::GetProperty("ro.serialno", ""));
+bool GetSerial(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+               std::string* message) {
+    *message = android::base::GetProperty("ro.serialno", "");
+    return true;
 }
 
-bool GetSecure(FastbootDevice* device, const std::vector<std::string>& /* args */) {
-    return device->WriteOkay(android::base::GetBoolProperty("ro.secure", "") ? "yes" : "no");
+bool GetSecure(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+               std::string* message) {
+    *message = android::base::GetBoolProperty("ro.secure", "") ? "yes" : "no";
+    return true;
 }
 
-bool GetCurrentSlot(FastbootDevice* device, const std::vector<std::string>& /* args */) {
+bool GetCurrentSlot(FastbootDevice* device, const std::vector<std::string>& /* args */,
+                    std::string* message) {
     std::string suffix = device->GetCurrentSlot();
-    std::string slot = suffix.size() == 2 ? suffix.substr(1) : suffix;
-    return device->WriteOkay(slot);
+    *message = suffix.size() == 2 ? suffix.substr(1) : suffix;
+    return true;
 }
 
-bool GetSlotCount(FastbootDevice* device, const std::vector<std::string>& /* args */) {
+bool GetSlotCount(FastbootDevice* device, const std::vector<std::string>& /* args */,
+                  std::string* message) {
     auto boot_control_hal = device->boot_control_hal();
     if (!boot_control_hal) {
-        return "0";
+        *message = "0";
+    } else {
+        *message = std::to_string(boot_control_hal->getNumberSlots());
     }
-    return device->WriteOkay(std::to_string(boot_control_hal->getNumberSlots()));
+    return true;
 }
 
-bool GetSlotSuccessful(FastbootDevice* device, const std::vector<std::string>& args) {
+bool GetSlotSuccessful(FastbootDevice* device, const std::vector<std::string>& args,
+                       std::string* message) {
     if (args.empty()) {
-        return device->WriteFail("Missing argument");
+        *message = "Missing argument";
+        return false;
     }
     Slot slot;
     if (!GetSlotNumber(args[0], &slot)) {
-        return device->WriteFail("Invalid slot");
+        *message = "Invalid slot";
+        return false;
     }
     auto boot_control_hal = device->boot_control_hal();
     if (!boot_control_hal) {
-        return device->WriteFail("Device has no slots");
+        *message = "Device has no slots";
+        return false;
     }
     if (boot_control_hal->isSlotMarkedSuccessful(slot) != BoolResult::TRUE) {
-        return device->WriteOkay("no");
+        *message = "no";
+    } else {
+        *message = "yes";
     }
-    return device->WriteOkay("yes");
+    return true;
 }
 
-bool GetSlotUnbootable(FastbootDevice* device, const std::vector<std::string>& args) {
+bool GetSlotUnbootable(FastbootDevice* device, const std::vector<std::string>& args,
+                       std::string* message) {
     if (args.empty()) {
-        return device->WriteFail("Missing argument");
+        *message = "Missing argument";
+        return false;
     }
     Slot slot;
     if (!GetSlotNumber(args[0], &slot)) {
-        return device->WriteFail("Invalid slot");
+        *message = "Invalid slot";
+        return false;
     }
     auto boot_control_hal = device->boot_control_hal();
     if (!boot_control_hal) {
-        return device->WriteFail("Device has no slots");
+        *message = "Device has no slots";
+        return false;
     }
     if (boot_control_hal->isSlotBootable(slot) != BoolResult::TRUE) {
-        return device->WriteOkay("yes");
+        *message = "yes";
+    } else {
+        *message = "no";
     }
-    return device->WriteOkay("no");
+    return true;
 }
 
-bool GetMaxDownloadSize(FastbootDevice* device, const std::vector<std::string>& /* args */) {
-    return device->WriteOkay(std::to_string(kMaxDownloadSizeDefault));
+bool GetMaxDownloadSize(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+                        std::string* message) {
+    *message = std::to_string(kMaxDownloadSizeDefault);
+    return true;
 }
 
-bool GetUnlocked(FastbootDevice* device, const std::vector<std::string>& /* args */) {
-    return device->WriteOkay("yes");
+bool GetUnlocked(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+                 std::string* message) {
+    *message = "yes";
+    return true;
 }
 
-bool GetHasSlot(FastbootDevice* device, const std::vector<std::string>& args) {
+bool GetHasSlot(FastbootDevice* device, const std::vector<std::string>& args,
+                std::string* message) {
     if (args.empty()) {
-        return device->WriteFail("Missing argument");
+        *message = "Missing argument";
+        return false;
     }
     std::string slot_suffix = device->GetCurrentSlot();
     if (slot_suffix.empty()) {
-        return device->WriteOkay("no");
+        *message = "no";
+        return true;
     }
     std::string partition_name = args[0] + slot_suffix;
     if (FindPhysicalPartition(partition_name) ||
         LogicalPartitionExists(partition_name, slot_suffix)) {
-        return device->WriteOkay("yes");
+        *message = "yes";
+    } else {
+        *message = "no";
     }
-    return device->WriteOkay("no");
+    return true;
 }
 
-bool GetPartitionSize(FastbootDevice* device, const std::vector<std::string>& args) {
+bool GetPartitionSize(FastbootDevice* device, const std::vector<std::string>& args,
+                      std::string* message) {
     if (args.size() < 1) {
-        return device->WriteFail("Missing argument");
+        *message = "Missing argument";
+        return false;
     }
     // Zero-length partitions cannot be created through device-mapper, so we
     // special case them here.
     bool is_zero_length;
     if (LogicalPartitionExists(args[0], device->GetCurrentSlot(), &is_zero_length) &&
         is_zero_length) {
-        return device->WriteOkay("0");
+        *message = "0";
+        return true;
     }
     // Otherwise, open the partition as normal.
     PartitionHandle handle;
     if (!OpenPartition(device, args[0], &handle)) {
-        return device->WriteFail("Could not open partition");
+        *message = "Could not open partition";
+        return false;
     }
     uint64_t size = get_block_device_size(handle.fd());
-    return device->WriteOkay(android::base::StringPrintf("%" PRIX64, size));
+    *message = android::base::StringPrintf("0x%" PRIX64, size);
+    return true;
 }
 
-bool GetPartitionIsLogical(FastbootDevice* device, const std::vector<std::string>& args) {
+bool GetPartitionIsLogical(FastbootDevice* device, const std::vector<std::string>& args,
+                           std::string* message) {
     if (args.size() < 1) {
-        return device->WriteFail("Missing argument");
+        *message = "Missing argument";
+        return false;
     }
     // Note: if a partition name is in both the GPT and the super partition, we
     // return "true", to be consistent with prefering to flash logical partitions
     // over physical ones.
     std::string partition_name = args[0];
     if (LogicalPartitionExists(partition_name, device->GetCurrentSlot())) {
-        return device->WriteOkay("yes");
+        *message = "yes";
+        return true;
     }
     if (FindPhysicalPartition(partition_name)) {
-        return device->WriteOkay("no");
+        *message = "no";
+        return true;
     }
-    return device->WriteFail("Partition not found");
+    *message = "Partition not found";
+    return false;
 }
 
-bool GetIsUserspace(FastbootDevice* device, const std::vector<std::string>& /* args */) {
-    return device->WriteOkay("yes");
+bool GetIsUserspace(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+                    std::string* message) {
+    *message = "yes";
+    return true;
+}
+
+std::vector<std::vector<std::string>> GetAllPartitionArgsWithSlot(FastbootDevice* device) {
+    std::vector<std::vector<std::string>> args;
+    auto partitions = ListPartitions(device);
+    for (const auto& partition : partitions) {
+        args.emplace_back(std::initializer_list<std::string>{partition});
+    }
+    return args;
+}
+
+std::vector<std::vector<std::string>> GetAllPartitionArgsNoSlot(FastbootDevice* device) {
+    auto partitions = ListPartitions(device);
+
+    std::string slot_suffix = device->GetCurrentSlot();
+    if (!slot_suffix.empty()) {
+        auto names = std::move(partitions);
+        for (const auto& name : names) {
+            std::string slotless_name = name;
+            if (android::base::EndsWith(name, "_a") || android::base::EndsWith(name, "_b")) {
+                slotless_name = name.substr(0, name.rfind("_"));
+            }
+            if (std::find(partitions.begin(), partitions.end(), slotless_name) ==
+                partitions.end()) {
+                partitions.emplace_back(slotless_name);
+            }
+        }
+    }
+
+    std::vector<std::vector<std::string>> args;
+    for (const auto& partition : partitions) {
+        args.emplace_back(std::initializer_list<std::string>{partition});
+    }
+    return args;
 }
diff --git a/fastboot/device/variables.h b/fastboot/device/variables.h
index 554a080..c3a64cf 100644
--- a/fastboot/device/variables.h
+++ b/fastboot/device/variables.h
@@ -21,19 +21,34 @@
 
 class FastbootDevice;
 
-bool GetVersion(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetBootloaderVersion(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetBasebandVersion(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetProduct(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetSerial(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetSecure(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetCurrentSlot(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetSlotCount(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetSlotSuccessful(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetSlotUnbootable(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetMaxDownloadSize(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetUnlocked(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetHasSlot(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetPartitionSize(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetPartitionIsLogical(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetIsUserspace(FastbootDevice* device, const std::vector<std::string>& args);
+bool GetVersion(FastbootDevice* device, const std::vector<std::string>& args, std::string* message);
+bool GetBootloaderVersion(FastbootDevice* device, const std::vector<std::string>& args,
+                          std::string* message);
+bool GetBasebandVersion(FastbootDevice* device, const std::vector<std::string>& args,
+                        std::string* message);
+bool GetProduct(FastbootDevice* device, const std::vector<std::string>& args, std::string* message);
+bool GetSerial(FastbootDevice* device, const std::vector<std::string>& args, std::string* message);
+bool GetSecure(FastbootDevice* device, const std::vector<std::string>& args, std::string* message);
+bool GetCurrentSlot(FastbootDevice* device, const std::vector<std::string>& args,
+                    std::string* message);
+bool GetSlotCount(FastbootDevice* device, const std::vector<std::string>& args,
+                  std::string* message);
+bool GetSlotSuccessful(FastbootDevice* device, const std::vector<std::string>& args,
+                       std::string* message);
+bool GetSlotUnbootable(FastbootDevice* device, const std::vector<std::string>& args,
+                       std::string* message);
+bool GetMaxDownloadSize(FastbootDevice* device, const std::vector<std::string>& args,
+                        std::string* message);
+bool GetUnlocked(FastbootDevice* device, const std::vector<std::string>& args,
+                 std::string* message);
+bool GetHasSlot(FastbootDevice* device, const std::vector<std::string>& args, std::string* message);
+bool GetPartitionSize(FastbootDevice* device, const std::vector<std::string>& args,
+                      std::string* message);
+bool GetPartitionIsLogical(FastbootDevice* device, const std::vector<std::string>& args,
+                           std::string* message);
+bool GetIsUserspace(FastbootDevice* device, const std::vector<std::string>& args,
+                    std::string* message);
+
+// Helpers for getvar all.
+std::vector<std::vector<std::string>> GetAllPartitionArgsWithSlot(FastbootDevice* device);
+std::vector<std::vector<std::string>> GetAllPartitionArgsNoSlot(FastbootDevice* device);
diff --git a/fastboot/engine.cpp b/fastboot/engine.cpp
index 6a52b12..d80e986 100644
--- a/fastboot/engine.cpp
+++ b/fastboot/engine.cpp
@@ -88,7 +88,9 @@
 }
 
 void fb_reinit(Transport* transport) {
-    fb->set_transport(transport);
+    if (Transport* old_transport = fb->set_transport(transport)) {
+        delete old_transport;
+    }
 }
 
 const std::string fb_get_error() {
@@ -392,6 +394,6 @@
     }
     fprintf(stderr, "OKAY\n");
 
-    fb->set_transport(nullptr);
+    fb_reinit(nullptr);
     return true;
 }
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 293ff00..1aef567 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -55,6 +55,8 @@
 #include <android-base/strings.h>
 #include <android-base/test_utils.h>
 #include <android-base/unique_fd.h>
+#include <build/version.h>
+#include <platform_tools_version.h>
 #include <sparse/sparse.h>
 #include <ziparchive/zip_archive.h>
 
@@ -1548,7 +1550,7 @@
                 setvbuf(stdout, nullptr, _IONBF, 0);
                 setvbuf(stderr, nullptr, _IONBF, 0);
             } else if (name == "version") {
-                fprintf(stdout, "fastboot version %s\n", FASTBOOT_VERSION);
+                fprintf(stdout, "fastboot version %s-%s\n", PLATFORM_TOOLS_VERSION, android::build::GetBuildNumber().c_str());
                 fprintf(stdout, "Installed as %s\n", android::base::GetExecutablePath().c_str());
                 return 0;
 #if !defined(_WIN32)
@@ -1845,6 +1847,10 @@
 
     int status = fb_execute_queue() ? EXIT_FAILURE : EXIT_SUCCESS;
     fprintf(stderr, "Finished. Total time: %.3fs\n", (now() - start));
+
+    if (Transport* old_transport = fb.set_transport(nullptr)) {
+        delete old_transport;
+    }
     return status;
 }
 
diff --git a/fastboot/fastboot_driver.cpp b/fastboot/fastboot_driver.cpp
index ceee066..f9e640a 100644
--- a/fastboot/fastboot_driver.cpp
+++ b/fastboot/fastboot_driver.cpp
@@ -58,7 +58,6 @@
 }
 
 FastBootDriver::~FastBootDriver() {
-    set_transport(nullptr);
 }
 
 RetCode FastBootDriver::Boot(std::string* response, std::vector<std::string>* info) {
@@ -127,7 +126,7 @@
     return RawCommand(Commands::FLASH + part);
 }
 
-RetCode FastBootDriver::Partitions(std::vector<std::tuple<std::string, uint32_t>>* parts) {
+RetCode FastBootDriver::Partitions(std::vector<std::tuple<std::string, uint64_t>>* parts) {
     std::vector<std::string> all;
     RetCode ret;
     if ((ret = GetVarAll(&all))) {
@@ -141,7 +140,7 @@
         if (std::regex_match(s, sm, reg)) {
             std::string m1(sm[1]);
             std::string m2(sm[2]);
-            uint32_t tmp = strtol(m2.c_str(), 0, 16);
+            uint64_t tmp = strtoll(m2.c_str(), 0, 16);
             parts->push_back(std::make_tuple(m1, tmp));
         }
     }
@@ -537,12 +536,9 @@
     return 0;
 }
 
-void FastBootDriver::set_transport(Transport* transport) {
-    if (transport_) {
-        transport_->Close();
-        delete transport_;
-    }
-    transport_ = transport;
+Transport* FastBootDriver::set_transport(Transport* transport) {
+    std::swap(transport_, transport);
+    return transport;
 }
 
 }  // End namespace fastboot
diff --git a/fastboot/fastboot_driver.h b/fastboot/fastboot_driver.h
index 4647945..ca9003a 100644
--- a/fastboot/fastboot_driver.h
+++ b/fastboot/fastboot_driver.h
@@ -99,7 +99,7 @@
     RetCode FlashPartition(const std::string& part, int fd, uint32_t sz);
     RetCode FlashPartition(const std::string& part, sparse_file* s);
 
-    RetCode Partitions(std::vector<std::tuple<std::string, uint32_t>>* parts);
+    RetCode Partitions(std::vector<std::tuple<std::string, uint64_t>>* parts);
     RetCode Require(const std::string& var, const std::vector<std::string>& allowed, bool* reqmet,
                     bool invert = false);
 
@@ -109,8 +109,8 @@
     std::string Error();
     RetCode WaitForDisconnect();
 
-    // Note: changing the transport will close and delete the existing one.
-    void set_transport(Transport* transport);
+    // Note: set_transport will return the previous transport.
+    Transport* set_transport(Transport* transport);
     Transport* transport() const { return transport_; }
 
     // This is temporarily public for engine.cpp
diff --git a/fastboot/fuzzy_fastboot/fixtures.cpp b/fastboot/fuzzy_fastboot/fixtures.cpp
index 0a87598..4da71ca 100644
--- a/fastboot/fuzzy_fastboot/fixtures.cpp
+++ b/fastboot/fuzzy_fastboot/fixtures.cpp
@@ -133,7 +133,6 @@
     fb.reset();
 
     if (transport) {
-        transport->Close();
         transport.reset();
     }
 
@@ -188,7 +187,6 @@
         ASSERT_EQ(fb->RawCommand("flashing " + cmd, &resp), SUCCESS)
                 << "Attempting to change locked state, but 'flashing" + cmd + "' command failed";
         fb.reset();
-        transport->Close();
         transport.reset();
         printf("PLEASE RESPOND TO PROMPT FOR '%sing' BOOTLOADER ON DEVICE\n", cmd.c_str());
         while (UsbStillAvailible())
@@ -249,7 +247,6 @@
     }
 
     if (transport) {
-        transport->Close();
         transport.reset();
     }
 
diff --git a/fastboot/fuzzy_fastboot/main.cpp b/fastboot/fuzzy_fastboot/main.cpp
index 1d30f8b..dd64082 100644
--- a/fastboot/fuzzy_fastboot/main.cpp
+++ b/fastboot/fuzzy_fastboot/main.cpp
@@ -304,13 +304,13 @@
 }
 
 TEST_F(Conformance, PartitionInfo) {
-    std::vector<std::tuple<std::string, uint32_t>> parts;
+    std::vector<std::tuple<std::string, uint64_t>> parts;
     EXPECT_EQ(fb->Partitions(&parts), SUCCESS) << "getvar:all failed";
     EXPECT_GT(parts.size(), 0)
             << "getvar:all did not report any partition-size: through INFO responses";
     std::set<std::string> allowed{"ext4", "f2fs", "raw"};
     for (const auto p : parts) {
-        EXPECT_GT(std::get<1>(p), 0);
+        EXPECT_GE(std::get<1>(p), 0);
         std::string part(std::get<0>(p));
         std::set<std::string> allowed{"ext4", "f2fs", "raw"};
         std::string resp;
@@ -340,7 +340,7 @@
     // Can't run out of alphabet letters...
     ASSERT_LE(num_slots, 26) << "What?! You can't have more than 26 slots";
 
-    std::vector<std::tuple<std::string, uint32_t>> parts;
+    std::vector<std::tuple<std::string, uint64_t>> parts;
     EXPECT_EQ(fb->Partitions(&parts), SUCCESS) << "getvar:all failed";
 
     std::map<std::string, std::set<char>> part_slots;
@@ -587,14 +587,14 @@
     std::vector<char> buf{'a', 'o', 's', 'p'};
     EXPECT_EQ(fb->Download(buf), SUCCESS) << "Download failed in unlocked mode";
     ;
-    std::vector<std::tuple<std::string, uint32_t>> parts;
+    std::vector<std::tuple<std::string, uint64_t>> parts;
     EXPECT_EQ(fb->Partitions(&parts), SUCCESS) << "getvar:all failed in unlocked mode";
 }
 
 TEST_F(LockPermissions, DownloadFlash) {
     std::vector<char> buf{'a', 'o', 's', 'p'};
     EXPECT_EQ(fb->Download(buf), SUCCESS) << "Download failed in locked mode";
-    std::vector<std::tuple<std::string, uint32_t>> parts;
+    std::vector<std::tuple<std::string, uint64_t>> parts;
     EXPECT_EQ(fb->Partitions(&parts), SUCCESS) << "getvar:all failed in locked mode";
     std::string resp;
     for (const auto tup : parts) {
@@ -607,7 +607,7 @@
 }
 
 TEST_F(LockPermissions, Erase) {
-    std::vector<std::tuple<std::string, uint32_t>> parts;
+    std::vector<std::tuple<std::string, uint64_t>> parts;
     EXPECT_EQ(fb->Partitions(&parts), SUCCESS) << "getvar:all failed";
     std::string resp;
     for (const auto tup : parts) {
@@ -619,7 +619,7 @@
 }
 
 TEST_F(LockPermissions, SetActive) {
-    std::vector<std::tuple<std::string, uint32_t>> parts;
+    std::vector<std::tuple<std::string, uint64_t>> parts;
     EXPECT_EQ(fb->Partitions(&parts), SUCCESS) << "getvar:all failed";
 
     std::string resp;
@@ -916,7 +916,7 @@
 
 TEST_P(AnyPartition, ReportedGetVarAll) {
     // As long as the partition is reported in INFO, it would be tested by generic Conformance
-    std::vector<std::tuple<std::string, uint32_t>> parts;
+    std::vector<std::tuple<std::string, uint64_t>> parts;
     ASSERT_EQ(fb->Partitions(&parts), SUCCESS) << "getvar:all failed";
     const std::string name = GetParam().first;
     if (GetParam().second.slots) {
diff --git a/fastboot/fuzzy_fastboot/usb_transport_sniffer.cpp b/fastboot/fuzzy_fastboot/usb_transport_sniffer.cpp
index ee510e9..7c595f4 100644
--- a/fastboot/fuzzy_fastboot/usb_transport_sniffer.cpp
+++ b/fastboot/fuzzy_fastboot/usb_transport_sniffer.cpp
@@ -12,6 +12,10 @@
                                          const int serial_fd)
     : transport_(std::move(transport)), serial_fd_(serial_fd) {}
 
+UsbTransportSniffer::~UsbTransportSniffer() {
+    Close();
+}
+
 ssize_t UsbTransportSniffer::Read(void* data, size_t len) {
     ProcessSerial();
 
diff --git a/fastboot/fuzzy_fastboot/usb_transport_sniffer.h b/fastboot/fuzzy_fastboot/usb_transport_sniffer.h
index 693f042..89cc009 100644
--- a/fastboot/fuzzy_fastboot/usb_transport_sniffer.h
+++ b/fastboot/fuzzy_fastboot/usb_transport_sniffer.h
@@ -68,6 +68,7 @@
     };
 
     UsbTransportSniffer(std::unique_ptr<UsbTransport> transport, const int serial_fd = 0);
+    ~UsbTransportSniffer() override;
 
     virtual ssize_t Read(void* data, size_t len) override;
     virtual ssize_t Write(const void* data, size_t len) override;
diff --git a/fastboot/usb_linux.cpp b/fastboot/usb_linux.cpp
index 9b779dd..6363aa5 100644
--- a/fastboot/usb_linux.cpp
+++ b/fastboot/usb_linux.cpp
@@ -95,7 +95,7 @@
   public:
     explicit LinuxUsbTransport(std::unique_ptr<usb_handle> handle, uint32_t ms_timeout = 0)
         : handle_(std::move(handle)), ms_timeout_(ms_timeout) {}
-    ~LinuxUsbTransport() override = default;
+    ~LinuxUsbTransport() override;
 
     ssize_t Read(void* data, size_t len) override;
     ssize_t Write(const void* data, size_t len) override;
@@ -387,6 +387,10 @@
     return usb;
 }
 
+LinuxUsbTransport::~LinuxUsbTransport() {
+    Close();
+}
+
 ssize_t LinuxUsbTransport::Write(const void* _data, size_t len)
 {
     unsigned char *data = (unsigned char*) _data;
diff --git a/fastboot/usb_osx.cpp b/fastboot/usb_osx.cpp
index 4d48f6e..ed02c4a 100644
--- a/fastboot/usb_osx.cpp
+++ b/fastboot/usb_osx.cpp
@@ -70,7 +70,7 @@
     // A timeout of 0 is blocking
     OsxUsbTransport(std::unique_ptr<usb_handle> handle, uint32_t ms_timeout = 0)
         : handle_(std::move(handle)), ms_timeout_(ms_timeout) {}
-    ~OsxUsbTransport() override = default;
+    ~OsxUsbTransport() override;
 
     ssize_t Read(void* data, size_t len) override;
     ssize_t Write(const void* data, size_t len) override;
@@ -471,6 +471,10 @@
     return new OsxUsbTransport(std::move(handle), timeout_ms);
 }
 
+OsxUsbTransport::~OsxUsbTransport() {
+    Close();
+}
+
 int OsxUsbTransport::Close() {
     /* TODO: Something better here? */
     return 0;
diff --git a/fastboot/usb_windows.cpp b/fastboot/usb_windows.cpp
index 8c60a71..b00edb3 100644
--- a/fastboot/usb_windows.cpp
+++ b/fastboot/usb_windows.cpp
@@ -69,7 +69,7 @@
 class WindowsUsbTransport : public UsbTransport {
   public:
     WindowsUsbTransport(std::unique_ptr<usb_handle> handle) : handle_(std::move(handle)) {}
-    ~WindowsUsbTransport() override = default;
+    ~WindowsUsbTransport() override;
 
     ssize_t Read(void* data, size_t len) override;
     ssize_t Write(const void* data, size_t len) override;
@@ -250,6 +250,10 @@
     }
 }
 
+WindowsUsbTransport::~WindowsUsbTransport() {
+    Close();
+}
+
 int WindowsUsbTransport::Close() {
     DBG("usb_close\n");
 
diff --git a/fs_mgr/liblp/reader.cpp b/fs_mgr/liblp/reader.cpp
index 117f5d5..190c650 100644
--- a/fs_mgr/liblp/reader.cpp
+++ b/fs_mgr/liblp/reader.cpp
@@ -314,7 +314,7 @@
         return nullptr;
     }
 
-    // Read the priamry copy, and if that fails, try the backup.
+    // Read the primary copy, and if that fails, try the backup.
     std::unique_ptr<LpMetadata> metadata = ReadPrimaryMetadata(fd, geometry, slot_number);
     if (metadata) {
         return metadata;
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index a10e636..c42ae49 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -89,29 +89,20 @@
                 "libbase",
                 "liblog",
                 "libunwindstack",
-                "libdexfile",
             ],
 
             static_libs: [
                 "libprocinfo",
             ],
-
-            // libdexfile will eventually properly export headers, for now
-            // include these directly.
-            include_dirs: [
-                "art/runtime",
-            ],
         },
         android: {
             static_libs: ["libasync_safe"],
         },
         vendor: {
             cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
-            exclude_shared_libs: ["libdexfile"],
         },
         recovery: {
             cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
-            exclude_shared_libs: ["libdexfile"],
         },
     },
     whole_static_libs: ["libdemangle"],
@@ -154,7 +145,6 @@
     shared_libs: [
         "libbacktrace_test",
         "libbacktrace",
-        "libdexfile",
         "libbase",
         "liblog",
         "libunwindstack",
@@ -174,12 +164,6 @@
         },
     },
 
-    // libdexfile will eventually properly export headers, for now
-    // include these directly.
-    include_dirs: [
-        "art/runtime",
-    ],
-
     test_suites: ["device-tests"],
     data: [
         "testdata/arm/*",
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index 2606aa9..fd3f602 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -158,4 +158,5 @@
         "libbase",
         "libziparchive",
     ],
+    recovery_available: true,
 }
diff --git a/llkd/Android.bp b/llkd/Android.bp
index a6edd26..62a637d 100644
--- a/llkd/Android.bp
+++ b/llkd/Android.bp
@@ -20,6 +20,12 @@
     export_include_dirs: ["include"],
 
     cflags: ["-Werror"],
+
+    product_variables: {
+        debuggable: {
+            cppflags: ["-D__PTRACE_ENABLED__"],
+        },
+    },
 }
 
 cc_binary {
@@ -39,4 +45,9 @@
     cflags: ["-Werror"],
 
     init_rc: ["llkd.rc"],
+    product_variables: {
+        debuggable: {
+            init_rc: ["llkd-debuggable.rc"],
+	},
+    },
 }
diff --git a/llkd/README.md b/llkd/README.md
index 2314583..1f69718 100644
--- a/llkd/README.md
+++ b/llkd/README.md
@@ -23,6 +23,9 @@
 Operations
 ----------
 
+There are two detection scenarios. Persistent D or Z state, and persistent
+stack signature.
+
 If a thread is in D or Z state with no forward progress for longer than
 ro.llk.timeout_ms, or ro.llk.[D|Z].timeout_ms, kill the process or parent
 process respectively.  If another scan shows the same process continues to
@@ -32,6 +35,26 @@
 double the expected time to flow through the mainloop.  Sampling is every
 ro.llk_sample_ms.
 
+For usedebug releases only, persistent stack signature checking is enabled.
+If a thread in any state but Z, has a persistent listed ro.llk.stack kernel
+symbol always being reported, even if there is forward scheduling progress, for
+longer than ro.llk.timeout_ms, or ro.llk.stack.timeout_ms, then issue a kill
+to the process.  If another scan shows the same process continues to exist,
+then have a confirmed live-lock condition and need to panic.  There is no
+ABA detection since forward scheduling progress is allowed, thus the condition
+for the symbols are:
+
+- Check is looking for " " + __symbol__+ "0x" in /proc/<pid>/stack.
+- The __symbol__ should be rare and short lived enough that on a typical
+  system the function is seen at most only once in a sample over the timeout
+  period of ro.llk.stack.timeout_ms, samples occur every ro.llk.check_ms. This
+  can be the only way to prevent a false trigger as there is no ABA protection.
+- Persistent continuously when the live lock condition exists.
+- Should be just below the function that is calling the lock that could
+  contend, because if the lock is below or in the symbol function, the
+  symbol will show in all affected processes, not just the one that
+  caused the lockup.
+
 Default will not monitor init, or [kthreadd] and all that [kthreadd] spawns.
 This reduces the effectiveness of llkd by limiting its coverage.  If there is
 value in covering [kthreadd] spawned threads, the requirement will be that
@@ -40,7 +63,9 @@
 coding hygiene, a common request to add such to publicly reviewed kernel.org
 maintained drivers).  For instance use wait_event_interruptible() instead of
 wait_event().  The blacklists can be adjusted accordingly if these
-conditions are met to cover kernel components.
+conditions are met to cover kernel components.  For the stack symbol checking,
+there is an additional process blacklist so that we do not incide sepolicy
+violations on services that block ptrace operations.
 
 An accompanying gTest set have been added, and will setup a persistent D or Z
 process, with and without forward progress, but not in a live-lock state
@@ -93,14 +118,31 @@
 #### ro.llk.Z.timeout_ms
 default ro.llk.timeout_ms, Z maximum timelimit.
 
+#### ro.llk.stack.timeout_ms
+default ro.llk.timeout_ms,
+checking for persistent stack symbols maximum timelimit.
+Only active on userdebug and eng builds.
+
 #### ro.llk.check_ms
 default 2 minutes samples of threads for D or Z.
 
+#### ro.llk.stack
+default *empty* or false, comma separated list of kernel symbols.
+The string "*false*" is the equivalent to an *empty* list.
+Look for kernel stack symbols that if ever persistently present can
+indicate a subsystem is locked up.
+Beware, check does not on purpose do forward scheduling ABA except by polling
+every ro.llk_check_ms over the period ro.llk.stack.timeout_ms, so stack symbol
+should be exceptionally rare and fleeting.
+One must be convinced that it is virtually *impossible* for symbol to show up
+persistently in all samples of the stack.
+Only active on userdebug and eng builds.
+
 #### ro.llk.blacklist.process
 default 0,1,2 (kernel, init and [kthreadd]) plus process names
 init,[kthreadd],[khungtaskd],lmkd,lmkd.llkd,llkd,watchdogd,
 [watchdogd],[watchdogd/0],...,[watchdogd/***get_nprocs**-1*].
-The string false is the equivalent to an empty list.
+The string "*false*" is the equivalent to an *empty* list.
 Do not watch these processes.  A process can be comm, cmdline or pid reference.
 NB: automated default here can be larger than the current maximum property
 size of 92.
@@ -108,15 +150,23 @@
 
 #### ro.llk.blacklist.parent
 default 0,2 (kernel and [kthreadd]).
-The string false is the equivalent to an empty list.
+The string "*false*" is the equivalent to an *empty* list.
 Do not watch processes that have this parent.
 A parent process can be comm, cmdline or pid reference.
 
 #### ro.llk.blacklist.uid
 default *empty* or false, comma separated list of uid numbers or names.
-The string false is the equivalent to an empty list.
+The string "*false*" is the equivalent to an *empty* list.
 Do not watch processes that match this uid.
 
+#### ro.llk.blacklist.process.stack
+default process names init,lmkd,lmkd.llkd,llkd,keystore,logd.
+The string "*false*" is the equivalent to an *empty* list.
+This subset of processes are not monitored for live lock stack signatures.
+Also prevents the sepolicy violation associated with processes that block
+ptrace, as these can not be checked anyways.
+Only active on userdebug and eng builds.
+
 Architectural Concerns
 ----------------------
 
diff --git a/llkd/include/llkd.h b/llkd/include/llkd.h
index e3ae4bb..d0188ec 100644
--- a/llkd/include/llkd.h
+++ b/llkd/include/llkd.h
@@ -43,9 +43,12 @@
 #define KHT_TIMEOUT_PROPERTY           "ro.khungtask.timeout"
 #define LLK_D_TIMEOUT_MS_PROPERTY      "ro.llk.D.timeout_ms"
 #define LLK_Z_TIMEOUT_MS_PROPERTY      "ro.llk.Z.timeout_ms"
+#define LLK_STACK_TIMEOUT_MS_PROPERTY  "ro.llk.stack.timeout_ms"
 #define LLK_CHECK_MS_PROPERTY          "ro.llk.check_ms"
 /* LLK_CHECK_MS_DEFAULT = actual timeout_ms / LLK_CHECKS_PER_TIMEOUT_DEFAULT */
 #define LLK_CHECKS_PER_TIMEOUT_DEFAULT 5
+#define LLK_CHECK_STACK_PROPERTY       "ro.llk.stack"
+#define LLK_CHECK_STACK_DEFAULT        ""
 #define LLK_BLACKLIST_PROCESS_PROPERTY "ro.llk.blacklist.process"
 #define LLK_BLACKLIST_PROCESS_DEFAULT  \
     "0,1,2,init,[kthreadd],[khungtaskd],lmkd,lmkd.llkd,llkd,watchdogd,[watchdogd],[watchdogd/0]"
@@ -53,6 +56,8 @@
 #define LLK_BLACKLIST_PARENT_DEFAULT   "0,2,[kthreadd]"
 #define LLK_BLACKLIST_UID_PROPERTY     "ro.llk.blacklist.uid"
 #define LLK_BLACKLIST_UID_DEFAULT      ""
+#define LLK_BLACKLIST_STACK_PROPERTY   "ro.llk.blacklist.process.stack"
+#define LLK_BLACKLIST_STACK_DEFAULT    "init,lmkd.llkd,llkd,keystore,/system/bin/keystore"
 /* clang-format on */
 
 __END_DECLS
diff --git a/llkd/libllkd.cpp b/llkd/libllkd.cpp
index bb55d1f..58c2ba8 100644
--- a/llkd/libllkd.cpp
+++ b/llkd/libllkd.cpp
@@ -73,7 +73,14 @@
 bool llkMlockall = LLK_MLOCKALL_DEFAULT;             // run mlocked
 bool llkTestWithKill = LLK_KILLTEST_DEFAULT;         // issue test kills
 milliseconds llkTimeoutMs = LLK_TIMEOUT_MS_DEFAULT;  // default timeout
-enum { llkStateD, llkStateZ, llkNumStates };         // state indexes
+enum {                                               // enum of state indexes
+    llkStateD,                                       // Persistent 'D' state
+    llkStateZ,                                       // Persistent 'Z' state
+#ifdef __PTRACE_ENABLED__                            // Extra privileged states
+    llkStateStack,                                   // stack signature
+#endif                                               // End of extra privilege
+    llkNumStates,                                    // Maxumum number of states
+};                                                   // state indexes
 milliseconds llkStateTimeoutMs[llkNumStates];        // timeout override for each detection state
 milliseconds llkCheckMs;                             // checking interval to inspect any
                                                      // persistent live-locked states
@@ -83,6 +90,10 @@
 // Provides a wide angle of margin b/c khtTimeout is also its granularity.
 seconds khtTimeout = duration_cast<seconds>(llkTimeoutMs * (1 + LLK_CHECKS_PER_TIMEOUT_DEFAULT) /
                                             LLK_CHECKS_PER_TIMEOUT_DEFAULT);
+#ifdef __PTRACE_ENABLED__
+// list of stack symbols to search for persistence.
+std::unordered_set<std::string> llkCheckStackSymbols;
+#endif
 
 // Blacklist variables, initialized with comma separated lists of high false
 // positive and/or dangerous references, e.g. without self restart, for pid,
@@ -97,6 +108,11 @@
 std::unordered_set<std::string> llkBlacklistParent;
 // list of uids, and uid names, to skip, default nothing
 std::unordered_set<std::string> llkBlacklistUid;
+#ifdef __PTRACE_ENABLED__
+// list of names to skip stack checking. "init", "lmkd", "llkd", "keystore" or
+// "logd" (if not userdebug).
+std::unordered_set<std::string> llkBlacklistStack;
+#endif
 
 class dir {
   public:
@@ -263,6 +279,9 @@
                                    // forward scheduling progress.
     milliseconds update;           // llkUpdate millisecond signature of last.
     milliseconds count;            // duration in state.
+#ifdef __PTRACE_ENABLED__          // Privileged state checking
+    milliseconds count_stack;      // duration where stack is stagnant.
+#endif                             // End privilege
     pid_t pid;                     // /proc/<pid> before iterating through
                                    // /proc/<pid>/task/<tid> for threads.
     pid_t ppid;                    // /proc/<tid>/stat field 4 parent pid.
@@ -272,6 +291,9 @@
     std::string cmdline;           // cached /cmdline content
     char state;                    // /proc/<tid>/stat field 3: Z or D
                                    // (others we do not monitor: S, R, T or ?)
+#ifdef __PTRACE_ENABLED__          // Privileged state checking
+    char stack;                    // index in llkCheckStackSymbols for matches
+#endif                             // and with maximum index PROP_VALUE_MAX/2.
     char comm[TASK_COMM_LEN + 3];  // space for adding '[' and ']'
     bool exeMissingValid;          // exeMissing has been cached
     bool cmdlineValid;             // cmdline has been cached
@@ -286,11 +308,17 @@
           nrSwitches(0),
           update(llkUpdate),
           count(0ms),
+#ifdef __PTRACE_ENABLED__
+          count_stack(0ms),
+#endif
           pid(pid),
           ppid(ppid),
           uid(-1),
           time(time),
           state(state),
+#ifdef __PTRACE_ENABLED__
+          stack(-1),
+#endif
           exeMissingValid(false),
           cmdlineValid(false),
           updated(true),
@@ -343,6 +371,10 @@
     void reset(void) {  // reset cache, if we detected pid rollover
         uid = -1;
         state = '?';
+#ifdef __PTRACE_ENABLED__
+        count_stack = 0ms;
+        stack = -1;
+#endif
         cmdline = "";
         comm[0] = '\0';
         exeMissingValid = false;
@@ -667,6 +699,48 @@
     return ret;
 }
 
+#ifdef __PTRACE_ENABLED__
+bool llkCheckStack(proc* procp, const std::string& piddir) {
+    if (llkCheckStackSymbols.empty()) return false;
+    if (procp->state == 'Z') {  // No brains for Zombies
+        procp->stack = -1;
+        procp->count_stack = 0ms;
+        return false;
+    }
+
+    // Don't check process that are known to block ptrace, save sepolicy noise.
+    if (llkSkipName(std::to_string(procp->pid), llkBlacklistStack)) return false;
+    if (llkSkipName(procp->getComm(), llkBlacklistStack)) return false;
+    if (llkSkipName(procp->getCmdline(), llkBlacklistStack)) return false;
+
+    auto kernel_stack = ReadFile(piddir + "/stack");
+    if (kernel_stack.empty()) {
+        LOG(INFO) << piddir << "/stack empty comm=" << procp->getComm()
+                  << " cmdline=" << procp->getCmdline();
+        return false;
+    }
+    // A scheduling incident that should not reset count_stack
+    if (kernel_stack.find(" cpu_worker_pools+0x") != std::string::npos) return false;
+    char idx = -1;
+    char match = -1;
+    for (const auto& stack : llkCheckStackSymbols) {
+        if (++idx < 0) break;
+        if (kernel_stack.find(" "s + stack + "+0x") != std::string::npos) {
+            match = idx;
+            break;
+        }
+    }
+    if (procp->stack != match) {
+        procp->stack = match;
+        procp->count_stack = 0ms;
+        return false;
+    }
+    if (match == char(-1)) return false;
+    procp->count_stack += llkCycle;
+    return procp->count_stack >= llkStateTimeoutMs[llkStateStack];
+}
+#endif
+
 // Primary ABA mitigation watching last time schedule activity happened
 void llkCheckSchedUpdate(proc* procp, const std::string& piddir) {
     // Audit finds /proc/<tid>/sched is just over 1K, and
@@ -731,7 +805,15 @@
               << LLK_TIMEOUT_MS_PROPERTY "=" << llkFormat(llkTimeoutMs) << "\n"
               << LLK_D_TIMEOUT_MS_PROPERTY "=" << llkFormat(llkStateTimeoutMs[llkStateD]) << "\n"
               << LLK_Z_TIMEOUT_MS_PROPERTY "=" << llkFormat(llkStateTimeoutMs[llkStateZ]) << "\n"
+#ifdef __PTRACE_ENABLED__
+              << LLK_STACK_TIMEOUT_MS_PROPERTY "=" << llkFormat(llkStateTimeoutMs[llkStateStack])
+              << "\n"
+#endif
               << LLK_CHECK_MS_PROPERTY "=" << llkFormat(llkCheckMs) << "\n"
+#ifdef __PTRACE_ENABLED__
+              << LLK_CHECK_STACK_PROPERTY "=" << llkFormat(llkCheckStackSymbols) << "\n"
+              << LLK_BLACKLIST_STACK_PROPERTY "=" << llkFormat(llkBlacklistStack) << "\n"
+#endif
               << LLK_BLACKLIST_PROCESS_PROPERTY "=" << llkFormat(llkBlacklistProcess) << "\n"
               << LLK_BLACKLIST_PARENT_PROPERTY "=" << llkFormat(llkBlacklistParent) << "\n"
               << LLK_BLACKLIST_UID_PROPERTY "=" << llkFormat(llkBlacklistUid);
@@ -892,9 +974,14 @@
             if (pid == myPid) {
                 break;
             }
-            if (!llkIsMonitorState(state)) {
+#ifdef __PTRACE_ENABLED__
+            // if no stack monitoring, we can quickly exit here
+            if (!llkIsMonitorState(state) && llkCheckStackSymbols.empty()) {
                 continue;
             }
+#else
+            if (!llkIsMonitorState(state)) continue;
+#endif
             if ((tid == myTid) || llkSkipPid(tid)) {
                 continue;
             }
@@ -925,12 +1012,26 @@
             // ABA mitigation watching last time schedule activity happened
             llkCheckSchedUpdate(procp, piddir);
 
-            // Can only fall through to here if registered D or Z state !!!
-            if (procp->count < llkStateTimeoutMs[(state == 'Z') ? llkStateZ : llkStateD]) {
-                LOG(VERBOSE) << state << ' ' << llkFormat(procp->count) << ' ' << ppid << "->"
-                             << pid << "->" << tid << ' ' << procp->getComm();
+#ifdef __PTRACE_ENABLED__
+            auto stuck = llkCheckStack(procp, piddir);
+            if (llkIsMonitorState(state)) {
+                if (procp->count >= llkStateTimeoutMs[(state == 'Z') ? llkStateZ : llkStateD]) {
+                    stuck = true;
+                } else if (procp->count != 0ms) {
+                    LOG(VERBOSE) << state << ' ' << llkFormat(procp->count) << ' ' << ppid << "->"
+                                 << pid << "->" << tid << ' ' << procp->getComm();
+                }
+            }
+            if (!stuck) continue;
+#else
+            if (procp->count >= llkStateTimeoutMs[(state == 'Z') ? llkStateZ : llkStateD]) {
+                if (procp->count != 0ms) {
+                    LOG(VERBOSE) << state << ' ' << llkFormat(procp->count) << ' ' << ppid << "->"
+                                 << pid << "->" << tid << ' ' << procp->getComm();
+                }
                 continue;
             }
+#endif
 
             // We have to kill it to determine difference between live lock
             // and persistent state blocked on a resource.  Is there something
@@ -969,12 +1070,13 @@
                         // not working is we kill a process that likes to
                         // stay in 'D' state, instead of panicing the
                         // kernel (worse).
-                        LOG(WARNING) << "D " << llkFormat(procp->count) << ' ' << pid << "->" << tid
-                                     << ' ' << procp->getComm() << " [kill]";
+                    default:
+                        LOG(WARNING) << state << ' ' << llkFormat(procp->count) << ' ' << pid
+                                     << "->" << tid << ' ' << procp->getComm() << " [kill]";
                         if ((llkKillOneProcess(llkTidLookup(pid), procp) >= 0) ||
-                            (llkKillOneProcess(pid, 'D', tid) >= 0) ||
+                            (llkKillOneProcess(pid, state, tid) >= 0) ||
                             (llkKillOneProcess(procp, procp) >= 0) ||
-                            (llkKillOneProcess(tid, 'D', tid) >= 0)) {
+                            (llkKillOneProcess(tid, state, tid) >= 0)) {
                             continue;
                         }
                         break;
@@ -983,7 +1085,8 @@
             // We are here because we have confirmed kernel live-lock
             LOG(ERROR) << state << ' ' << llkFormat(procp->count) << ' ' << ppid << "->" << pid
                        << "->" << tid << ' ' << procp->getComm() << " [panic]";
-            llkPanicKernel(true, tid, (state == 'Z') ? "zombie" : "driver");
+            llkPanicKernel(true, tid,
+                           (state == 'Z') ? "zombie" : (state == 'D') ? "driver" : "sleeping");
         }
         LOG(VERBOSE) << "+closedir()";
     }
@@ -1041,8 +1144,9 @@
 }
 
 bool llkInit(const char* threadname) {
+    auto debuggable = android::base::GetBoolProperty("ro.debuggable", false);
     llkLowRam = android::base::GetBoolProperty("ro.config.low_ram", false);
-    if (!LLK_ENABLE_DEFAULT && android::base::GetBoolProperty("ro.debuggable", false)) {
+    if (!LLK_ENABLE_DEFAULT && debuggable) {
         llkEnable = android::base::GetProperty(LLK_ENABLE_PROPERTY, "eng") == "eng";
         khtEnable = android::base::GetProperty(KHT_ENABLE_PROPERTY, "eng") == "eng";
     }
@@ -1069,8 +1173,21 @@
     llkValidate();  // validate llkTimeoutMs, llkCheckMs and llkCycle
     llkStateTimeoutMs[llkStateD] = GetUintProperty(LLK_D_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
     llkStateTimeoutMs[llkStateZ] = GetUintProperty(LLK_Z_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
+#ifdef __PTRACE_ENABLED__
+    llkStateTimeoutMs[llkStateStack] = GetUintProperty(LLK_STACK_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
+#endif
     llkCheckMs = GetUintProperty(LLK_CHECK_MS_PROPERTY, llkCheckMs);
     llkValidate();  // validate all (effectively minus llkTimeoutMs)
+#ifdef __PTRACE_ENABLED__
+    if (debuggable) {
+        llkCheckStackSymbols = llkSplit(
+                android::base::GetProperty(LLK_CHECK_STACK_PROPERTY, LLK_CHECK_STACK_DEFAULT));
+    }
+    std::string defaultBlacklistStack(LLK_BLACKLIST_STACK_DEFAULT);
+    if (!debuggable) defaultBlacklistStack += ",logd,/system/bin/logd";
+    llkBlacklistStack = llkSplit(
+            android::base::GetProperty(LLK_BLACKLIST_STACK_PROPERTY, defaultBlacklistStack));
+#endif
     std::string defaultBlacklistProcess(
         std::to_string(kernelPid) + "," + std::to_string(initPid) + "," +
         std::to_string(kthreaddPid) + "," + std::to_string(::getpid()) + "," +
diff --git a/llkd/llkd-debuggable.rc b/llkd/llkd-debuggable.rc
new file mode 100644
index 0000000..724cb5e
--- /dev/null
+++ b/llkd/llkd-debuggable.rc
@@ -0,0 +1,19 @@
+on property:ro.debuggable=1
+    setprop llk.enable ${ro.llk.enable:-1}
+    setprop khungtask.enable ${ro.khungtask.enable:-1}
+
+on property:ro.llk.enable=eng
+    setprop llk.enable ${ro.debuggable:-0}
+
+on property:ro.khungtask.enable=eng
+    setprop khungtask.enable ${ro.debuggable:-0}
+
+service llkd-1 /system/bin/llkd
+    class late_start
+    disabled
+    user llkd
+    group llkd readproc
+    capabilities KILL IPC_LOCK SYS_PTRACE DAC_OVERRIDE
+    file /dev/kmsg w
+    file /proc/sysrq-trigger w
+    writepid /dev/cpuset/system-background/tasks
diff --git a/llkd/llkd.rc b/llkd/llkd.rc
index e538cdb..b1f96a8 100644
--- a/llkd/llkd.rc
+++ b/llkd/llkd.rc
@@ -3,15 +3,8 @@
     setprop llk.enable ${ro.llk.enable:-0}
     setprop khungtask.enable ${ro.khungtask.enable:-0}
 
-on property:ro.debuggable=1
-    setprop llk.enable ${ro.llk.enable:-1}
-    setprop khungtask.enable ${ro.khungtask.enable:-1}
-
-on property:ro.llk.enable=eng
-    setprop llk.enable ${ro.debuggable:-0}
-
-on property:ro.khungtask.enable=eng
-    setprop khungtask.enable ${ro.debuggable:-0}
+on property:ro.llk.enable=true
+    setprop llk.enable true
 
 on property:llk.enable=1
     setprop llk.enable true
@@ -19,6 +12,9 @@
 on property:llk.enable=0
     setprop llk.enable false
 
+on property:ro.khungtask.enable=true
+    setprop khungtask.enable true
+
 on property:khungtask.enable=1
     setprop khungtask.enable true
 
@@ -36,9 +32,9 @@
     write /proc/sys/kernel/hung_task_panic 0
 
 on property:llk.enable=true
-    start llkd
+    start llkd-${ro.debuggable:-0}
 
-service llkd /system/bin/llkd
+service llkd-0 /system/bin/llkd
     class late_start
     disabled
     user llkd
diff --git a/llkd/tests/llkd_test.cpp b/llkd/tests/llkd_test.cpp
index 3a15ff1..f54932b 100644
--- a/llkd/tests/llkd_test.cpp
+++ b/llkd/tests/llkd_test.cpp
@@ -14,8 +14,10 @@
  * limitations under the License.
  */
 
+#include <fcntl.h>
 #include <signal.h>
 #include <stdint.h>
+#include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
@@ -81,9 +83,12 @@
         (GetUintProperty(LLK_CHECK_MS_PROPERTY,
                          LLK_TIMEOUT_MS_DEFAULT / LLK_CHECKS_PER_TIMEOUT_DEFAULT) !=
          duration_cast<milliseconds>(10s))) {
-        execute("stop llkd");
+        execute("stop llkd-0");
+        execute("stop llkd-1");
         rest();
         std::string setprop("setprop ");
+        execute((setprop + LLK_CHECK_STACK_PROPERTY + " SyS_openat").c_str());
+        rest();
         execute((setprop + LLK_ENABLE_WRITEABLE_PROPERTY + " false").c_str());
         rest();
         execute((setprop + LLK_TIMEOUT_MS_PROPERTY + " 120000").c_str());
@@ -92,8 +97,10 @@
         rest();
         execute((setprop + LLK_CHECK_MS_PROPERTY + " 10000").c_str());
         rest();
-        execute((setprop + LLK_ENABLE_PROPERTY + " true").c_str());
-        rest();
+        if (!default_enable) {
+            execute((setprop + LLK_ENABLE_PROPERTY + " true").c_str());
+            rest();
+        }
         execute((setprop + LLK_ENABLE_WRITEABLE_PROPERTY + " true").c_str());
         rest();
     }
@@ -104,7 +111,7 @@
     }
     default_enable = android::base::GetBoolProperty(LLK_ENABLE_PROPERTY, default_enable);
     if (default_enable) {
-        execute("start llkd");
+        execute("start llkd-1");
         rest();
         GTEST_LOG_INFO << "llkd enabled\n";
     } else {
@@ -123,8 +130,10 @@
         llkTimeoutMs = LLK_TIMEOUT_MS_MINIMUM;
     }
     milliseconds llkCheckMs = llkTimeoutMs / LLK_CHECKS_PER_TIMEOUT_DEFAULT;
-    auto timeout = GetUintProperty(
-        (state == 'Z') ? LLK_Z_TIMEOUT_MS_PROPERTY : LLK_D_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
+    auto timeout = GetUintProperty((state == 'Z') ? LLK_Z_TIMEOUT_MS_PROPERTY
+                                                  : (state == 'S') ? LLK_STACK_TIMEOUT_MS_PROPERTY
+                                                                   : LLK_D_TIMEOUT_MS_PROPERTY,
+                                   llkTimeoutMs);
     if (timeout < LLK_TIMEOUT_MS_MINIMUM) {
         timeout = LLK_TIMEOUT_MS_MINIMUM;
     }
@@ -285,3 +294,41 @@
 
     waitForPid(child_pid);
 }
+
+TEST(llkd, sleep) {
+    if (checkKill("kernel_panic,sysrq,livelock,sleeping")) {
+        return;
+    }
+    if (!android::base::GetBoolProperty("ro.debuggable", false)) {
+        GTEST_LOG_WARNING << "Features not available on user builds\n";
+    }
+
+    const auto period = llkdSleepPeriod('S');
+
+    /* Create a Persistent SyS_openat for single-ended pipe */
+    static constexpr char stack_pipe_file[] = "/dev/stack_pipe_file";
+    unlink(stack_pipe_file);
+    auto pipe_ret = mknod(stack_pipe_file, S_IFIFO | 0666, 0);
+    ASSERT_LE(0, pipe_ret);
+
+    auto child_pid = fork();
+    ASSERT_LE(0, child_pid);
+    if (!child_pid) {
+        child_pid = fork();
+        ASSERT_LE(0, child_pid);
+        if (!child_pid) {
+            sleep(period.count());
+            auto fd = open(stack_pipe_file, O_RDONLY | O_CLOEXEC);
+            close(fd);
+            exit(0);
+        } else {
+            auto fd = open(stack_pipe_file, O_WRONLY | O_CLOEXEC);
+            close(fd);
+            exit(42);
+        }
+    }
+
+    waitForPid(child_pid);
+
+    unlink(stack_pipe_file);
+}
diff --git a/platform_tools_tool_version.mk b/platform_tools_tool_version.mk
deleted file mode 100644
index eed2ab5..0000000
--- a/platform_tools_tool_version.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (C) 2017 Google Inc.
-#
-# 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.
-
-# We rewrite ${PLATFORM_SDK_VERSION} with 0 rather than $(PLATFORM_SDK_VERSION)
-# because on the actual platform tools release branches the file contains a
-# literal instead. Using 0 lets us easily distinguish non-canonical builds.
-platform_tools_version := $(shell sed \
-    's/$${PLATFORM_SDK_VERSION}/0/ ; s/^Pkg.Revision=\(.*\)/\1/p ; d' \
-    development/sdk/plat_tools_source.prop_template \
-  )
-tool_version := $(platform_tools_version)-$(BUILD_NUMBER_FROM_FILE)
diff --git a/shell_and_utilities/Android.bp b/shell_and_utilities/Android.bp
index 3d7521c..2d4a26f 100644
--- a/shell_and_utilities/Android.bp
+++ b/shell_and_utilities/Android.bp
@@ -21,6 +21,7 @@
         "tcpdump",
         "toolbox",
         "toybox",
+        "unzip",
     ],
 }
 
@@ -31,6 +32,7 @@
         "sh.recovery",
         "toolbox.recovery",
         "toybox.recovery",
+        "unzip.recovery",
     ],
 }
 
diff --git a/trusty/keymaster/legacy/trusty_keymaster_device.cpp b/trusty/keymaster/legacy/trusty_keymaster_device.cpp
index ea00a92..afdf43b 100644
--- a/trusty/keymaster/legacy/trusty_keymaster_device.cpp
+++ b/trusty/keymaster/legacy/trusty_keymaster_device.cpp
@@ -122,10 +122,10 @@
 void AddClientAndAppData(const keymaster_blob_t* client_id, const keymaster_blob_t* app_data,
                          RequestType* request) {
     request->additional_params.Clear();
-    if (client_id) {
+    if (client_id && client_id->data_length > 0) {
         request->additional_params.push_back(TAG_APPLICATION_ID, *client_id);
     }
-    if (app_data) {
+    if (app_data && app_data->data_length > 0) {
         request->additional_params.push_back(TAG_APPLICATION_DATA, *app_data);
     }
 }