Merge "libdm: Fix WaitForFile early-returning on failed accesses."
diff --git a/CleanSpec.mk b/CleanSpec.mk
index c84bd24..0a534a2 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -90,3 +90,4 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/debug_ramdisk/product_services)
 $(call add-clean-step, find $(PRODUCT_OUT) -type l -name "charger" -print0 | xargs -0 rm -f)
 $(call add-clean-step, rm -f $(PRODUCT_OUT)/system/bin/adbd)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/init/snapshotctl.rc)
diff --git a/adb/Android.bp b/adb/Android.bp
index fea8c78..97bc4da 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -314,6 +314,7 @@
         "libadb_protos",
         "libadb_tls_connection",
         "libandroidfw",
+        "libapp_processes_protos_full",
         "libbase",
         "libcutils",
         "libcrypto_utils",
@@ -323,7 +324,7 @@
         "liblog",
         "liblz4",
         "libmdnssd",
-        "libprotobuf-cpp-lite",
+        "libprotobuf-cpp-full",
         "libssl",
         "libusb",
         "libutils",
@@ -375,6 +376,7 @@
     srcs: libadb_srcs + libadb_linux_srcs + libadb_posix_srcs + [
         "daemon/auth.cpp",
         "daemon/jdwp_service.cpp",
+        "daemon/logging.cpp",
         "daemon/adb_wifi.cpp",
     ],
 
@@ -386,6 +388,7 @@
 
     static_libs: [
         "libadbconnection_server",
+        "libapp_processes_protos_lite",
         "libdiagnose_usb",
     ],
 
@@ -402,6 +405,12 @@
         "liblog",
     ],
 
+    proto: {
+        type: "lite",
+        static: true,
+        export_proto_headers: true,
+    },
+
     target: {
         android: {
             whole_static_libs: [
@@ -418,6 +427,12 @@
             srcs: [
                 "daemon/usb_dummy.cpp",
             ]
+        },
+        recovery: {
+            exclude_shared_libs: [
+                "libadb_pairing_auth",
+                "libadb_pairing_connection",
+            ],
         }
     },
 }
@@ -443,7 +458,9 @@
     static_libs: [
         "libadbconnection_server",
         "libadbd_core",
+        "libapp_processes_protos_lite",
         "libdiagnose_usb",
+        "libprotobuf-cpp-lite",
     ],
 
     shared_libs: [
@@ -477,6 +494,10 @@
             exclude_srcs: [
                 "daemon/abb_service.cpp",
             ],
+            exclude_shared_libs: [
+                "libadb_pairing_auth",
+                "libadb_pairing_connection",
+            ],
         },
     },
 }
@@ -496,6 +517,8 @@
     whole_static_libs: [
         "libadbconnection_server",
         "libadbd_core",
+        "libapp_processes_protos_lite",
+        "libprotobuf-cpp-lite",
     ],
 
     shared_libs: [
@@ -512,6 +535,15 @@
         "libselinux",
     ],
 
+    target: {
+        recovery: {
+            exclude_shared_libs: [
+                "libadb_pairing_auth",
+                "libadb_pairing_connection",
+            ],
+        }
+    },
+
     static_libs: [
         "libadbd_services",
         "libcutils_sockets",
@@ -544,9 +576,12 @@
     },
 
     static_libs: [
+        "libadb_crypto",
+        "libadb_tls_connection",
         "libadbconnection_server",
         "libadbd",
         "libadbd_services",
+        "libapp_processes_protos_lite",
         "libasyncio",
         "libbase",
         "libcap",
@@ -556,20 +591,28 @@
         "liblog",
         "libmdnssd",
         "libminijail",
+        "libprotobuf-cpp-lite",
         "libselinux",
         "libssl",
     ],
 
     shared_libs: [
-        "libadb_crypto",
         "libadb_pairing_connection",
         "libadb_protos",
-        "libadb_tls_connection",
         "libadbd_auth",
         "libadbd_fs",
         "libcrypto",
     ],
 
+    target: {
+        recovery: {
+            exclude_shared_libs: [
+                "libadb_pairing_auth",
+                "libadb_pairing_connection",
+            ],
+        }
+    },
+
     required: [
         "libadbd_auth",
         "libadbd_fs",
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 554a754..98db191 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -34,6 +34,7 @@
 #include <condition_variable>
 #include <mutex>
 #include <string>
+#include <string_view>
 #include <thread>
 #include <vector>
 
@@ -61,6 +62,8 @@
 #include <sys/mount.h>
 #include <android-base/properties.h>
 using namespace std::chrono_literals;
+
+#include "daemon/logging.h"
 #endif
 
 std::string adb_version() {
@@ -312,6 +315,9 @@
 #if ADB_HOST
     handle_online(t);
 #else
+    ADB_LOG(Connection) << "received CNXN: version=" << p->msg.arg0 << ", maxdata = " << p->msg.arg1
+                        << ", banner = '" << banner << "'";
+
     if (t->use_tls) {
         // We still handshake in TLS mode. If auth_required is disabled,
         // we'll just not verify the client's certificate. This should be the
diff --git a/adb/adb.h b/adb/adb.h
index 86d205c..9f8d299 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -169,6 +169,7 @@
 int init_jdwp(void);
 asocket* create_jdwp_service_socket();
 asocket* create_jdwp_tracker_service_socket();
+asocket* create_app_tracker_service_socket();
 unique_fd create_jdwp_connection_fd(int jdwp_pid);
 #endif
 
diff --git a/adb/apex/Android.bp b/adb/apex/Android.bp
index 0189455..4346f67 100644
--- a/adb/apex/Android.bp
+++ b/adb/apex/Android.bp
@@ -1,5 +1,6 @@
 apex_defaults {
     name: "com.android.adbd-defaults",
+    updatable: true,
 
     binaries: ["adbd"],
     compile_multilib: "both",
diff --git a/adb/client/auth.cpp b/adb/client/auth.cpp
index 8738ce7..4b2fa04 100644
--- a/adb/client/auth.cpp
+++ b/adb/client/auth.cpp
@@ -145,12 +145,12 @@
 
     std::lock_guard<std::mutex> lock(g_keys_mutex);
     std::string fingerprint = hash_key(key.get());
-    if (g_keys.find(fingerprint) != g_keys.end()) {
-        LOG(INFO) << "ignoring already-loaded key: " << file;
-    } else {
-        LOG(INFO) << "Loaded fingerprint=[" << SHA256BitsToHexString(fingerprint) << "]";
+    bool already_loaded = (g_keys.find(fingerprint) != g_keys.end());
+    if (!already_loaded) {
         g_keys[fingerprint] = std::move(key);
     }
+    LOG(INFO) << (already_loaded ? "ignored already-loaded" : "loaded new") << " key from '" << file
+              << "' with fingerprint " << SHA256BitsToHexString(fingerprint);
     return true;
 }
 
@@ -159,23 +159,25 @@
 
     struct stat st;
     if (stat(path.c_str(), &st) != 0) {
-        PLOG(ERROR) << "failed to stat '" << path << "'";
+        PLOG(ERROR) << "load_keys: failed to stat '" << path << "'";
         return false;
     }
 
     if (S_ISREG(st.st_mode)) {
         return load_key(path);
-    } else if (S_ISDIR(st.st_mode)) {
+    }
+
+    if (S_ISDIR(st.st_mode)) {
         if (!allow_dir) {
             // inotify isn't recursive. It would break expectations to load keys in nested
             // directories but not monitor them for new keys.
-            LOG(WARNING) << "refusing to recurse into directory '" << path << "'";
+            LOG(WARNING) << "load_keys: refusing to recurse into directory '" << path << "'";
             return false;
         }
 
         std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
         if (!dir) {
-            PLOG(ERROR) << "failed to open directory '" << path << "'";
+            PLOG(ERROR) << "load_keys: failed to open directory '" << path << "'";
             return false;
         }
 
@@ -189,7 +191,7 @@
             }
 
             if (!android::base::EndsWith(name, ".adb_key")) {
-                LOG(INFO) << "skipping non-adb_key '" << path << "/" << name << "'";
+                LOG(INFO) << "skipped non-adb_key '" << path << "/" << name << "'";
                 continue;
             }
 
@@ -198,7 +200,7 @@
         return result;
     }
 
-    LOG(ERROR) << "unexpected type for '" << path << "': 0x" << std::hex << st.st_mode;
+    LOG(ERROR) << "load_keys: unexpected type for '" << path << "': 0x" << std::hex << st.st_mode;
     return false;
 }
 
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 081bac4..1186060 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -50,6 +50,8 @@
 #include <unistd.h>
 #endif
 
+#include <google/protobuf/text_format.h>
+
 #include "adb.h"
 #include "adb_auth.h"
 #include "adb_client.h"
@@ -57,6 +59,7 @@
 #include "adb_io.h"
 #include "adb_unique_fd.h"
 #include "adb_utils.h"
+#include "app_processes.pb.h"
 #include "bugreport.h"
 #include "client/file_sync_client.h"
 #include "commandline.h"
@@ -1354,17 +1357,49 @@
     }
 }
 
-static int adb_connect_command(const std::string& command, TransportId* transport = nullptr) {
+static int adb_connect_command(const std::string& command, TransportId* transport,
+                               StandardStreamsCallbackInterface* callback) {
     std::string error;
     unique_fd fd(adb_connect(transport, command, &error));
     if (fd < 0) {
         fprintf(stderr, "error: %s\n", error.c_str());
         return 1;
     }
-    read_and_dump(fd);
+    read_and_dump(fd, false, callback);
     return 0;
 }
 
+static int adb_connect_command(const std::string& command, TransportId* transport = nullptr) {
+    return adb_connect_command(command, transport, &DEFAULT_STANDARD_STREAMS_CALLBACK);
+}
+
+// A class that prints out human readable form of the protobuf message for "track-app" service
+// (received in binary format).
+class TrackAppStreamsCallback : public DefaultStandardStreamsCallback {
+  public:
+    TrackAppStreamsCallback() : DefaultStandardStreamsCallback(nullptr, nullptr) {}
+
+    // Assume the buffer contains at least 4 bytes of valid data.
+    void OnStdout(const char* buffer, int length) override {
+        if (length < 4) return;  // Unexpected length received. Do nothing.
+
+        adb::proto::AppProcesses binary_proto;
+        // The first 4 bytes are the length of remaining content in hexadecimal format.
+        binary_proto.ParseFromString(std::string(buffer + 4, length - 4));
+        char summary[24];  // The following string includes digits and 16 fixed characters.
+        int written = snprintf(summary, sizeof(summary), "Process count: %d\n",
+                               binary_proto.process_size());
+        OnStream(nullptr, stdout, summary, written);
+
+        std::string string_proto;
+        google::protobuf::TextFormat::PrintToString(binary_proto, &string_proto);
+        OnStream(nullptr, stdout, string_proto.data(), string_proto.length());
+    }
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(TrackAppStreamsCallback);
+};
+
 static int adb_connect_command_bidirectional(const std::string& command) {
     std::string error;
     unique_fd fd(adb_connect(command, &error));
@@ -1925,6 +1960,18 @@
         return adb_connect_command("jdwp");
     } else if (!strcmp(argv[0], "track-jdwp")) {
         return adb_connect_command("track-jdwp");
+    } else if (!strcmp(argv[0], "track-app")) {
+        FeatureSet features;
+        std::string error;
+        if (!adb_get_feature_set(&features, &error)) {
+            fprintf(stderr, "error: %s\n", error.c_str());
+            return 1;
+        }
+        if (!CanUseFeature(features, kFeatureTrackApp)) {
+            error_exit("track-app is not supported by the device");
+        }
+        TrackAppStreamsCallback callback;
+        return adb_connect_command("track-app", nullptr, &callback);
     } else if (!strcmp(argv[0], "track-devices")) {
         if (argc > 2 || (argc == 2 && strcmp(argv[1], "-l"))) {
             error_exit("usage: adb track-devices [-l]");
diff --git a/adb/crypto/Android.bp b/adb/crypto/Android.bp
index b7f75ed..ce1de4a 100644
--- a/adb/crypto/Android.bp
+++ b/adb/crypto/Android.bp
@@ -45,8 +45,6 @@
     host_supported: true,
     recovery_available: true,
 
-    stl: "libc++_static",
-
     shared_libs: [
         "libadb_protos",
         "libbase",
diff --git a/adb/daemon/jdwp_service.cpp b/adb/daemon/jdwp_service.cpp
index b92a7de..c99aead 100644
--- a/adb/daemon/jdwp_service.cpp
+++ b/adb/daemon/jdwp_service.cpp
@@ -21,6 +21,7 @@
 #include "sysdeps.h"
 
 #include <errno.h>
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -33,6 +34,7 @@
 #include <thread>
 #include <vector>
 
+#include <adbconnection/process_info.h>
 #include <adbconnection/server.h>
 #include <android-base/cmsg.h>
 #include <android-base/unique_fd.h>
@@ -41,6 +43,7 @@
 #include "adb_io.h"
 #include "adb_unique_fd.h"
 #include "adb_utils.h"
+#include "app_processes.pb.h"
 
 using android::base::borrowed_fd;
 using android::base::unique_fd;
@@ -132,18 +135,24 @@
  ** for each JDWP process, we record its pid and its connected socket
  **/
 
+enum class TrackerKind {
+    kJdwp,
+    kApp,
+};
+
 static void jdwp_process_event(int socket, unsigned events, void* _proc);
 static void jdwp_process_list_updated(void);
+static void app_process_list_updated(void);
 
 struct JdwpProcess;
 static auto& _jdwp_list = *new std::list<std::unique_ptr<JdwpProcess>>();
 
 struct JdwpProcess {
-    JdwpProcess(unique_fd socket, pid_t pid) {
-        CHECK(pid != 0);
+    JdwpProcess(unique_fd socket, ProcessInfo process) {
+        CHECK(process.pid != 0);
 
         this->socket = socket;
-        this->pid = pid;
+        this->process = process;
         this->fde = fdevent_create(socket.release(), jdwp_process_event, this);
 
         if (!this->fde) {
@@ -171,17 +180,19 @@
     }
 
     borrowed_fd socket = -1;
-    int32_t pid = -1;
+    ProcessInfo process;
     fdevent* fde = nullptr;
 
     std::vector<unique_fd> out_fds;
 };
 
+// Populate the list of processes for "track-jdwp" service.
 static size_t jdwp_process_list(char* buffer, size_t bufferlen) {
     std::string temp;
 
     for (auto& proc : _jdwp_list) {
-        std::string next = std::to_string(proc->pid) + "\n";
+        if (!proc->process.debuggable) continue;
+        std::string next = std::to_string(proc->process.pid) + "\n";
         if (temp.length() + next.length() > bufferlen) {
             D("truncating JDWP process list (max len = %zu)", bufferlen);
             break;
@@ -193,7 +204,44 @@
     return temp.length();
 }
 
-static size_t jdwp_process_list_msg(char* buffer, size_t bufferlen) {
+// Populate the list of processes for "track-app" service.
+// The list is a protobuf message in the binary format for efficiency.
+static size_t app_process_list(char* buffer, size_t bufferlen) {
+    adb::proto::AppProcesses output;  // result that's guaranteed to fit in the given buffer
+    adb::proto::AppProcesses temp;    // temporary result that may be longer than the given buffer
+    std::string serialized_message;
+
+    for (auto& proc : _jdwp_list) {
+        if (!proc->process.debuggable && !proc->process.profileable) continue;
+        auto* entry = temp.add_process();
+        entry->set_pid(proc->process.pid);
+        entry->set_debuggable(proc->process.debuggable);
+        entry->set_profileable(proc->process.profileable);
+        entry->set_architecture(proc->process.arch_name, proc->process.arch_name_length);
+        temp.SerializeToString(&serialized_message);
+        if (serialized_message.size() > bufferlen) {
+            D("truncating app process list (max len = %zu)", bufferlen);
+            break;
+        }
+        output = temp;
+    }
+    output.SerializeToString(&serialized_message);
+    memcpy(buffer, serialized_message.data(), serialized_message.length());
+    return serialized_message.length();
+}
+
+// Populate the list of processes for either "track-jdwp" or "track-app" services,
+// depending on the given kind.
+static size_t process_list(TrackerKind kind, char* buffer, size_t bufferlen) {
+    switch (kind) {
+        case TrackerKind::kJdwp:
+            return jdwp_process_list(buffer, bufferlen);
+        case TrackerKind::kApp:
+            return app_process_list(buffer, bufferlen);
+    }
+}
+
+static size_t process_list_msg(TrackerKind kind, char* buffer, size_t bufferlen) {
     // Message is length-prefixed with 4 hex digits in ASCII.
     static constexpr size_t header_len = 4;
     if (bufferlen < header_len) {
@@ -201,7 +249,7 @@
     }
 
     char head[header_len + 1];
-    size_t len = jdwp_process_list(buffer + header_len, bufferlen - header_len);
+    size_t len = process_list(kind, buffer + header_len, bufferlen - header_len);
     snprintf(head, sizeof head, "%04zx", len);
     memcpy(buffer, head, header_len);
     return len + header_len;
@@ -213,7 +261,7 @@
 
     if (events & FDE_READ) {
         // We already have the PID, if we can read from the socket, we've probably hit EOF.
-        D("terminating JDWP connection %d", proc->pid);
+        D("terminating JDWP connection %" PRId64, proc->process.pid);
         goto CloseProcess;
     }
 
@@ -223,11 +271,12 @@
 
         int fd = proc->out_fds.back().get();
         if (android::base::SendFileDescriptors(socket, "", 1, fd) != 1) {
-            D("sending new file descriptor to JDWP %d failed: %s", proc->pid, strerror(errno));
+            D("sending new file descriptor to JDWP %" PRId64 " failed: %s", proc->process.pid,
+              strerror(errno));
             goto CloseProcess;
         }
 
-        D("sent file descriptor %d to JDWP process %d", fd, proc->pid);
+        D("sent file descriptor %d to JDWP process %" PRId64, fd, proc->process.pid);
 
         proc->out_fds.pop_back();
         if (proc->out_fds.empty()) {
@@ -238,15 +287,20 @@
     return;
 
 CloseProcess:
+    bool debuggable = proc->process.debuggable;
+    bool profileable = proc->process.profileable;
     proc->RemoveFromList();
-    jdwp_process_list_updated();
+    if (debuggable) jdwp_process_list_updated();
+    if (debuggable || profileable) app_process_list_updated();
 }
 
 unique_fd create_jdwp_connection_fd(int pid) {
     D("looking for pid %d in JDWP process list", pid);
 
     for (auto& proc : _jdwp_list) {
-        if (proc->pid == pid) {
+        // Don't allow JDWP connection to a non-debuggable process.
+        if (!proc->process.debuggable) continue;
+        if (proc->process.pid == static_cast<uint64_t>(pid)) {
             int fds[2];
 
             if (adb_socketpair(fds) < 0) {
@@ -338,18 +392,22 @@
  **/
 
 struct JdwpTracker : public asocket {
+    TrackerKind kind;
     bool need_initial;
+
+    explicit JdwpTracker(TrackerKind k, bool initial) : kind(k), need_initial(initial) {}
 };
 
 static auto& _jdwp_trackers = *new std::vector<std::unique_ptr<JdwpTracker>>();
 
-static void jdwp_process_list_updated(void) {
+static void process_list_updated(TrackerKind kind) {
     std::string data;
-    data.resize(1024);
-    data.resize(jdwp_process_list_msg(&data[0], data.size()));
+    const int kMaxLength = kind == TrackerKind::kJdwp ? 1024 : 2048;
+    data.resize(kMaxLength);
+    data.resize(process_list_msg(kind, &data[0], data.size()));
 
     for (auto& t : _jdwp_trackers) {
-        if (t->peer) {
+        if (t->kind == kind && t->peer) {
             // The tracker might not have been connected yet.
             apacket::payload_type payload(data.begin(), data.end());
             t->peer->enqueue(t->peer, std::move(payload));
@@ -357,6 +415,14 @@
     }
 }
 
+static void jdwp_process_list_updated(void) {
+    process_list_updated(TrackerKind::kJdwp);
+}
+
+static void app_process_list_updated(void) {
+    process_list_updated(TrackerKind::kApp);
+}
+
 static void jdwp_tracker_close(asocket* s) {
     D("LS(%d): destroying jdwp tracker service", s->id);
 
@@ -380,7 +446,7 @@
     if (t->need_initial) {
         apacket::payload_type data;
         data.resize(s->get_max_payload());
-        data.resize(jdwp_process_list_msg(&data[0], data.size()));
+        data.resize(process_list_msg(t->kind, &data[0], data.size()));
         t->need_initial = false;
         s->peer->enqueue(s->peer, std::move(data));
     }
@@ -393,8 +459,8 @@
     return -1;
 }
 
-asocket* create_jdwp_tracker_service_socket(void) {
-    auto t = std::make_unique<JdwpTracker>();
+asocket* create_process_tracker_service_socket(TrackerKind kind) {
+    auto t = std::make_unique<JdwpTracker>(kind, true);
     if (!t) {
         LOG(FATAL) << "failed to allocate JdwpTracker";
     }
@@ -407,7 +473,6 @@
     t->ready = jdwp_tracker_ready;
     t->enqueue = jdwp_tracker_enqueue;
     t->close = jdwp_tracker_close;
-    t->need_initial = true;
 
     asocket* result = t.get();
 
@@ -416,19 +481,28 @@
     return result;
 }
 
+asocket* create_jdwp_tracker_service_socket() {
+    return create_process_tracker_service_socket(TrackerKind::kJdwp);
+}
+
+asocket* create_app_tracker_service_socket() {
+    return create_process_tracker_service_socket(TrackerKind::kApp);
+}
+
 int init_jdwp(void) {
     std::thread([]() {
         adb_thread_setname("jdwp control");
-        adbconnection_listen([](int fd, pid_t pid) {
-            LOG(INFO) << "jdwp connection from " << pid;
-            fdevent_run_on_main_thread([fd, pid] {
+        adbconnection_listen([](int fd, ProcessInfo process) {
+            LOG(INFO) << "jdwp connection from " << process.pid;
+            fdevent_run_on_main_thread([fd, process] {
                 unique_fd ufd(fd);
-                auto proc = std::make_unique<JdwpProcess>(std::move(ufd), pid);
+                auto proc = std::make_unique<JdwpProcess>(std::move(ufd), process);
                 if (!proc) {
                     LOG(FATAL) << "failed to allocate JdwpProcess";
                 }
                 _jdwp_list.emplace_back(std::move(proc));
-                jdwp_process_list_updated();
+                if (process.debuggable) jdwp_process_list_updated();
+                if (process.debuggable || process.profileable) app_process_list_updated();
             });
         });
     }).detach();
diff --git a/adb/daemon/logging.cpp b/adb/daemon/logging.cpp
new file mode 100644
index 0000000..203c6c7
--- /dev/null
+++ b/adb/daemon/logging.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2020 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 "daemon/logging.h"
+
+#include <mutex>
+#include <optional>
+#include <string_view>
+
+#include <android-base/no_destructor.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <android-base/thread_annotations.h>
+
+#if defined(__ANDROID__)
+struct LogStatus {
+    bool enabled[static_cast<size_t>(adb::LogType::COUNT)];
+
+    bool& operator[](adb::LogType type) { return enabled[static_cast<size_t>(type)]; }
+};
+
+using android::base::CachedProperty;
+using android::base::NoDestructor;
+
+static NoDestructor<std::mutex> log_mutex;
+static NoDestructor<CachedProperty> log_property GUARDED_BY(log_mutex)("debug.adbd.logging");
+static std::optional<LogStatus> cached_log_status GUARDED_BY(log_mutex);
+
+static NoDestructor<CachedProperty> persist_log_property
+        GUARDED_BY(log_mutex)("persist.debug.adbd.logging");
+static std::optional<LogStatus> cached_persist_log_status GUARDED_BY(log_mutex);
+
+static LogStatus ParseLogStatus(std::string_view str) {
+    LogStatus result = {};
+    for (const auto& part : android::base::Split(std::string(str), ",")) {
+        if (part == "cnxn") {
+            result[adb::LogType::Connection] = true;
+        } else if (part == "service") {
+            result[adb::LogType::Service] = true;
+        } else if (part == "shell") {
+            result[adb::LogType::Shell] = true;
+        } else if (part == "all") {
+            result[adb::LogType::Connection] = true;
+            result[adb::LogType::Service] = true;
+            result[adb::LogType::Shell] = true;
+        }
+    }
+    return result;
+}
+
+static LogStatus GetLogStatus(android::base::CachedProperty* property,
+                              std::optional<LogStatus>* cached_status) REQUIRES(log_mutex) {
+    bool changed;
+    const char* value = property->Get(&changed);
+    if (changed || !*cached_status) {
+        **cached_status = ParseLogStatus(value);
+    }
+    return **cached_status;
+}
+
+namespace adb {
+bool is_logging_enabled(LogType type) {
+    std::lock_guard<std::mutex> lock(*log_mutex);
+    return GetLogStatus(log_property.get(), &cached_log_status)[type] ||
+           GetLogStatus(persist_log_property.get(), &cached_persist_log_status)[type];
+}
+}  // namespace adb
+
+#else
+
+namespace adb {
+bool is_logging_enabled(LogType type) {
+    return false;
+}
+}  // namespace adb
+#endif
diff --git a/adb/daemon/logging.h b/adb/daemon/logging.h
new file mode 100644
index 0000000..3e28bef
--- /dev/null
+++ b/adb/daemon/logging.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/logging.h>
+
+namespace adb {
+enum class LogType {
+    Connection,
+    Service,
+    Shell,
+    COUNT,
+};
+
+bool is_logging_enabled(LogType type);
+
+#define ADB_LOG(type) ::adb::is_logging_enabled(::adb::LogType::type) && LOG(INFO)
+
+}  // namespace adb
diff --git a/adb/daemon/services.cpp b/adb/daemon/services.cpp
index 4ec90d2..a9d1fe8 100644
--- a/adb/daemon/services.cpp
+++ b/adb/daemon/services.cpp
@@ -54,10 +54,10 @@
 
 #include "daemon/file_sync_service.h"
 #include "daemon/framebuffer_service.h"
+#include "daemon/logging.h"
 #include "daemon/restart_service.h"
 #include "daemon/shell_service.h"
 
-
 void reconnect_service(unique_fd fd, atransport* t) {
     WriteFdExactly(fd.get(), "done");
     kick_transport(t);
@@ -241,6 +241,8 @@
         return create_jdwp_service_socket();
     } else if (name == "track-jdwp") {
         return create_jdwp_tracker_service_socket();
+    } else if (name == "track-app") {
+        return create_app_tracker_service_socket();
     } else if (android::base::ConsumePrefix(&name, "sink:")) {
         uint64_t byte_count = 0;
         if (!ParseUint(&byte_count, name)) {
@@ -259,6 +261,8 @@
 }
 
 unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) {
+    ADB_LOG(Service) << "transport " << transport->serial_name() << " opening service " << name;
+
 #if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
     if (name.starts_with("abb:") || name.starts_with("abb_exec:")) {
         return execute_abb_command(name);
diff --git a/adb/daemon/shell_service.cpp b/adb/daemon/shell_service.cpp
index f62032d..fbfae1e 100644
--- a/adb/daemon/shell_service.cpp
+++ b/adb/daemon/shell_service.cpp
@@ -107,6 +107,7 @@
 #include "adb_trace.h"
 #include "adb_unique_fd.h"
 #include "adb_utils.h"
+#include "daemon/logging.h"
 #include "security_log_tags.h"
 #include "shell_protocol.h"
 
@@ -760,14 +761,14 @@
             D("post waitpid (pid=%d) status=%04x", pid_, status);
             if (WIFSIGNALED(status)) {
                 exit_code = 0x80 | WTERMSIG(status);
-                D("subprocess killed by signal %d", WTERMSIG(status));
+                ADB_LOG(Shell) << "subprocess " << pid_ << " killed by signal " << WTERMSIG(status);
                 break;
             } else if (!WIFEXITED(status)) {
                 D("subprocess didn't exit");
                 break;
             } else if (WEXITSTATUS(status) >= 0) {
                 exit_code = WEXITSTATUS(status);
-                D("subprocess exit code = %d", WEXITSTATUS(status));
+                ADB_LOG(Shell) << "subprocess " << pid_ << " exited with status " << exit_code;
                 break;
             }
         }
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index 0928198..87937fb 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -282,6 +282,7 @@
 
         monitor_thread_ = std::thread([this]() {
             adb_thread_setname("UsbFfs-monitor");
+            LOG(INFO) << "UsbFfs-monitor thread spawned";
 
             bool bound = false;
             bool enabled = false;
@@ -427,6 +428,8 @@
         worker_started_ = true;
         worker_thread_ = std::thread([this]() {
             adb_thread_setname("UsbFfs-worker");
+            LOG(INFO) << "UsbFfs-worker thread spawned";
+
             for (size_t i = 0; i < kUsbReadQueueDepth; ++i) {
                 read_requests_[i] = CreateReadBlock(next_read_id_++);
                 if (!SubmitRead(&read_requests_[i])) {
@@ -525,14 +528,16 @@
             }
 
             if (id.direction == TransferDirection::READ) {
-                HandleRead(id, event.res);
+                if (!HandleRead(id, event.res)) {
+                    return;
+                }
             } else {
                 HandleWrite(id);
             }
         }
     }
 
-    void HandleRead(TransferId id, int64_t size) {
+    bool HandleRead(TransferId id, int64_t size) {
         uint64_t read_idx = id.id % kUsbReadQueueDepth;
         IoReadBlock* block = &read_requests_[read_idx];
         block->pending = false;
@@ -542,7 +547,7 @@
         if (block->id().id != needed_read_id_) {
             LOG(VERBOSE) << "read " << block->id().id << " completed while waiting for "
                          << needed_read_id_;
-            return;
+            return true;
         }
 
         for (uint64_t id = needed_read_id_;; ++id) {
@@ -551,15 +556,22 @@
             if (current_block->pending) {
                 break;
             }
-            ProcessRead(current_block);
+            if (!ProcessRead(current_block)) {
+                return false;
+            }
             ++needed_read_id_;
         }
+
+        return true;
     }
 
-    void ProcessRead(IoReadBlock* block) {
+    bool ProcessRead(IoReadBlock* block) {
         if (!block->payload.empty()) {
             if (!incoming_header_.has_value()) {
-                CHECK_EQ(sizeof(amessage), block->payload.size());
+                if (block->payload.size() != sizeof(amessage)) {
+                    HandleError("received packet of unexpected length while reading header");
+                    return false;
+                }
                 amessage& msg = incoming_header_.emplace();
                 memcpy(&msg, block->payload.data(), sizeof(msg));
                 LOG(DEBUG) << "USB read:" << dump_header(&msg);
@@ -567,7 +579,10 @@
             } else {
                 size_t bytes_left = incoming_header_->data_length - incoming_payload_.size();
                 Block payload = std::move(block->payload);
-                CHECK_LE(payload.size(), bytes_left);
+                if (block->payload.size() > bytes_left) {
+                    HandleError("received too many bytes while waiting for payload");
+                    return false;
+                }
                 incoming_payload_.append(std::move(payload));
             }
 
@@ -590,6 +605,7 @@
 
         PrepareReadBlock(block, block->id().id + kUsbReadQueueDepth);
         SubmitRead(block);
+        return true;
     }
 
     bool SubmitRead(IoReadBlock* block) {
diff --git a/adb/daemon/usb_ffs.cpp b/adb/daemon/usb_ffs.cpp
index b19fa5d..cb7e2fb 100644
--- a/adb/daemon/usb_ffs.cpp
+++ b/adb/daemon/usb_ffs.cpp
@@ -299,6 +299,7 @@
         }
         // Signal only when writing the descriptors to ffs
         android::base::SetProperty("sys.usb.ffs.ready", "1");
+        *out_control = std::move(control);
     }
 
     bulk_out.reset(adb_open(USB_FFS_ADB_OUT, O_RDONLY));
@@ -313,7 +314,6 @@
         return false;
     }
 
-    *out_control = std::move(control);
     *out_bulk_in = std::move(bulk_in);
     *out_bulk_out = std::move(bulk_out);
     return true;
diff --git a/adb/libs/adbconnection/adbconnection_client.cpp b/adb/libs/adbconnection/adbconnection_client.cpp
index ee48abb..c132342 100644
--- a/adb/libs/adbconnection/adbconnection_client.cpp
+++ b/adb/libs/adbconnection/adbconnection_client.cpp
@@ -29,6 +29,8 @@
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
 
+#include "adbconnection/process_info.h"
+
 using android::base::unique_fd;
 
 static constexpr char kJdwpControlName[] = "\0jdwp-control";
@@ -60,6 +62,8 @@
 
   std::optional<uint64_t> pid;
   std::optional<bool> debuggable;
+  std::optional<bool> profileable;
+  std::optional<std::string> architecture;
 
   for (size_t i = 0; i < info_count; ++i) {
     auto info = info_elems[i];
@@ -77,7 +81,23 @@
           LOG(ERROR) << "multiple debuggable entries in AdbConnectionClientInfo, ignoring";
           continue;
         }
-        debuggable = info->data.pid;
+        debuggable = info->data.debuggable;
+        break;
+
+      case AdbConnectionClientInfoType::profileable:
+        if (profileable) {
+          LOG(ERROR) << "multiple profileable entries in AdbConnectionClientInfo, ignoring";
+          continue;
+        }
+        profileable = info->data.profileable;
+        break;
+
+      case AdbConnectionClientInfoType::architecture:
+        if (architecture) {
+          LOG(ERROR) << "multiple architecture entries in AdbConnectionClientInfo, ignoring";
+          continue;
+        }
+        architecture = std::string(info->data.architecture.name, info->data.architecture.size);
         break;
     }
   }
@@ -92,6 +112,16 @@
     return nullptr;
   }
 
+  if (!profileable) {
+    LOG(ERROR) << "AdbConnectionClientInfo missing required field profileable";
+    return nullptr;
+  }
+
+  if (!architecture) {
+    LOG(ERROR) << "AdbConnectionClientInfo missing required field architecture";
+    return nullptr;
+  }
+
   ctx->control_socket_.reset(socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0));
   if (ctx->control_socket_ < 0) {
     PLOG(ERROR) << "failed to create Unix domain socket";
@@ -120,10 +150,10 @@
     return nullptr;
   }
 
-  uint32_t pid_u32 = static_cast<uint32_t>(*pid);
-  rc = TEMP_FAILURE_RETRY(write(ctx->control_socket_.get(), &pid_u32, sizeof(pid_u32)));
-  if (rc != sizeof(pid_u32)) {
-    PLOG(ERROR) << "failed to send JDWP process pid to adbd";
+  ProcessInfo process(*pid, *debuggable, *profileable, *architecture);
+  rc = TEMP_FAILURE_RETRY(write(ctx->control_socket_.get(), &process, sizeof(process)));
+  if (rc != sizeof(process)) {
+    PLOG(ERROR) << "failed to send JDWP process info to adbd";
   }
 
   return ctx.release();
diff --git a/adb/libs/adbconnection/adbconnection_server.cpp b/adb/libs/adbconnection/adbconnection_server.cpp
index 939da2f..aac9615 100644
--- a/adb/libs/adbconnection/adbconnection_server.cpp
+++ b/adb/libs/adbconnection/adbconnection_server.cpp
@@ -28,6 +28,8 @@
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
 
+#include "adbconnection/process_info.h"
+
 using android::base::unique_fd;
 
 #define JDWP_CONTROL_NAME "\0jdwp-control"
@@ -36,7 +38,7 @@
 static_assert(JDWP_CONTROL_NAME_LEN <= sizeof(reinterpret_cast<sockaddr_un*>(0)->sun_path));
 
 // Listen for incoming jdwp clients forever.
-void adbconnection_listen(void (*callback)(int fd, pid_t pid)) {
+void adbconnection_listen(void (*callback)(int fd, ProcessInfo process)) {
   sockaddr_un addr = {};
   socklen_t addrlen = JDWP_CONTROL_NAME_LEN + sizeof(addr.sun_family);
 
@@ -106,16 +108,13 @@
                      << ") in pending connections";
         }
 
-        // Massively oversized buffer: we're expecting an int32_t from the other end.
-        char buf[32];
-        int rc = TEMP_FAILURE_RETRY(recv(it->get(), buf, sizeof(buf), MSG_DONTWAIT));
-        if (rc != 4) {
+        ProcessInfo process;
+        int rc = TEMP_FAILURE_RETRY(recv(it->get(), &process, sizeof(process), MSG_DONTWAIT));
+        if (rc != sizeof(process)) {
           LOG(ERROR) << "received data of incorrect size from JDWP client: read " << rc
-                     << ", expected 4";
+                     << ", expected " << sizeof(process);
         } else {
-          int32_t pid;
-          memcpy(&pid, buf, sizeof(pid));
-          callback(it->release(), static_cast<pid_t>(pid));
+          callback(it->release(), process);
         }
 
         if (epoll_ctl(epfd.get(), EPOLL_CTL_DEL, event.data.fd, nullptr) != 0) {
diff --git a/adb/libs/adbconnection/include/adbconnection/client.h b/adb/libs/adbconnection/include/adbconnection/client.h
index 692fea0..a74cd36 100644
--- a/adb/libs/adbconnection/include/adbconnection/client.h
+++ b/adb/libs/adbconnection/include/adbconnection/client.h
@@ -28,6 +28,8 @@
 enum AdbConnectionClientInfoType {
   pid,
   debuggable,
+  profileable,
+  architecture,
 };
 
 struct AdbConnectionClientInfo {
@@ -35,11 +37,17 @@
   union {
     uint64_t pid;
     bool debuggable;
+    bool profileable;
+    struct {
+      const char* name;
+      size_t size;
+    } architecture;
   } data;
 };
 
 // Construct a context and connect to adbd.
 // Returns null if we fail to connect to adbd.
+// Note this is an apex interface as it's loaded by ART.
 AdbConnectionClientContext* adbconnection_client_new(
     const AdbConnectionClientInfo* const* info_elems, size_t info_count);
 
diff --git a/adb/libs/adbconnection/include/adbconnection/process_info.h b/adb/libs/adbconnection/include/adbconnection/process_info.h
new file mode 100644
index 0000000..86d3259
--- /dev/null
+++ b/adb/libs/adbconnection/include/adbconnection/process_info.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <string.h>
+#include <string>
+
+struct ProcessInfo {
+  const static size_t kMaxArchNameLength = 16;
+
+  uint64_t pid;
+  bool debuggable;
+  bool profileable;
+  int32_t arch_name_length;            // length of architecture name in bytes
+  char arch_name[kMaxArchNameLength];  // ISA name, e.g., "arm64"
+
+  ProcessInfo() : pid(0), debuggable(false), profileable(false), arch_name_length(0) {}
+
+  ProcessInfo(uint64_t pid, bool dbg, bool prof, const std::string& arch)
+      : pid(pid), debuggable(dbg), profileable(prof) {
+    arch_name_length = std::min(arch.size(), kMaxArchNameLength);
+    memcpy(arch_name, arch.data(), arch_name_length);
+  }
+};
diff --git a/adb/libs/adbconnection/include/adbconnection/server.h b/adb/libs/adbconnection/include/adbconnection/server.h
index 57ca6cd..b1059ba 100644
--- a/adb/libs/adbconnection/include/adbconnection/server.h
+++ b/adb/libs/adbconnection/include/adbconnection/server.h
@@ -20,7 +20,7 @@
 
 #include <android-base/unique_fd.h>
 
-extern "C" {
+#include "adbconnection/process_info.h"
 
-void adbconnection_listen(void (*callback)(int fd, pid_t pid));
-}
+// Note this is NOT an apex interface as it's linked only into adbd.
+void adbconnection_listen(void (*callback)(int fd, ProcessInfo process));
diff --git a/adb/pairing_auth/Android.bp b/adb/pairing_auth/Android.bp
index 0850047..a43f4d0 100644
--- a/adb/pairing_auth/Android.bp
+++ b/adb/pairing_auth/Android.bp
@@ -47,7 +47,7 @@
     use_version_lib: false,
 
     host_supported: true,
-    recovery_available: true,
+    recovery_available: false,
 
     stl: "libc++_static",
 
diff --git a/adb/pairing_connection/Android.bp b/adb/pairing_connection/Android.bp
index c053854..bcde7b1 100644
--- a/adb/pairing_connection/Android.bp
+++ b/adb/pairing_connection/Android.bp
@@ -52,7 +52,7 @@
     stl: "libc++_static",
 
     host_supported: true,
-    recovery_available: true,
+    recovery_available: false,
 
     static_libs: [
         "libbase",
@@ -131,7 +131,7 @@
     ],
 
     host_supported: true,
-    recovery_available: true,
+    recovery_available: false,
 
     stl: "libc++_static",
 
diff --git a/adb/pairing_connection/tests/pairing_connection_test.cpp b/adb/pairing_connection/tests/pairing_connection_test.cpp
index b6e09f1..86b66aa 100644
--- a/adb/pairing_connection/tests/pairing_connection_test.cpp
+++ b/adb/pairing_connection/tests/pairing_connection_test.cpp
@@ -440,7 +440,7 @@
     EXPECT_FALSE(*(server_waiter.is_valid_));
 }
 
-TEST_F(AdbPairingConnectionTest, MultipleClientsOnePass) {
+TEST_F(AdbPairingConnectionTest, DISABLED_MultipleClientsOnePass) {
     // Send multiple clients with bad passwords, but send the last one with the
     // correct password.
     std::vector<uint8_t> pswd{0x01, 0x03, 0x05, 0x07};
diff --git a/adb/proto/Android.bp b/adb/proto/Android.bp
index a7e5d9c..fe828a0 100644
--- a/adb/proto/Android.bp
+++ b/adb/proto/Android.bp
@@ -68,3 +68,61 @@
         "//apex_available:platform",
     ],
 }
+
+cc_defaults {
+    name: "libapp_processes_protos_defaults",
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Wthread-safety",
+        "-Werror",
+    ],
+
+    compile_multilib: "both",
+
+    srcs: [
+        "app_processes.proto",
+    ],
+    target: {
+        windows: {
+            compile_multilib: "first",
+            enabled: true,
+        },
+    },
+
+    visibility: [
+        "//system/core/adb:__subpackages__",
+    ],
+
+    stl: "libc++_static",
+
+    apex_available: [
+        "com.android.adbd",
+        "test_com.android.adbd",
+    ],
+}
+
+cc_library {
+    name: "libapp_processes_protos_lite",
+    defaults: ["libapp_processes_protos_defaults"],
+
+    apex_available: ["//apex_available:platform"],
+
+    proto: {
+        export_proto_headers: true,
+        type: "lite",
+    },
+
+    host_supported: true,
+    recovery_available: true,
+}
+
+cc_library_host_static {
+    name: "libapp_processes_protos_full",
+    defaults: ["libapp_processes_protos_defaults"],
+
+    proto: {
+        export_proto_headers: true,
+        type: "full",
+    },
+}
diff --git a/adb/proto/app_processes.proto b/adb/proto/app_processes.proto
new file mode 100644
index 0000000..1183645
--- /dev/null
+++ b/adb/proto/app_processes.proto
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+syntax = "proto3";
+
+option java_package = "com.android.server.adb.protos";
+option java_outer_classname = "AppProcessesProto";
+
+package adb.proto;
+
+message ProcessEntry {
+    int64 pid = 1;
+    bool debuggable = 2;
+    bool profileable = 3;
+    string architecture = 4;
+}
+
+message AppProcesses {
+  repeated ProcessEntry process = 1;
+}
diff --git a/adb/test_adb.py b/adb/test_adb.py
index 3d6de26..c872fb0 100755
--- a/adb/test_adb.py
+++ b/adb/test_adb.py
@@ -33,6 +33,11 @@
 import unittest
 import warnings
 
+def find_open_port():
+    # Find an open port.
+    with socket.socket() as s:
+        s.bind(("localhost", 0))
+        return s.getsockname()[1]
 
 @contextlib.contextmanager
 def fake_adbd(protocol=socket.AF_INET, port=0):
@@ -126,10 +131,7 @@
     This creates an ADB server and returns the port it's listening on.
     """
 
-    port = 5038
-    # Kill any existing server on this non-default port.
-    subprocess.check_output(["adb", "-P", str(port), "kill-server"],
-                            stderr=subprocess.STDOUT)
+    port = find_open_port()
     read_pipe, write_pipe = os.pipe()
 
     if sys.platform == "win32":
@@ -224,10 +226,7 @@
         # adb server, this also tests whether multiple instances of the adb
         # server conflict on adb.log.
 
-        port = 5038
-        # Kill any existing server on this non-default port.
-        subprocess.check_output(["adb", "-P", str(port), "kill-server"],
-                                stderr=subprocess.STDOUT)
+        port = find_open_port()
 
         try:
             # We get warnings for unclosed files for the subprocess's pipes,
@@ -289,12 +288,8 @@
         """
         Tests that the server can start up on ::1 and that it's accessible
         """
-        server_port = 5037
-        # Kill any existing server on this non-default port.
-        subprocess.check_output(
-            ["adb", "-P", str(server_port), "kill-server"],
-            stderr=subprocess.STDOUT,
-        )
+
+        server_port = find_open_port()
         try:
             subprocess.check_output(
                 ["adb", "-L", "tcp:[::1]:{}".format(server_port), "server"],
diff --git a/adb/tls/Android.bp b/adb/tls/Android.bp
index 49833ff..f2837e1 100644
--- a/adb/tls/Android.bp
+++ b/adb/tls/Android.bp
@@ -42,12 +42,8 @@
         "//system/core/adb:__subpackages__",
     ],
 
-    stl: "libc++_static",
-
-    static_libs: [
-        "libbase",
-    ],
     shared_libs: [
+        "libbase",
         "libcrypto",
         "liblog",
         "libssl",
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 8b3461a..447a8fe 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -81,6 +81,7 @@
 const char* const kFeatureFixedPushSymlinkTimestamp = "fixed_push_symlink_timestamp";
 const char* const kFeatureAbbExec = "abb_exec";
 const char* const kFeatureRemountShell = "remount_shell";
+const char* const kFeatureTrackApp = "track_app";
 
 namespace {
 
@@ -1175,6 +1176,7 @@
             kFeatureFixedPushSymlinkTimestamp,
             kFeatureAbbExec,
             kFeatureRemountShell,
+            kFeatureTrackApp,
             // Increment ADB_SERVER_VERSION when adding a feature that adbd needs
             // to know about. Otherwise, the client can be stuck running an old
             // version of the server even after upgrading their copy of adb.
diff --git a/adb/transport.h b/adb/transport.h
index 8a0f62a..a62349e 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -82,6 +82,8 @@
 // adbd properly updates symlink timestamps on push.
 extern const char* const kFeatureFixedPushSymlinkTimestamp;
 extern const char* const kFeatureRemountShell;
+// adbd supports `track-app` service reporting debuggable/profileable apps.
+extern const char* const kFeatureTrackApp;
 
 TransportId NextTransportId();
 
diff --git a/base/include/android-base/properties.h b/base/include/android-base/properties.h
index 31823df..49f1f31 100644
--- a/base/include/android-base/properties.h
+++ b/base/include/android-base/properties.h
@@ -20,8 +20,11 @@
 
 #include <chrono>
 #include <limits>
+#include <optional>
 #include <string>
 
+struct prop_info;
+
 namespace android {
 namespace base {
 
@@ -67,5 +70,32 @@
                                                          std::chrono::milliseconds::max());
 #endif
 
+#if defined(__BIONIC__) && __cplusplus >= 201703L
+// Cached system property lookup. For code that needs to read the same property multiple times,
+// this class helps optimize those lookups.
+class CachedProperty {
+ public:
+  explicit CachedProperty(const char* property_name);
+
+  // Returns the current value of the underlying system property as cheaply as possible.
+  // The returned pointer is valid until the next call to Get. Because most callers are going
+  // to want to parse the string returned here and cached that as well, this function performs
+  // no locking, and is completely thread unsafe. It is the caller's responsibility to provide a
+  // lock for thread-safety.
+  //
+  // Note: *changed can be set to true even if the contents of the property remain the same.
+  const char* Get(bool* changed = nullptr);
+
+ private:
+  std::string property_name_;
+  const prop_info* prop_info_;
+  std::optional<uint32_t> cached_area_serial_;
+  std::optional<uint32_t> cached_property_serial_;
+  char cached_value_[92];
+  bool is_read_only_;
+  const char* read_only_property_;
+};
+#endif
+
 } // namespace base
 } // namespace android
diff --git a/base/logging.cpp b/base/logging.cpp
index f42b996..9360a56 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -447,7 +447,7 @@
     // See the comment in SetLogger().
     static std::atomic<AbortFunction*> abort_function(nullptr);
     auto* old_abort_function = abort_function.exchange(new AbortFunction(aborter));
-    __android_log_set_aborter([](const char* abort_message) {
+    liblog_functions->__android_log_set_aborter([](const char* abort_message) {
       auto& function = *abort_function.load(std::memory_order_acquire);
       function(abort_message);
     });
@@ -578,7 +578,7 @@
   if (liblog_functions) {
     __android_logger_data logger_data = {
         sizeof(__android_logger_data), LOG_ID_DEFAULT, priority, tag, file, line};
-    __android_log_write_logger_data(&logger_data, message);
+    liblog_functions->__android_log_write_logger_data(&logger_data, message);
   } else {
     if (tag == nullptr) {
       std::lock_guard<std::recursive_mutex> lock(TagLock());
diff --git a/base/properties.cpp b/base/properties.cpp
index 4731bf2..35e41a8 100644
--- a/base/properties.cpp
+++ b/base/properties.cpp
@@ -30,6 +30,7 @@
 
 #include <android-base/parsebool.h>
 #include <android-base/parseint.h>
+#include <android-base/strings.h>
 
 namespace android {
 namespace base {
@@ -195,6 +196,62 @@
   return (WaitForPropertyCreation(key, relative_timeout, start_time) != nullptr);
 }
 
+CachedProperty::CachedProperty(const char* property_name)
+    : property_name_(property_name),
+      prop_info_(nullptr),
+      cached_area_serial_(0),
+      cached_property_serial_(0),
+      is_read_only_(android::base::StartsWith(property_name, "ro.")),
+      read_only_property_(nullptr) {
+  static_assert(sizeof(cached_value_) == PROP_VALUE_MAX);
+}
+
+const char* CachedProperty::Get(bool* changed) {
+  std::optional<uint32_t> initial_property_serial_ = cached_property_serial_;
+
+  // Do we have a `struct prop_info` yet?
+  if (prop_info_ == nullptr) {
+    // `__system_property_find` is expensive, so only retry if a property
+    // has been created since last time we checked.
+    uint32_t property_area_serial = __system_property_area_serial();
+    if (property_area_serial != cached_area_serial_) {
+      prop_info_ = __system_property_find(property_name_.c_str());
+      cached_area_serial_ = property_area_serial;
+    }
+  }
+
+  if (prop_info_ != nullptr) {
+    // Only bother re-reading the property if it's actually changed since last time.
+    uint32_t property_serial = __system_property_serial(prop_info_);
+    if (property_serial != cached_property_serial_) {
+      __system_property_read_callback(
+          prop_info_,
+          [](void* data, const char*, const char* value, uint32_t serial) {
+            CachedProperty* instance = reinterpret_cast<CachedProperty*>(data);
+            instance->cached_property_serial_ = serial;
+            // Read only properties can be larger than PROP_VALUE_MAX, but also never change value
+            // or location, thus we return the pointer from the shared memory directly.
+            if (instance->is_read_only_) {
+              instance->read_only_property_ = value;
+            } else {
+              strlcpy(instance->cached_value_, value, PROP_VALUE_MAX);
+            }
+          },
+          this);
+    }
+  }
+
+  if (changed) {
+    *changed = cached_property_serial_ != initial_property_serial_;
+  }
+
+  if (is_read_only_) {
+    return read_only_property_;
+  } else {
+    return cached_value_;
+  }
+}
+
 #endif
 
 }  // namespace base
diff --git a/base/properties_test.cpp b/base/properties_test.cpp
index e7d4880..c30c41e 100644
--- a/base/properties_test.cpp
+++ b/base/properties_test.cpp
@@ -230,3 +230,28 @@
   GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
 #endif
 }
+
+TEST(properties, CachedProperty) {
+#if defined(__BIONIC__)
+  android::base::CachedProperty cached_property("debug.libbase.CachedProperty_test");
+  bool changed;
+  cached_property.Get(&changed);
+
+  android::base::SetProperty("debug.libbase.CachedProperty_test", "foo");
+  ASSERT_STREQ("foo", cached_property.Get(&changed));
+  ASSERT_TRUE(changed);
+
+  ASSERT_STREQ("foo", cached_property.Get(&changed));
+  ASSERT_FALSE(changed);
+
+  android::base::SetProperty("debug.libbase.CachedProperty_test", "bar");
+  ASSERT_STREQ("bar", cached_property.Get(&changed));
+  ASSERT_TRUE(changed);
+
+  ASSERT_STREQ("bar", cached_property.Get(&changed));
+  ASSERT_FALSE(changed);
+
+#else
+  GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
+#endif
+}
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 3e99880..6a38145 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -254,9 +254,7 @@
 }
 
 static void ReadCrashInfo(unique_fd& fd, siginfo_t* siginfo,
-                          std::unique_ptr<unwindstack::Regs>* regs, uintptr_t* abort_msg_address,
-                          uintptr_t* fdsan_table_address, uintptr_t* gwp_asan_state,
-                          uintptr_t* gwp_asan_metadata) {
+                          std::unique_ptr<unwindstack::Regs>* regs, ProcessInfo* process_info) {
   std::aligned_storage<sizeof(CrashInfo) + 1, alignof(CrashInfo)>::type buf;
   CrashInfo* crash_info = reinterpret_cast<CrashInfo*>(&buf);
   ssize_t rc = TEMP_FAILURE_RETRY(read(fd.get(), &buf, sizeof(buf)));
@@ -288,19 +286,16 @@
     }
   }
 
-  *fdsan_table_address = 0;
-  *gwp_asan_state = 0;
-  *gwp_asan_metadata = 0;
   switch (crash_info->header.version) {
     case 3:
-      *gwp_asan_state = crash_info->data.v3.gwp_asan_state;
-      *gwp_asan_metadata = crash_info->data.v3.gwp_asan_metadata;
+      process_info->gwp_asan_state = crash_info->data.v3.gwp_asan_state;
+      process_info->gwp_asan_metadata = crash_info->data.v3.gwp_asan_metadata;
       FALLTHROUGH_INTENDED;
     case 2:
-      *fdsan_table_address = crash_info->data.v2.fdsan_table_address;
+      process_info->fdsan_table_address = crash_info->data.v2.fdsan_table_address;
       FALLTHROUGH_INTENDED;
     case 1:
-      *abort_msg_address = crash_info->data.v1.abort_msg_address;
+      process_info->abort_msg_address = crash_info->data.v1.abort_msg_address;
       *siginfo = crash_info->data.v1.siginfo;
       regs->reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(),
                                                         &crash_info->data.v1.ucontext));
@@ -425,10 +420,7 @@
   ATRACE_NAME("after reparent");
   pid_t pseudothread_tid;
   DebuggerdDumpType dump_type;
-  uintptr_t abort_msg_address = 0;
-  uintptr_t fdsan_table_address = 0;
-  uintptr_t gwp_asan_state = 0;
-  uintptr_t gwp_asan_metadata = 0;
+  ProcessInfo process_info;
 
   Initialize(argv);
   ParseArgs(argc, argv, &pseudothread_tid, &dump_type);
@@ -489,8 +481,7 @@
 
       if (thread == g_target_thread) {
         // Read the thread's registers along with the rest of the crash info out of the pipe.
-        ReadCrashInfo(input_pipe, &siginfo, &info.registers, &abort_msg_address,
-                      &fdsan_table_address, &gwp_asan_state, &gwp_asan_metadata);
+        ReadCrashInfo(input_pipe, &siginfo, &info.registers, &process_info);
         info.siginfo = &siginfo;
         info.signo = info.siginfo->si_signo;
       } else {
@@ -599,14 +590,14 @@
   } else {
     {
       ATRACE_NAME("fdsan table dump");
-      populate_fdsan_table(&open_files, unwinder.GetProcessMemory(), fdsan_table_address);
+      populate_fdsan_table(&open_files, unwinder.GetProcessMemory(),
+                           process_info.fdsan_table_address);
     }
 
     {
       ATRACE_NAME("engrave_tombstone");
-      engrave_tombstone(std::move(g_output_fd), &unwinder, thread_info, g_target_thread,
-                        abort_msg_address, &open_files, &amfd_data, gwp_asan_state,
-                        gwp_asan_metadata);
+      engrave_tombstone(std::move(g_output_fd), &unwinder, thread_info, g_target_thread, process_info,
+                        &open_files, &amfd_data);
     }
   }
 
diff --git a/debuggerd/include/debuggerd/handler.h b/debuggerd/include/debuggerd/handler.h
index 4f24360..665d24a 100644
--- a/debuggerd/include/debuggerd/handler.h
+++ b/debuggerd/include/debuggerd/handler.h
@@ -19,7 +19,9 @@
 #include <bionic/reserved_signals.h>
 #include <signal.h>
 #include <stdint.h>
+#include <string.h>
 #include <sys/cdefs.h>
+#include <sys/system_properties.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
@@ -50,16 +52,21 @@
 #define DEBUGGER_SIGNAL BIONIC_SIGNAL_DEBUGGER
 
 static void __attribute__((__unused__)) debuggerd_register_handlers(struct sigaction* action) {
-  sigaction(SIGABRT, action, nullptr);
-  sigaction(SIGBUS, action, nullptr);
-  sigaction(SIGFPE, action, nullptr);
-  sigaction(SIGILL, action, nullptr);
-  sigaction(SIGSEGV, action, nullptr);
-#if defined(SIGSTKFLT)
-  sigaction(SIGSTKFLT, action, nullptr);
-#endif
-  sigaction(SIGSYS, action, nullptr);
-  sigaction(SIGTRAP, action, nullptr);
+  char value[PROP_VALUE_MAX] = "";
+  bool enabled =
+      !(__system_property_get("ro.debuggable", value) > 0 && !strcmp(value, "1") &&
+        __system_property_get("debug.debuggerd.disable", value) > 0 && !strcmp(value, "1"));
+  if (enabled) {
+    sigaction(SIGABRT, action, nullptr);
+    sigaction(SIGBUS, action, nullptr);
+    sigaction(SIGFPE, action, nullptr);
+    sigaction(SIGILL, action, nullptr);
+    sigaction(SIGSEGV, action, nullptr);
+    sigaction(SIGSTKFLT, action, nullptr);
+    sigaction(SIGSYS, action, nullptr);
+    sigaction(SIGTRAP, action, nullptr);
+  }
+
   sigaction(BIONIC_SIGNAL_DEBUGGER, action, nullptr);
 }
 
diff --git a/debuggerd/libdebuggerd/gwp_asan.cpp b/debuggerd/libdebuggerd/gwp_asan.cpp
index 53df783..fe3a173 100644
--- a/debuggerd/libdebuggerd/gwp_asan.cpp
+++ b/debuggerd/libdebuggerd/gwp_asan.cpp
@@ -63,12 +63,11 @@
 }
 
 GwpAsanCrashData::GwpAsanCrashData(unwindstack::Memory* process_memory,
-                                   uintptr_t gwp_asan_state_ptr, uintptr_t gwp_asan_metadata_ptr,
-                                   const ThreadInfo& thread_info) {
-  if (!process_memory || !gwp_asan_metadata_ptr || !gwp_asan_state_ptr) return;
+                                   const ProcessInfo& process_info, const ThreadInfo& thread_info) {
+  if (!process_memory || !process_info.gwp_asan_metadata || !process_info.gwp_asan_state) return;
   // Extract the GWP-ASan regions from the dead process.
-  if (!retrieve_gwp_asan_state(process_memory, gwp_asan_state_ptr, &state_)) return;
-  metadata_.reset(retrieve_gwp_asan_metadata(process_memory, state_, gwp_asan_metadata_ptr));
+  if (!retrieve_gwp_asan_state(process_memory, process_info.gwp_asan_state, &state_)) return;
+  metadata_.reset(retrieve_gwp_asan_metadata(process_memory, state_, process_info.gwp_asan_metadata));
   if (!metadata_.get()) return;
 
   // Get the external crash address from the thread info.
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/gwp_asan.h b/debuggerd/libdebuggerd/include/libdebuggerd/gwp_asan.h
index aef4c62..6c88733 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/gwp_asan.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/gwp_asan.h
@@ -38,8 +38,8 @@
   // still be responsible, as it terminates when it detects an internal error
   // (double free, invalid free). In these cases, we will retrieve the fault
   // address from the GWP-ASan allocator's state.
-  GwpAsanCrashData(unwindstack::Memory* process_memory, uintptr_t gwp_asan_state_ptr,
-                   uintptr_t gwp_asan_metadata_ptr, const ThreadInfo& thread_info);
+  GwpAsanCrashData(unwindstack::Memory* process_memory, const ProcessInfo& process_info,
+                   const ThreadInfo& thread_info);
 
   // Is GWP-ASan responsible for this crash.
   bool CrashIsMine() const;
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h b/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
index 291d994..3ff7d62 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
@@ -44,18 +44,13 @@
 int open_tombstone(std::string* path);
 
 /* Creates a tombstone file and writes the crash dump to it. */
-void engrave_tombstone(int tombstone_fd, unwindstack::Unwinder* unwinder,
-                       const OpenFilesList* open_files, pid_t pid, pid_t tid,
-                       const std::string& process_name, const std::map<pid_t, std::string>& threads,
-                       uint64_t abort_msg_address, std::string* amfd_data);
+void engrave_tombstone(android::base::unique_fd output_fd, unwindstack::Unwinder* unwinder,
+                       const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread,
+                       const ProcessInfo& process_info, OpenFilesList* open_files,
+                       std::string* amfd_data);
 
 void engrave_tombstone_ucontext(int tombstone_fd, uint64_t abort_msg_address, siginfo_t* siginfo,
                                 ucontext_t* ucontext);
 
-void engrave_tombstone(android::base::unique_fd output_fd, unwindstack::Unwinder* unwinder,
-                       const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread,
-                       uint64_t abort_msg_address, OpenFilesList* open_files,
-                       std::string* amfd_data, uintptr_t gwp_asan_state,
-                       uintptr_t gwp_asan_metadata);
 
 #endif  // _DEBUGGERD_TOMBSTONE_H
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/types.h b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
index eb4b1b8..4f681c2 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/types.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
@@ -35,3 +35,10 @@
   int signo = 0;
   siginfo_t* siginfo = nullptr;
 };
+
+struct ProcessInfo {
+  uintptr_t abort_msg_address = 0;
+  uintptr_t fdsan_table_address = 0;
+  uintptr_t gwp_asan_state = 0;
+  uintptr_t gwp_asan_metadata = 0;
+};
diff --git a/debuggerd/libdebuggerd/test/tombstone_test.cpp b/debuggerd/libdebuggerd/test/tombstone_test.cpp
index eed95bc..aec8c60 100644
--- a/debuggerd/libdebuggerd/test/tombstone_test.cpp
+++ b/debuggerd/libdebuggerd/test/tombstone_test.cpp
@@ -371,7 +371,7 @@
   GwpAsanCrashDataTest(
       gwp_asan::Error error,
       const gwp_asan::AllocationMetadata *responsible_allocation) :
-      GwpAsanCrashData(nullptr, 0u, 0u, ThreadInfo{}) {
+      GwpAsanCrashData(nullptr, ProcessInfo{}, ThreadInfo{}) {
     is_gwp_asan_responsible_ = true;
     error_ = error;
     responsible_allocation_ = responsible_allocation;
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index fd52e81..b3f059c 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -376,8 +376,7 @@
 }
 
 static bool dump_thread(log_t* log, unwindstack::Unwinder* unwinder, const ThreadInfo& thread_info,
-                        uint64_t abort_msg_address, bool primary_thread,
-                        const GwpAsanCrashData& gwp_asan_crash_data) {
+                        const ProcessInfo& process_info, bool primary_thread) {
   log->current_tid = thread_info.tid;
   if (!primary_thread) {
     _LOG(log, logtype::THREAD, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
@@ -388,15 +387,21 @@
     dump_signal_info(log, thread_info, unwinder->GetProcessMemory().get());
   }
 
-  if (primary_thread && gwp_asan_crash_data.CrashIsMine()) {
-    gwp_asan_crash_data.DumpCause(log);
+  std::unique_ptr<GwpAsanCrashData> gwp_asan_crash_data;
+  if (primary_thread) {
+    gwp_asan_crash_data = std::make_unique<GwpAsanCrashData>(unwinder->GetProcessMemory().get(),
+                                                             process_info, thread_info);
+  }
+
+  if (primary_thread && gwp_asan_crash_data->CrashIsMine()) {
+    gwp_asan_crash_data->DumpCause(log);
   } else if (thread_info.siginfo) {
     dump_probable_cause(log, thread_info.siginfo, unwinder->GetMaps(),
                         thread_info.registers.get());
   }
 
   if (primary_thread) {
-    dump_abort_message(log, unwinder->GetProcessMemory().get(), abort_msg_address);
+    dump_abort_message(log, unwinder->GetProcessMemory().get(), process_info.abort_msg_address);
   }
 
   dump_registers(log, thread_info.registers.get());
@@ -413,12 +418,12 @@
   }
 
   if (primary_thread) {
-    if (gwp_asan_crash_data.HasDeallocationTrace()) {
-      gwp_asan_crash_data.DumpDeallocationTrace(log, unwinder);
+    if (gwp_asan_crash_data->HasDeallocationTrace()) {
+      gwp_asan_crash_data->DumpDeallocationTrace(log, unwinder);
     }
 
-    if (gwp_asan_crash_data.HasAllocationTrace()) {
-      gwp_asan_crash_data.DumpAllocationTrace(log, unwinder);
+    if (gwp_asan_crash_data->HasAllocationTrace()) {
+      gwp_asan_crash_data->DumpAllocationTrace(log, unwinder);
     }
 
     unwindstack::Maps* maps = unwinder->GetMaps();
@@ -601,15 +606,16 @@
     LOG(FATAL) << "Failed to init unwinder object.";
   }
 
-  engrave_tombstone(unique_fd(dup(tombstone_fd)), &unwinder, threads, tid, abort_msg_address,
-                    nullptr, nullptr, 0u, 0u);
+  ProcessInfo process_info;
+  process_info.abort_msg_address = abort_msg_address;
+  engrave_tombstone(unique_fd(dup(tombstone_fd)), &unwinder, threads, tid, process_info, nullptr,
+                    nullptr);
 }
 
 void engrave_tombstone(unique_fd output_fd, unwindstack::Unwinder* unwinder,
                        const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
-                       uint64_t abort_msg_address, OpenFilesList* open_files,
-                       std::string* amfd_data, uintptr_t gwp_asan_state_ptr,
-                       uintptr_t gwp_asan_metadata_ptr) {
+                       const ProcessInfo& process_info, OpenFilesList* open_files,
+                       std::string* amfd_data) {
   // don't copy log messages to tombstone unless this is a dev device
   bool want_logs = android::base::GetBoolProperty("ro.debuggable", false);
 
@@ -628,12 +634,7 @@
     LOG(FATAL) << "failed to find target thread";
   }
 
-  GwpAsanCrashData gwp_asan_crash_data(unwinder->GetProcessMemory().get(),
-                                       gwp_asan_state_ptr,
-                                       gwp_asan_metadata_ptr, it->second);
-
-  dump_thread(&log, unwinder, it->second, abort_msg_address, true,
-              gwp_asan_crash_data);
+  dump_thread(&log, unwinder, it->second, process_info, true);
 
   if (want_logs) {
     dump_logs(&log, it->second.pid, 50);
@@ -644,7 +645,7 @@
       continue;
     }
 
-    dump_thread(&log, unwinder, thread_info, 0, false, gwp_asan_crash_data);
+    dump_thread(&log, unwinder, thread_info, process_info, false);
   }
 
   if (open_files) {
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index 2c9dec9..ca120c6 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -261,7 +261,7 @@
     }
 
     // If the slot is not changing, do nothing.
-    if (slot == boot_control_hal->getCurrentSlot()) {
+    if (args[1] == device->GetCurrentSlot()) {
         return device->WriteOkay("");
     }
 
diff --git a/fs_mgr/TEST_MAPPING b/fs_mgr/TEST_MAPPING
index 705d4e3..676f446 100644
--- a/fs_mgr/TEST_MAPPING
+++ b/fs_mgr/TEST_MAPPING
@@ -13,7 +13,7 @@
       "name": "fiemap_writer_test"
     },
     {
-      "name": "vts_libsnapshot_test_presubmit"
+      "name": "vts_libsnapshot_test"
     }
   ]
 }
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index bd35815..0089989 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -96,7 +96,9 @@
 
 using android::base::Basename;
 using android::base::GetBoolProperty;
+using android::base::Readlink;
 using android::base::Realpath;
+using android::base::SetProperty;
 using android::base::StartsWith;
 using android::base::Timer;
 using android::base::unique_fd;
@@ -178,6 +180,7 @@
         return;
     }
 
+    Timer t;
     /* Check for the types of filesystems we know how to check */
     if (is_extfs(fs_type)) {
         /*
@@ -253,15 +256,19 @@
             }
         }
     } else if (is_f2fs(fs_type)) {
-        const char* f2fs_fsck_argv[] = {F2FS_FSCK_BIN, "-a", blk_device.c_str()};
-        const char* f2fs_fsck_forced_argv[] = {F2FS_FSCK_BIN, "-f", blk_device.c_str()};
+        const char* f2fs_fsck_argv[] = {F2FS_FSCK_BIN,     "-a", "-c", "10000", "--debug-cache",
+                                        blk_device.c_str()};
+        const char* f2fs_fsck_forced_argv[] = {
+                F2FS_FSCK_BIN, "-f", "-c", "10000", "--debug-cache", blk_device.c_str()};
 
         if (should_force_check(*fs_stat)) {
-            LINFO << "Running " << F2FS_FSCK_BIN << " -f " << realpath(blk_device);
+            LINFO << "Running " << F2FS_FSCK_BIN << " -f -c 10000 --debug-cache"
+                  << realpath(blk_device);
             ret = logwrap_fork_execvp(ARRAY_SIZE(f2fs_fsck_forced_argv), f2fs_fsck_forced_argv,
                                       &status, false, LOG_KLOG | LOG_FILE, false, FSCK_LOG_FILE);
         } else {
-            LINFO << "Running " << F2FS_FSCK_BIN << " -a " << realpath(blk_device);
+            LINFO << "Running " << F2FS_FSCK_BIN << " -a -c 10000 --debug-cache"
+                  << realpath(blk_device);
             ret = logwrap_fork_execvp(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv, &status, false,
                                       LOG_KLOG | LOG_FILE, false, FSCK_LOG_FILE);
         }
@@ -270,7 +277,8 @@
             LERROR << "Failed trying to run " << F2FS_FSCK_BIN;
         }
     }
-
+    android::base::SetProperty("ro.boottime.init.fsck." + Basename(target),
+                               std::to_string(t.duration().count()));
     return;
 }
 
@@ -512,8 +520,7 @@
 // Enable casefold if needed.
 static void tune_casefold(const std::string& blk_device, const struct ext4_super_block* sb,
                           int* fs_stat) {
-    bool has_casefold =
-            (sb->s_feature_ro_compat & cpu_to_le32(EXT4_FEATURE_INCOMPAT_CASEFOLD)) != 0;
+    bool has_casefold = (sb->s_feature_incompat & cpu_to_le32(EXT4_FEATURE_INCOMPAT_CASEFOLD)) != 0;
     bool wants_casefold = android::base::GetBoolProperty("ro.emulated_storage.casefold", false);
 
     if (!wants_casefold || has_casefold) return;
@@ -1581,6 +1588,79 @@
     }
 }
 
+static std::string ResolveBlockDevice(const std::string& block_device) {
+    if (!StartsWith(block_device, "/dev/block/")) {
+        LWARNING << block_device << " is not a block device";
+        return block_device;
+    }
+    std::string name = block_device.substr(5);
+    if (!StartsWith(name, "block/dm-")) {
+        // Not a dm-device, but might be a symlink. Optimistically try to readlink.
+        std::string result;
+        if (Readlink(block_device, &result)) {
+            return result;
+        } else if (errno == EINVAL) {
+            // After all, it wasn't a symlink.
+            return block_device;
+        } else {
+            LERROR << "Failed to readlink " << block_device;
+            return "";
+        }
+    }
+    // It's a dm-device, let's find what's inside!
+    std::string sys_dir = "/sys/" + name;
+    while (true) {
+        std::string slaves_dir = sys_dir + "/slaves";
+        std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(slaves_dir.c_str()), closedir);
+        if (!dir) {
+            LERROR << "Failed to open " << slaves_dir;
+            return "";
+        }
+        std::string sub_device_name = "";
+        for (auto entry = readdir(dir.get()); entry; entry = readdir(dir.get())) {
+            if (entry->d_type != DT_LNK) continue;
+            if (!sub_device_name.empty()) {
+                LERROR << "Too many slaves in " << slaves_dir;
+                return "";
+            }
+            sub_device_name = entry->d_name;
+        }
+        if (sub_device_name.empty()) {
+            LERROR << "No slaves in " << slaves_dir;
+            return "";
+        }
+        if (!StartsWith(sub_device_name, "dm-")) {
+            // Not a dm-device! We can stop now.
+            return "/dev/block/" + sub_device_name;
+        }
+        // Still a dm-device, keep digging.
+        sys_dir = "/sys/block/" + sub_device_name;
+    }
+}
+
+FstabEntry* fs_mgr_get_mounted_entry_for_userdata(Fstab* fstab, const FstabEntry& mounted_entry) {
+    std::string resolved_block_device = ResolveBlockDevice(mounted_entry.blk_device);
+    if (resolved_block_device.empty()) {
+        return nullptr;
+    }
+    LINFO << "/data is mounted on " << resolved_block_device;
+    for (auto& entry : *fstab) {
+        if (entry.mount_point != "/data") {
+            continue;
+        }
+        std::string block_device;
+        if (!Readlink(entry.blk_device, &block_device)) {
+            LWARNING << "Failed to readlink " << entry.blk_device;
+            block_device = entry.blk_device;
+        }
+        if (block_device == resolved_block_device) {
+            return &entry;
+        }
+    }
+    LERROR << "Didn't find entry that was used to mount /data";
+    return nullptr;
+}
+
 // TODO(b/143970043): return different error codes based on which step failed.
 int fs_mgr_remount_userdata_into_checkpointing(Fstab* fstab) {
     Fstab proc_mounts;
@@ -1589,16 +1669,13 @@
         return -1;
     }
     std::string block_device;
-    if (auto entry = GetEntryForMountPoint(&proc_mounts, "/data"); entry != nullptr) {
-        // Note: we don't care about a userdata wrapper here, since it's safe
-        // to remount on top of the bow device instead, there will be no
-        // conflicts.
-        block_device = entry->blk_device;
-    } else {
+    auto mounted_entry = GetEntryForMountPoint(&proc_mounts, "/data");
+    if (mounted_entry == nullptr) {
         LERROR << "/data is not mounted";
         return -1;
     }
-    auto fstab_entry = GetMountedEntryForUserdata(fstab);
+    block_device = mounted_entry->blk_device;
+    auto fstab_entry = fs_mgr_get_mounted_entry_for_userdata(fstab, *mounted_entry);
     if (fstab_entry == nullptr) {
         LERROR << "Can't find /data in fstab";
         return -1;
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 65f710a..a836d3b 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -30,6 +30,7 @@
 
 #include <android-base/file.h>
 #include <android-base/parseint.h>
+#include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <libgsi/libgsi.h>
@@ -659,6 +660,21 @@
     }
 }
 
+void EnableMandatoryFlags(Fstab* fstab) {
+    // Devices launched in R and after should enable fs_verity on userdata. The flag causes tune2fs
+    // to enable the feature. A better alternative would be to enable on mkfs at the beginning.
+    if (android::base::GetIntProperty("ro.product.first_api_level", 0) >= 30) {
+        std::vector<FstabEntry*> data_entries = GetEntriesForMountPoint(fstab, "/data");
+        for (auto&& entry : data_entries) {
+            // Besides ext4, f2fs is also supported. But the image is already created with verity
+            // turned on when it was first introduced.
+            if (entry->fs_type == "ext4") {
+                entry->fs_mgr_flags.fs_verity = true;
+            }
+        }
+    }
+}
+
 bool ReadFstabFromFile(const std::string& path, Fstab* fstab) {
     auto fstab_file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
     if (!fstab_file) {
@@ -679,6 +695,7 @@
     }
 
     SkipMountingPartitions(fstab);
+    EnableMandatoryFlags(fstab);
 
     return true;
 }
@@ -802,89 +819,6 @@
     return entries;
 }
 
-static std::string ResolveBlockDevice(const std::string& block_device) {
-    if (!StartsWith(block_device, "/dev/block/")) {
-        LWARNING << block_device << " is not a block device";
-        return block_device;
-    }
-    std::string name = block_device.substr(5);
-    if (!StartsWith(name, "block/dm-")) {
-        // Not a dm-device, but might be a symlink. Optimistically try to readlink.
-        std::string result;
-        if (Readlink(block_device, &result)) {
-            return result;
-        } else if (errno == EINVAL) {
-            // After all, it wasn't a symlink.
-            return block_device;
-        } else {
-            LERROR << "Failed to readlink " << block_device;
-            return "";
-        }
-    }
-    // It's a dm-device, let's find what's inside!
-    std::string sys_dir = "/sys/" + name;
-    while (true) {
-        std::string slaves_dir = sys_dir + "/slaves";
-        std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(slaves_dir.c_str()), closedir);
-        if (!dir) {
-            LERROR << "Failed to open " << slaves_dir;
-            return "";
-        }
-        std::string sub_device_name = "";
-        for (auto entry = readdir(dir.get()); entry; entry = readdir(dir.get())) {
-            if (entry->d_type != DT_LNK) continue;
-            if (!sub_device_name.empty()) {
-                LERROR << "Too many slaves in " << slaves_dir;
-                return "";
-            }
-            sub_device_name = entry->d_name;
-        }
-        if (sub_device_name.empty()) {
-            LERROR << "No slaves in " << slaves_dir;
-            return "";
-        }
-        if (!StartsWith(sub_device_name, "dm-")) {
-            // Not a dm-device! We can stop now.
-            return "/dev/block/" + sub_device_name;
-        }
-        // Still a dm-device, keep digging.
-        sys_dir = "/sys/block/" + sub_device_name;
-    }
-}
-
-FstabEntry* GetMountedEntryForUserdata(Fstab* fstab) {
-    Fstab mounts;
-    if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
-        LERROR << "Failed to read /proc/mounts";
-        return nullptr;
-    }
-    auto mounted_entry = GetEntryForMountPoint(&mounts, "/data");
-    if (mounted_entry == nullptr) {
-        LWARNING << "/data is not mounted";
-        return nullptr;
-    }
-    std::string resolved_block_device = ResolveBlockDevice(mounted_entry->blk_device);
-    if (resolved_block_device.empty()) {
-        return nullptr;
-    }
-    LINFO << "/data is mounted on " << resolved_block_device;
-    for (auto& entry : *fstab) {
-        if (entry.mount_point != "/data") {
-            continue;
-        }
-        std::string block_device;
-        if (!Readlink(entry.blk_device, &block_device)) {
-            LWARNING << "Failed to readlink " << entry.blk_device;
-            block_device = entry.blk_device;
-        }
-        if (block_device == resolved_block_device) {
-            return &entry;
-        }
-    }
-    LERROR << "Didn't find entry that was used to mount /data";
-    return nullptr;
-}
-
 std::set<std::string> GetBootDevices() {
     // First check the kernel commandline, then try the device tree otherwise
     std::string dt_file_name = get_android_dt_dir() + "/boot_devices";
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 9bc38f9..3d556c9 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -107,6 +107,10 @@
 // it destroys verity devices from device mapper after the device is unmounted.
 int fs_mgr_umount_all(android::fs_mgr::Fstab* fstab);
 
+// Finds a entry in |fstab| that was used to mount a /data |mounted_entry| from
+// /proc/mounts.
+android::fs_mgr::FstabEntry* fs_mgr_get_mounted_entry_for_userdata(
+        android::fs_mgr::Fstab* fstab, const android::fs_mgr::FstabEntry& mounted_entry);
 int fs_mgr_remount_userdata_into_checkpointing(android::fs_mgr::Fstab* fstab);
 
 // Finds the dm_bow device on which this block device is stacked, or returns
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index 05e18fa..79d9402 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -104,7 +104,6 @@
 FstabEntry* GetEntryForMountPoint(Fstab* fstab, const std::string& path);
 // The Fstab can contain multiple entries for the same mount point with different configurations.
 std::vector<FstabEntry*> GetEntriesForMountPoint(Fstab* fstab, const std::string& path);
-FstabEntry* GetMountedEntryForUserdata(Fstab* fstab);
 
 // This method builds DSU fstab entries and transfer the fstab.
 //
diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp
index 6461788..29b1032 100644
--- a/fs_mgr/libdm/dm_target.cpp
+++ b/fs_mgr/libdm/dm_target.cpp
@@ -243,12 +243,10 @@
     return android::base::Join(argv, " ");
 }
 
-const std::string DmTargetDefaultKey::name_ = "default-key";
-
 bool DmTargetDefaultKey::IsLegacy(bool* result) {
     DeviceMapper& dm = DeviceMapper::Instance();
     DmTargetTypeInfo info;
-    if (!dm.GetTargetByName(name_, &info)) return false;
+    if (!dm.GetTargetByName(kName, &info)) return false;
     // dm-default-key was modified to be like dm-crypt with version 2
     *result = !info.IsAtLeast(2, 0, 0);
     return true;
diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h
index d2e50d3..050d0b6 100644
--- a/fs_mgr/libdm/include/libdm/dm_target.h
+++ b/fs_mgr/libdm/include/libdm/dm_target.h
@@ -287,7 +287,7 @@
           blockdev_(blockdev),
           start_sector_(start_sector) {}
 
-    std::string name() const override { return name_; }
+    std::string name() const override { return kName; }
     bool Valid() const override;
     std::string GetParameterString() const override;
     static bool IsLegacy(bool* result);
@@ -296,7 +296,8 @@
     void SetWrappedKeyV0() { is_hw_wrapped_ = true; }
 
   private:
-    static const std::string name_;
+    inline static const std::string kName = "default-key";
+
     std::string cipher_;
     std::string key_;
     std::string blockdev_;
diff --git a/fs_mgr/liblp/images.cpp b/fs_mgr/liblp/images.cpp
index e4d92ca..0b1e522 100644
--- a/fs_mgr/liblp/images.cpp
+++ b/fs_mgr/liblp/images.cpp
@@ -124,7 +124,7 @@
 }
 
 bool WriteToImageFile(const std::string& file, const LpMetadata& input) {
-    unique_fd fd(open(file.c_str(), O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC, 0644));
+    unique_fd fd(open(file.c_str(), O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC | O_BINARY, 0644));
     if (fd < 0) {
         PERROR << __PRETTY_FUNCTION__ << " open failed: " << file;
         return false;
@@ -184,7 +184,7 @@
 }
 
 bool ImageBuilder::Export(const std::string& file) {
-    unique_fd fd(open(file.c_str(), O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC, 0644));
+    unique_fd fd(open(file.c_str(), O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC | O_BINARY, 0644));
     if (fd < 0) {
         PERROR << "open failed: " << file;
         return false;
@@ -208,7 +208,7 @@
         std::string file_name = "super_" + name + ".img";
         std::string file_path = output_dir + "/" + file_name;
 
-        static const int kOpenFlags = O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC | O_NOFOLLOW;
+        static const int kOpenFlags = O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC | O_NOFOLLOW | O_BINARY;
         unique_fd fd(open(file_path.c_str(), kOpenFlags, 0644));
         if (fd < 0) {
             PERROR << "open failed: " << file_path;
@@ -443,7 +443,7 @@
 }
 
 int ImageBuilder::OpenImageFile(const std::string& file) {
-    android::base::unique_fd source_fd = GetControlFileOrOpen(file.c_str(), O_RDONLY | O_CLOEXEC);
+    unique_fd source_fd = GetControlFileOrOpen(file.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY);
     if (source_fd < 0) {
         PERROR << "open image file failed: " << file;
         return -1;
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index d274ba4..0a0a21d 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -208,21 +208,12 @@
     defaults: ["libsnapshot_test_defaults"],
 }
 
-cc_test {
-    name: "vts_libsnapshot_test_presubmit",
-    defaults: ["libsnapshot_test_defaults"],
-    cppflags: [
-        "-DSKIP_TEST_IN_PRESUBMIT",
-    ],
-}
-
 cc_binary {
     name: "snapshotctl",
     srcs: [
         "snapshotctl.cpp",
     ],
     static_libs: [
-        "libdm",
         "libfstab",
         "libsnapshot",
     ],
@@ -238,12 +229,10 @@
         "liblog",
         "liblp",
         "libprotobuf-cpp-lite",
+        "libstatslog",
         "libutils",
 
         // TODO(b/148818798): remove when parent bug is fixed.
         "libutilscallstack",
     ],
-    init_rc: [
-        "snapshotctl.rc",
-    ],
 }
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/return.h b/fs_mgr/libsnapshot/include/libsnapshot/return.h
index 1f132fa..dedc445 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/return.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/return.h
@@ -30,7 +30,6 @@
     enum class ErrorCode : int32_t {
         SUCCESS = static_cast<int32_t>(FiemapStatus::ErrorCode::SUCCESS),
         ERROR = static_cast<int32_t>(FiemapStatus::ErrorCode::ERROR),
-        NEEDS_REBOOT = ERROR + 1,
         NO_SPACE = static_cast<int32_t>(FiemapStatus::ErrorCode::NO_SPACE),
     };
     ErrorCode error_code() const { return error_code_; }
@@ -43,7 +42,6 @@
     static Return Ok() { return Return(ErrorCode::SUCCESS); }
     static Return Error() { return Return(ErrorCode::ERROR); }
     static Return NoSpace(uint64_t size) { return Return(ErrorCode::NO_SPACE, size); }
-    static Return NeedsReboot() { return Return(ErrorCode::NEEDS_REBOOT); }
     // Does not set required_size_ properly even when status.error_code() == NO_SPACE.
     explicit Return(const FiemapStatus& status)
         : error_code_(FromFiemapStatusErrorCode(status.error_code())), required_size_(0) {}
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index b440c71..81f616c 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -125,6 +125,9 @@
     // might be needed to perform first-stage mounts.
     static bool IsSnapshotManagerNeeded();
 
+    // Helper function for second stage init to restorecon on the rollback indicator.
+    static std::string GetGlobalRollbackIndicatorPath();
+
     // Begin an update. This must be called before creating any snapshots. It
     // will fail if GetUpdateState() != None.
     bool BeginUpdate();
@@ -140,7 +143,6 @@
     // Before calling this function, all snapshots must be mapped.
     bool FinishedSnapshotWrites();
 
-  private:
     // Initiate a merge on all snapshot devices. This should only be used after an
     // update has been marked successful after booting.
     bool InitiateMerge();
@@ -149,7 +151,11 @@
     // /data is mounted.
     //
     // If a merge is in progress, this function will block until the merge is
-    // completed. If a merge or update was cancelled, this will clean up any
+    // completed.
+    //    - Callback is called periodically during the merge. If callback()
+    //      returns false during the merge, ProcessUpdateState() will pause
+    //      and returns Merging.
+    // If a merge or update was cancelled, this will clean up any
     // update artifacts and return.
     //
     // Note that after calling this, GetUpdateState() may still return that a
@@ -169,9 +175,9 @@
     //
     // The optional callback allows the caller to periodically check the
     // progress with GetUpdateState().
-    UpdateState ProcessUpdateState(const std::function<void()>& callback = {});
+    UpdateState ProcessUpdateState(const std::function<bool()>& callback = {},
+                                   const std::function<bool()>& before_cancel = {});
 
-  public:
     // Initiate the merge if necessary, then wait for the merge to finish.
     // See InitiateMerge() and ProcessUpdateState() for details.
     // Returns:
@@ -179,16 +185,8 @@
     //   - Unverified if called on the source slot
     //   - MergeCompleted if merge is completed
     //   - other states indicating an error has occurred
-    UpdateState InitiateMergeAndWait(SnapshotMergeReport* report = nullptr);
-
-    // Wait for the merge if rebooted into the new slot. Does NOT initiate a
-    // merge. If the merge has not been initiated (but should be), wait.
-    // Returns:
-    //   - Return::Ok(): there is no merge or merge finishes
-    //   - Return::NeedsReboot(): merge finishes but need a reboot before
-    //     applying the next update.
-    //   - Return::Error(): other irrecoverable errors
-    Return WaitForMerge();
+    UpdateState InitiateMergeAndWait(SnapshotMergeReport* report = nullptr,
+                                     const std::function<bool()>& before_cancel = {});
 
     // Find the status of the current update, if any.
     //
@@ -375,14 +373,23 @@
 
     // Check for a cancelled or rolled back merge, returning true if such a
     // condition was detected and handled.
-    bool HandleCancelledUpdate(LockedFile* lock);
+    bool HandleCancelledUpdate(LockedFile* lock, const std::function<bool()>& before_cancel);
 
     // Helper for HandleCancelledUpdate. Assumes booting from new slot.
     bool AreAllSnapshotsCancelled(LockedFile* lock);
 
+    // Determine whether partition names in |snapshots| have been flashed and
+    // store result to |out|.
+    // Return true if values are successfully retrieved and false on error
+    // (e.g. super partition metadata cannot be read). When it returns true,
+    // |out| stores true for partitions that have been flashed and false for
+    // partitions that have not been flashed.
+    bool GetSnapshotFlashingStatus(LockedFile* lock, const std::vector<std::string>& snapshots,
+                                   std::map<std::string, bool>* out);
+
     // Remove artifacts created by the update process, such as snapshots, and
     // set the update state to None.
-    bool RemoveAllUpdateState(LockedFile* lock);
+    bool RemoveAllUpdateState(LockedFile* lock, const std::function<bool()>& prolog = {});
 
     // Interact with /metadata/ota.
     std::unique_ptr<LockedFile> OpenLock(int lock_flags);
@@ -437,8 +444,8 @@
     //   UpdateState::MergeCompleted
     //   UpdateState::MergeFailed
     //   UpdateState::MergeNeedsReboot
-    UpdateState CheckMergeState();
-    UpdateState CheckMergeState(LockedFile* lock);
+    UpdateState CheckMergeState(const std::function<bool()>& before_cancel);
+    UpdateState CheckMergeState(LockedFile* lock, const std::function<bool()>& before_cancel);
     UpdateState CheckTargetMergeState(LockedFile* lock, const std::string& name);
 
     // Interact with status files under /metadata/ota/snapshots.
@@ -513,6 +520,11 @@
 
     std::string ReadUpdateSourceSlotSuffix();
 
+    // Helper for RemoveAllSnapshots.
+    // Check whether |name| should be deleted as a snapshot name.
+    bool ShouldDeleteSnapshot(LockedFile* lock, const std::map<std::string, bool>& flashing_status,
+                              Slot current_slot, const std::string& name);
+
     std::string gsid_dir_;
     std::string metadata_dir_;
     std::unique_ptr<IDeviceInfo> device_;
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h
new file mode 100644
index 0000000..91dd34f
--- /dev/null
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h
@@ -0,0 +1,59 @@
+// Copyright (C) 2020 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.
+
+#pragma once
+
+#include <chrono>
+#include <memory>
+
+#include <android/snapshot/snapshot.pb.h>
+#include <libsnapshot/snapshot.h>
+
+namespace android {
+namespace snapshot {
+
+class SnapshotMergeStats {
+  public:
+    // Not thread safe.
+    static SnapshotMergeStats* GetInstance(SnapshotManager& manager);
+
+    // Called when merge starts or resumes.
+    bool Start();
+    void set_state(android::snapshot::UpdateState state);
+
+    // Called when merge ends. Properly clean up permanent storage.
+    class Result {
+      public:
+        virtual ~Result() {}
+        virtual const SnapshotMergeReport& report() const = 0;
+        // Time between successful Start() / Resume() to Finish().
+        virtual std::chrono::steady_clock::duration merge_time() const = 0;
+    };
+    std::unique_ptr<Result> Finish();
+
+  private:
+    bool ReadState();
+    bool WriteState();
+    bool DeleteState();
+    SnapshotMergeStats(const std::string& path);
+
+    std::string path_;
+    SnapshotMergeReport report_;
+    // Time of the last successful Start() / Resume() call.
+    std::chrono::time_point<std::chrono::steady_clock> start_time_;
+    bool running_{false};
+};
+
+}  // namespace snapshot
+}  // namespace android
diff --git a/fs_mgr/libsnapshot/return.cpp b/fs_mgr/libsnapshot/return.cpp
index 6559c12..cc64af5 100644
--- a/fs_mgr/libsnapshot/return.cpp
+++ b/fs_mgr/libsnapshot/return.cpp
@@ -24,8 +24,6 @@
     switch (error_code()) {
         case ErrorCode::ERROR:
             return "Error";
-        case ErrorCode::NEEDS_REBOOT:
-            return "Retry after reboot";
         case ErrorCode::SUCCESS:
             [[fallthrough]];
         case ErrorCode::NO_SPACE:
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 187f24c..0573c59 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -43,10 +43,10 @@
 #endif
 
 #include <android/snapshot/snapshot.pb.h>
+#include <libsnapshot/snapshot_stats.h>
 #include "device_info.h"
 #include "partition_cow_creator.h"
 #include "snapshot_metadata_updater.h"
-#include "snapshot_stats.h"
 #include "utility.h"
 
 namespace android {
@@ -81,6 +81,7 @@
 using namespace std::string_literals;
 
 static constexpr char kBootIndicatorPath[] = "/metadata/ota/snapshot-boot";
+static constexpr char kRollbackIndicatorPath[] = "/metadata/ota/rollback-indicator";
 static constexpr auto kUpdateStateCheckInterval = 2s;
 
 // Note: IImageManager is an incomplete type in the header, so the default
@@ -219,7 +220,12 @@
     return true;
 }
 
-bool SnapshotManager::RemoveAllUpdateState(LockedFile* lock) {
+bool SnapshotManager::RemoveAllUpdateState(LockedFile* lock, const std::function<bool()>& prolog) {
+    if (prolog && !prolog()) {
+        LOG(WARNING) << "Can't RemoveAllUpdateState: prolog failed.";
+        return false;
+    }
+
     LOG(INFO) << "Removing all update state.";
 
 #ifdef LIBSNAPSHOT_USE_CALLSTACK
@@ -789,9 +795,10 @@
 // Note that when a merge fails, we will *always* try again to complete the
 // merge each time the device boots. There is no harm in doing so, and if
 // the problem was transient, we might manage to get a new outcome.
-UpdateState SnapshotManager::ProcessUpdateState(const std::function<void()>& callback) {
+UpdateState SnapshotManager::ProcessUpdateState(const std::function<bool()>& callback,
+                                                const std::function<bool()>& before_cancel) {
     while (true) {
-        UpdateState state = CheckMergeState();
+        UpdateState state = CheckMergeState(before_cancel);
         if (state == UpdateState::MergeFailed) {
             AcknowledgeMergeFailure();
         }
@@ -801,8 +808,8 @@
             return state;
         }
 
-        if (callback) {
-            callback();
+        if (callback && !callback()) {
+            return state;
         }
 
         // This wait is not super time sensitive, so we have a relatively
@@ -811,24 +818,27 @@
     }
 }
 
-UpdateState SnapshotManager::CheckMergeState() {
+UpdateState SnapshotManager::CheckMergeState(const std::function<bool()>& before_cancel) {
     auto lock = LockExclusive();
     if (!lock) {
         return UpdateState::MergeFailed;
     }
 
-    UpdateState state = CheckMergeState(lock.get());
+    UpdateState state = CheckMergeState(lock.get(), before_cancel);
     if (state == UpdateState::MergeCompleted) {
         // Do this inside the same lock. Failures get acknowledged without the
         // lock, because flock() might have failed.
         AcknowledgeMergeSuccess(lock.get());
     } else if (state == UpdateState::Cancelled) {
-        RemoveAllUpdateState(lock.get());
+        if (!RemoveAllUpdateState(lock.get(), before_cancel)) {
+            return ReadSnapshotUpdateStatus(lock.get()).state();
+        }
     }
     return state;
 }
 
-UpdateState SnapshotManager::CheckMergeState(LockedFile* lock) {
+UpdateState SnapshotManager::CheckMergeState(LockedFile* lock,
+                                             const std::function<bool()>& before_cancel) {
     UpdateState state = ReadUpdateState(lock);
     switch (state) {
         case UpdateState::None:
@@ -849,7 +859,7 @@
             // This is an edge case. Normally cancelled updates are detected
             // via the merge poll below, but if we never started a merge, we
             // need to also check here.
-            if (HandleCancelledUpdate(lock)) {
+            if (HandleCancelledUpdate(lock, before_cancel)) {
                 return UpdateState::Cancelled;
             }
             return state;
@@ -1003,7 +1013,7 @@
 }
 
 std::string SnapshotManager::GetRollbackIndicatorPath() {
-    return metadata_dir_ + "/rollback-indicator";
+    return metadata_dir_ + "/" + android::base::Basename(kRollbackIndicatorPath);
 }
 
 void SnapshotManager::AcknowledgeMergeSuccess(LockedFile* lock) {
@@ -1169,7 +1179,8 @@
     return true;
 }
 
-bool SnapshotManager::HandleCancelledUpdate(LockedFile* lock) {
+bool SnapshotManager::HandleCancelledUpdate(LockedFile* lock,
+                                            const std::function<bool()>& before_cancel) {
     auto slot = GetCurrentSlot();
     if (slot == Slot::Unknown) {
         return false;
@@ -1177,15 +1188,30 @@
 
     // If all snapshots were reflashed, then cancel the entire update.
     if (AreAllSnapshotsCancelled(lock)) {
-        RemoveAllUpdateState(lock);
-        return true;
+        LOG(WARNING) << "Detected re-flashing, cancelling unverified update.";
+        return RemoveAllUpdateState(lock, before_cancel);
     }
 
-    // This unverified update might be rolled back, or it might not (b/147347110
-    // comment #77). Take no action, as update_engine is responsible for deciding
-    // whether to cancel.
-    LOG(ERROR) << "Update state is being processed before reboot, taking no action.";
-    return false;
+    // If update has been rolled back, then cancel the entire update.
+    // Client (update_engine) is responsible for doing additional cleanup work on its own states
+    // when ProcessUpdateState() returns UpdateState::Cancelled.
+    auto current_slot = GetCurrentSlot();
+    if (current_slot != Slot::Source) {
+        LOG(INFO) << "Update state is being processed while booting at " << current_slot
+                  << " slot, taking no action.";
+        return false;
+    }
+
+    // current_slot == Source. Attempt to detect rollbacks.
+    if (access(GetRollbackIndicatorPath().c_str(), F_OK) != 0) {
+        // This unverified update is not attempted. Take no action.
+        PLOG(INFO) << "Rollback indicator not detected. "
+                   << "Update state is being processed before reboot, taking no action.";
+        return false;
+    }
+
+    LOG(WARNING) << "Detected rollback, cancelling unverified update.";
+    return RemoveAllUpdateState(lock, before_cancel);
 }
 
 std::unique_ptr<LpMetadata> SnapshotManager::ReadCurrentMetadata() {
@@ -1219,6 +1245,28 @@
         return true;
     }
 
+    std::map<std::string, bool> flashing_status;
+
+    if (!GetSnapshotFlashingStatus(lock, snapshots, &flashing_status)) {
+        LOG(WARNING) << "Failed to determine whether partitions have been flashed. Not"
+                     << "removing update states.";
+        return false;
+    }
+
+    bool all_snapshots_cancelled = std::all_of(flashing_status.begin(), flashing_status.end(),
+                                               [](const auto& pair) { return pair.second; });
+
+    if (all_snapshots_cancelled) {
+        LOG(WARNING) << "All partitions are re-flashed after update, removing all update states.";
+    }
+    return all_snapshots_cancelled;
+}
+
+bool SnapshotManager::GetSnapshotFlashingStatus(LockedFile* lock,
+                                                const std::vector<std::string>& snapshots,
+                                                std::map<std::string, bool>* out) {
+    CHECK(lock);
+
     auto source_slot_suffix = ReadUpdateSourceSlotSuffix();
     if (source_slot_suffix.empty()) {
         return false;
@@ -1244,20 +1292,17 @@
         return false;
     }
 
-    bool all_snapshots_cancelled = true;
     for (const auto& snapshot_name : snapshots) {
         if (GetMetadataPartitionState(*metadata, snapshot_name) ==
             MetadataPartitionState::Updated) {
-            all_snapshots_cancelled = false;
-            continue;
+            out->emplace(snapshot_name, false);
+        } else {
+            // Delete snapshots for partitions that are re-flashed after the update.
+            LOG(WARNING) << "Detected re-flashing of partition " << snapshot_name << ".";
+            out->emplace(snapshot_name, true);
         }
-        // Delete snapshots for partitions that are re-flashed after the update.
-        LOG(WARNING) << "Detected re-flashing of partition " << snapshot_name << ".";
     }
-    if (all_snapshots_cancelled) {
-        LOG(WARNING) << "All partitions are re-flashed after update, removing all update states.";
-    }
-    return all_snapshots_cancelled;
+    return true;
 }
 
 bool SnapshotManager::RemoveAllSnapshots(LockedFile* lock) {
@@ -1267,10 +1312,38 @@
         return false;
     }
 
+    std::map<std::string, bool> flashing_status;
+    if (!GetSnapshotFlashingStatus(lock, snapshots, &flashing_status)) {
+        LOG(WARNING) << "Failed to get flashing status";
+    }
+
+    auto current_slot = GetCurrentSlot();
     bool ok = true;
     bool has_mapped_cow_images = false;
     for (const auto& name : snapshots) {
-        if (!UnmapPartitionWithSnapshot(lock, name) || !DeleteSnapshot(lock, name)) {
+        // If booting off source slot, it is okay to unmap and delete all the snapshots.
+        // If boot indicator is missing, update state is None or Initiated, so
+        //   it is also okay to unmap and delete all the snapshots.
+        // If booting off target slot,
+        //  - should not unmap because:
+        //    - In Android mode, snapshots are not mapped, but
+        //      filesystems are mounting off dm-linear targets directly.
+        //    - In recovery mode, assume nothing is mapped, so it is optional to unmap.
+        //  - If partition is flashed or unknown, it is okay to delete snapshots.
+        //    Otherwise (UPDATED flag), only delete snapshots if they are not mapped
+        //    as dm-snapshot (for example, after merge completes).
+        bool should_unmap = current_slot != Slot::Target;
+        bool should_delete = ShouldDeleteSnapshot(lock, flashing_status, current_slot, name);
+
+        bool partition_ok = true;
+        if (should_unmap && !UnmapPartitionWithSnapshot(lock, name)) {
+            partition_ok = false;
+        }
+        if (partition_ok && should_delete && !DeleteSnapshot(lock, name)) {
+            partition_ok = false;
+        }
+
+        if (!partition_ok) {
             // Remember whether or not we were able to unmap the cow image.
             auto cow_image_device = GetCowImageDeviceName(name);
             has_mapped_cow_images |=
@@ -1293,6 +1366,34 @@
     return ok;
 }
 
+// See comments in RemoveAllSnapshots().
+bool SnapshotManager::ShouldDeleteSnapshot(LockedFile* lock,
+                                           const std::map<std::string, bool>& flashing_status,
+                                           Slot current_slot, const std::string& name) {
+    if (current_slot != Slot::Target) {
+        return true;
+    }
+    auto it = flashing_status.find(name);
+    if (it == flashing_status.end()) {
+        LOG(WARNING) << "Can't determine flashing status for " << name;
+        return true;
+    }
+    if (it->second) {
+        // partition flashed, okay to delete obsolete snapshots
+        return true;
+    }
+    // partition updated, only delete if not dm-snapshot
+    SnapshotStatus status;
+    if (!ReadSnapshotStatus(lock, name, &status)) {
+        LOG(WARNING) << "Unable to read snapshot status for " << name
+                     << ", guessing snapshot device name";
+        auto extra_name = GetSnapshotExtraDeviceName(name);
+        return !IsSnapshotDevice(name) && !IsSnapshotDevice(extra_name);
+    }
+    auto dm_name = GetSnapshotDeviceName(name, status);
+    return !IsSnapshotDevice(dm_name);
+}
+
 UpdateState SnapshotManager::GetUpdateState(double* progress) {
     // If we've never started an update, the state file won't exist.
     auto state_file = GetStateFilePath();
@@ -1369,6 +1470,10 @@
     return access(kBootIndicatorPath, F_OK) == 0;
 }
 
+std::string SnapshotManager::GetGlobalRollbackIndicatorPath() {
+    return kRollbackIndicatorPath;
+}
+
 bool SnapshotManager::NeedSnapshotsInFirstStageMount() {
     // If we fail to read, we'll wind up using CreateLogicalPartitions, which
     // will create devices that look like the old slot, except with extra
@@ -1379,12 +1484,14 @@
     auto slot = GetCurrentSlot();
 
     if (slot != Slot::Target) {
-        if (slot == Slot::Source && !device_->IsRecovery()) {
+        if (slot == Slot::Source) {
             // Device is rebooting into the original slot, so mark this as a
             // rollback.
             auto path = GetRollbackIndicatorPath();
             if (!android::base::WriteStringToFile("1", path)) {
                 PLOG(ERROR) << "Unable to write rollback indicator: " << path;
+            } else {
+                LOG(INFO) << "Rollback detected, writing rollback indicator to " << path;
             }
         }
         LOG(INFO) << "Not booting from new slot. Will not mount snapshots.";
@@ -2391,7 +2498,8 @@
     return AutoUnmountDevice::New(device_->GetMetadataDir());
 }
 
-UpdateState SnapshotManager::InitiateMergeAndWait(SnapshotMergeReport* stats_report) {
+UpdateState SnapshotManager::InitiateMergeAndWait(SnapshotMergeReport* stats_report,
+                                                  const std::function<bool()>& before_cancel) {
     {
         auto lock = LockExclusive();
         // Sync update state from file with bootloader.
@@ -2401,23 +2509,24 @@
         }
     }
 
-    SnapshotMergeStats merge_stats(*this);
+    auto merge_stats = SnapshotMergeStats::GetInstance(*this);
 
     unsigned int last_progress = 0;
-    auto callback = [&]() -> void {
+    auto callback = [&]() -> bool {
         double progress;
         GetUpdateState(&progress);
         if (last_progress < static_cast<unsigned int>(progress)) {
             last_progress = progress;
             LOG(INFO) << "Waiting for merge to complete: " << last_progress << "%.";
         }
+        return true;  // continue
     };
 
     LOG(INFO) << "Waiting for any previous merge request to complete. "
               << "This can take up to several minutes.";
-    merge_stats.Resume();
-    auto state = ProcessUpdateState(callback);
-    merge_stats.set_state(state);
+    merge_stats->Start();
+    auto state = ProcessUpdateState(callback, before_cancel);
+    merge_stats->set_state(state);
     if (state == UpdateState::None) {
         LOG(INFO) << "Can't find any snapshot to merge.";
         return state;
@@ -2428,10 +2537,6 @@
             return state;
         }
 
-        // This is the first snapshot merge that is requested after OTA. We can
-        // initialize the merge duration statistics.
-        merge_stats.Start();
-
         if (!InitiateMerge()) {
             LOG(ERROR) << "Failed to initiate merge.";
             return state;
@@ -2439,43 +2544,22 @@
         // All other states can be handled by ProcessUpdateState.
         LOG(INFO) << "Waiting for merge to complete. This can take up to several minutes.";
         last_progress = 0;
-        state = ProcessUpdateState(callback);
-        merge_stats.set_state(state);
+        state = ProcessUpdateState(callback, before_cancel);
+        merge_stats->set_state(state);
     }
 
     LOG(INFO) << "Merge finished with state \"" << state << "\".";
     if (stats_report) {
-        *stats_report = merge_stats.GetReport();
+        auto result = merge_stats->Finish();
+        if (result) {
+            *stats_report = result->report();
+        } else {
+            LOG(WARNING) << "SnapshotMergeStatus::Finish failed.";
+        }
     }
     return state;
 }
 
-Return SnapshotManager::WaitForMerge() {
-    LOG(INFO) << "Waiting for any previous merge request to complete. "
-              << "This can take up to several minutes.";
-    while (true) {
-        auto state = ProcessUpdateState();
-        if (state == UpdateState::Unverified && GetCurrentSlot() == Slot::Target) {
-            LOG(INFO) << "Wait for merge to be initiated.";
-            std::this_thread::sleep_for(kUpdateStateCheckInterval);
-            continue;
-        }
-        LOG(INFO) << "Wait for merge exits with state " << state;
-        switch (state) {
-            case UpdateState::None:
-                [[fallthrough]];
-            case UpdateState::MergeCompleted:
-                [[fallthrough]];
-            case UpdateState::Cancelled:
-                return Return::Ok();
-            case UpdateState::MergeNeedsReboot:
-                return Return::NeedsReboot();
-            default:
-                return Return::Error();
-        }
-    }
-}
-
 bool SnapshotManager::HandleImminentDataWipe(const std::function<void()>& callback) {
     if (!device_->IsRecovery()) {
         LOG(ERROR) << "Data wipes are only allowed in recovery.";
@@ -2506,7 +2590,10 @@
         return false;
     }
 
-    UpdateState state = ProcessUpdateState(callback);
+    UpdateState state = ProcessUpdateState([&]() -> bool {
+        callback();
+        return true;
+    });
     LOG(INFO) << "Update state in recovery: " << state;
     switch (state) {
         case UpdateState::MergeFailed:
diff --git a/fs_mgr/libsnapshot/snapshot_stats.cpp b/fs_mgr/libsnapshot/snapshot_stats.cpp
index 635b47d..5da7b98 100644
--- a/fs_mgr/libsnapshot/snapshot_stats.cpp
+++ b/fs_mgr/libsnapshot/snapshot_stats.cpp
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "snapshot_stats.h"
+#include <libsnapshot/snapshot_stats.h>
 
 #include <sstream>
 
@@ -23,22 +23,17 @@
 namespace android {
 namespace snapshot {
 
-SnapshotMergeStats::SnapshotMergeStats(SnapshotManager& parent) : parent_(parent) {
-    init_time_ = std::chrono::steady_clock::now();
+SnapshotMergeStats* SnapshotMergeStats::GetInstance(SnapshotManager& parent) {
+    static SnapshotMergeStats g_instance(parent.GetMergeStateFilePath());
+    CHECK(g_instance.path_ == parent.GetMergeStateFilePath());
+    return &g_instance;
 }
 
-SnapshotMergeStats::~SnapshotMergeStats() {
-    std::string error;
-    auto file_path = parent_.GetMergeStateFilePath();
-    if (!android::base::RemoveFileIfExists(file_path, &error)) {
-        LOG(ERROR) << "Failed to remove merge statistics file " << file_path << ": " << error;
-        return;
-    }
-}
+SnapshotMergeStats::SnapshotMergeStats(const std::string& path) : path_(path), running_(false) {}
 
 bool SnapshotMergeStats::ReadState() {
     std::string contents;
-    if (!android::base::ReadFileToString(parent_.GetMergeStateFilePath(), &contents)) {
+    if (!android::base::ReadFileToString(path_, &contents)) {
         PLOG(INFO) << "Read merge statistics file failed";
         return false;
     }
@@ -55,34 +50,73 @@
         LOG(ERROR) << "Unable to serialize SnapshotMergeStats.";
         return false;
     }
-    auto file_path = parent_.GetMergeStateFilePath();
-    if (!WriteStringToFileAtomic(contents, file_path)) {
+    if (!WriteStringToFileAtomic(contents, path_)) {
         PLOG(ERROR) << "Could not write to merge statistics file";
         return false;
     }
     return true;
 }
 
-void SnapshotMergeStats::Start() {
-    report_.set_resume_count(0);
-    report_.set_state(UpdateState::None);
-    WriteState();
+bool SnapshotMergeStats::DeleteState() {
+    std::string error;
+    if (!android::base::RemoveFileIfExists(path_, &error)) {
+        LOG(ERROR) << "Failed to remove merge statistics file " << path_ << ": " << error;
+        return false;
+    }
+    return true;
 }
 
-void SnapshotMergeStats::Resume() {
-    if (!ReadState()) {
-        return;
+bool SnapshotMergeStats::Start() {
+    if (running_) {
+        LOG(ERROR) << "SnapshotMergeStats running_ == " << running_;
+        return false;
     }
-    report_.set_resume_count(report_.resume_count() + 1);
-    WriteState();
+    running_ = true;
+
+    start_time_ = std::chrono::steady_clock::now();
+    if (ReadState()) {
+        report_.set_resume_count(report_.resume_count() + 1);
+    } else {
+        report_.set_resume_count(0);
+        report_.set_state(UpdateState::None);
+    }
+
+    return WriteState();
 }
 
 void SnapshotMergeStats::set_state(android::snapshot::UpdateState state) {
     report_.set_state(state);
 }
 
-SnapshotMergeReport SnapshotMergeStats::GetReport() {
-    return report_;
+class SnapshotMergeStatsResultImpl : public SnapshotMergeStats::Result {
+  public:
+    SnapshotMergeStatsResultImpl(const SnapshotMergeReport& report,
+                                 std::chrono::steady_clock::duration merge_time)
+        : report_(report), merge_time_(merge_time) {}
+    const SnapshotMergeReport& report() const override { return report_; }
+    std::chrono::steady_clock::duration merge_time() const override { return merge_time_; }
+
+  private:
+    SnapshotMergeReport report_;
+    std::chrono::steady_clock::duration merge_time_;
+};
+
+std::unique_ptr<SnapshotMergeStats::Result> SnapshotMergeStats::Finish() {
+    if (!running_) {
+        LOG(ERROR) << "SnapshotMergeStats running_ == " << running_;
+        return nullptr;
+    }
+    running_ = false;
+
+    auto result = std::make_unique<SnapshotMergeStatsResultImpl>(
+            report_, std::chrono::steady_clock::now() - start_time_);
+
+    // We still want to report result if state is not deleted. Just leave
+    // it there and move on. A side effect is that it may be reported over and
+    // over again in the future, but there is nothing we can do.
+    (void)DeleteState();
+
+    return result;
 }
 
 }  // namespace snapshot
diff --git a/fs_mgr/libsnapshot/snapshot_stats.h b/fs_mgr/libsnapshot/snapshot_stats.h
deleted file mode 100644
index 60109a4..0000000
--- a/fs_mgr/libsnapshot/snapshot_stats.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (C) 2020 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.
-
-#pragma once
-
-#include <chrono>
-
-#include <android/snapshot/snapshot.pb.h>
-#include <libsnapshot/snapshot.h>
-
-namespace android {
-namespace snapshot {
-
-class SnapshotMergeStats {
-  public:
-    SnapshotMergeStats(SnapshotManager& parent);
-    ~SnapshotMergeStats();
-    void Start();
-    void Resume();
-    void set_state(android::snapshot::UpdateState state);
-    SnapshotMergeReport GetReport();
-
-  private:
-    bool ReadState();
-    bool WriteState();
-
-    const SnapshotManager& parent_;
-    SnapshotMergeReport report_;
-    std::chrono::time_point<std::chrono::steady_clock> init_time_;
-    std::chrono::time_point<std::chrono::steady_clock> end_time_;
-};
-
-}  // namespace snapshot
-}  // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 5d2840f..7d16ec2 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -506,9 +506,6 @@
 }
 
 TEST_F(SnapshotTest, FirstStageMountAndMerge) {
-#ifdef SKIP_TEST_IN_PRESUBMIT
-    GTEST_SKIP() << "WIP failure b/148889015";
-#endif
     ASSERT_TRUE(AcquireLock());
 
     static const uint64_t kDeviceSize = 1024 * 1024;
@@ -565,9 +562,6 @@
 }
 
 TEST_F(SnapshotTest, FlashSuperDuringMerge) {
-#ifdef SKIP_TEST_IN_PRESUBMIT
-    GTEST_SKIP() << "WIP failure b/148889015";
-#endif
     ASSERT_TRUE(AcquireLock());
 
     static const uint64_t kDeviceSize = 1024 * 1024;
@@ -979,9 +973,6 @@
 // Also test UnmapUpdateSnapshot unmaps everything.
 // Also test first stage mount and merge after this.
 TEST_F(SnapshotUpdateTest, FullUpdateFlow) {
-#ifdef SKIP_TEST_IN_PRESUBMIT
-    GTEST_SKIP() << "WIP failure b/148889015";
-#endif
     // OTA client blindly unmaps all partitions that are possibly mapped.
     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
         ASSERT_TRUE(sm->UnmapUpdateSnapshot(name));
@@ -1129,9 +1120,6 @@
 
 // Test that the old partitions are not modified.
 TEST_F(SnapshotUpdateTest, TestRollback) {
-#ifdef SKIP_TEST_IN_PRESUBMIT
-    GTEST_SKIP() << "WIP failure b/148889015";
-#endif
     // Execute the update.
     ASSERT_TRUE(sm->BeginUpdate());
     ASSERT_TRUE(sm->UnmapUpdateSnapshot("sys_b"));
@@ -1309,9 +1297,6 @@
 }
 
 TEST_F(SnapshotUpdateTest, MergeCannotRemoveCow) {
-#ifdef SKIP_TEST_IN_PRESUBMIT
-    GTEST_SKIP() << "WIP failure b/148889015";
-#endif
     // Make source partitions as big as possible to force COW image to be created.
     SetSize(sys_, 5_MiB);
     SetSize(vnd_, 5_MiB);
@@ -1585,48 +1570,6 @@
             << "FinishedSnapshotWrites should detect overflow of CoW device.";
 }
 
-TEST_F(SnapshotUpdateTest, WaitForMerge) {
-#ifdef SKIP_TEST_IN_PRESUBMIT
-    GTEST_SKIP() << "WIP failure b/148889015";
-#endif
-    AddOperationForPartitions();
-
-    // Execute the update.
-    ASSERT_TRUE(sm->BeginUpdate());
-    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
-
-    // Write some data to target partitions.
-    for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
-        ASSERT_TRUE(WriteSnapshotAndHash(name));
-    }
-
-    ASSERT_TRUE(sm->FinishedSnapshotWrites());
-
-    // Simulate shutting down the device.
-    ASSERT_TRUE(UnmapAll());
-
-    // After reboot, init does first stage mount.
-    {
-        auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
-        ASSERT_NE(nullptr, init);
-        ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
-    }
-
-    auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
-    ASSERT_NE(nullptr, new_sm);
-
-    auto waiter = std::async(std::launch::async, [&new_sm] { return new_sm->WaitForMerge(); });
-    ASSERT_EQ(std::future_status::timeout, waiter.wait_for(1s))
-            << "WaitForMerge should block when not initiated";
-
-    auto merger =
-            std::async(std::launch::async, [&new_sm] { return new_sm->InitiateMergeAndWait(); });
-    // Small images, so should be merged pretty quickly.
-    ASSERT_EQ(std::future_status::ready, waiter.wait_for(3s)) << "WaitForMerge did not finish";
-    ASSERT_TRUE(waiter.get());
-    ASSERT_THAT(merger.get(), AnyOf(UpdateState::None, UpdateState::MergeCompleted));
-}
-
 TEST_F(SnapshotUpdateTest, LowSpace) {
     static constexpr auto kMaxFree = 10_MiB;
     auto userdata = std::make_unique<LowSpaceUserdata>();
diff --git a/fs_mgr/libsnapshot/snapshotctl.cpp b/fs_mgr/libsnapshot/snapshotctl.cpp
index e35ad4b..aa5e9c1 100644
--- a/fs_mgr/libsnapshot/snapshotctl.cpp
+++ b/fs_mgr/libsnapshot/snapshotctl.cpp
@@ -24,8 +24,10 @@
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
+#include <android/snapshot/snapshot.pb.h>
 #include <libsnapshot/snapshot.h>
-#include "utility.h"
+#include <libsnapshot/snapshot_stats.h>
+#include <statslog.h>
 
 #include "utility.h"
 
@@ -37,17 +39,29 @@
                  "Actions:\n"
                  "  dump\n"
                  "    Print snapshot states.\n"
-                 "  merge [--logcat] [--log-to-file]\n"
+                 "  merge [--logcat] [--log-to-file] [--report] [--dry-run]\n"
                  "    Initialize merge and wait for it to be completed.\n"
                  "    If --logcat is specified, log to logcat.\n"
                  "    If --log-to-file is specified, log to /data/misc/snapshotctl_log/.\n"
-                 "    If both specified, log to both. If none specified, log to stdout.\n";
+                 "    If both specified, log to both. If none specified, log to stdout.\n"
+                 "    If --report is specified, send merge statistics to statsd.\n"
+                 "    If --dry-run flag, no real merge operation is is triggered, and\n"
+                 "      sample statistics are sent to statsd for testing purpose.\n";
     return EX_USAGE;
 }
 
 namespace android {
 namespace snapshot {
 
+static SnapshotMergeReport GetDummySnapshotMergeReport() {
+    SnapshotMergeReport fake_report;
+
+    fake_report.set_state(UpdateState::MergeCompleted);
+    fake_report.set_resume_count(56);
+
+    return fake_report;
+}
+
 bool DumpCmdHandler(int /*argc*/, char** argv) {
     android::base::InitLogging(argv, &android::base::StderrLogger);
     return SnapshotManager::New()->Dump(std::cout);
@@ -113,28 +127,58 @@
 };
 
 bool MergeCmdHandler(int argc, char** argv) {
-    auto begin = std::chrono::steady_clock::now();
+    std::chrono::milliseconds passed_ms;
+
+    bool report_to_statsd = false;
+    bool dry_run = false;
+    for (int i = 2; i < argc; ++i) {
+        if (argv[i] == "--report"s) {
+            report_to_statsd = true;
+        } else if (argv[i] == "--dry-run"s) {
+            dry_run = true;
+        }
+    }
 
     // 'snapshotctl merge' is stripped away from arguments to
     // Logger.
     android::base::InitLogging(argv);
     android::base::SetLogger(MergeCmdLogger(argc - 2, argv + 2));
 
-    auto state = SnapshotManager::New()->InitiateMergeAndWait();
+    UpdateState state;
+    SnapshotMergeReport merge_report;
+    if (dry_run) {
+        merge_report = GetDummySnapshotMergeReport();
+        state = merge_report.state();
+        passed_ms = std::chrono::milliseconds(1234);
+    } else {
+        auto begin = std::chrono::steady_clock::now();
 
-    // We could wind up in the Unverified state if the device rolled back or
-    // hasn't fully rebooted. Ignore this.
-    if (state == UpdateState::None || state == UpdateState::Unverified) {
-        return true;
-    }
-    if (state == UpdateState::MergeCompleted) {
+        state = SnapshotManager::New()->InitiateMergeAndWait(&merge_report);
+
+        // We could wind up in the Unverified state if the device rolled back or
+        // hasn't fully rebooted. Ignore this.
+        if (state == UpdateState::None || state == UpdateState::Unverified) {
+            return true;
+        }
+
         auto end = std::chrono::steady_clock::now();
-        auto passed = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count();
-        LOG(INFO) << "Snapshot merged in " << passed << " ms.";
+        passed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin);
+    }
+
+    if (report_to_statsd) {
+        android::util::stats_write(android::util::SNAPSHOT_MERGE_REPORTED,
+                                   static_cast<int32_t>(merge_report.state()),
+                                   static_cast<int64_t>(passed_ms.count()),
+                                   static_cast<int32_t>(merge_report.resume_count()));
+    }
+
+    if (state == UpdateState::MergeCompleted) {
+        LOG(INFO) << "Snapshot merged in " << passed_ms.count() << " ms.";
         return true;
     }
 
     LOG(ERROR) << "Snapshot failed to merge with state \"" << state << "\".";
+
     return false;
 }
 
diff --git a/fs_mgr/libsnapshot/snapshotctl.rc b/fs_mgr/libsnapshot/snapshotctl.rc
deleted file mode 100644
index 5dbe352..0000000
--- a/fs_mgr/libsnapshot/snapshotctl.rc
+++ /dev/null
@@ -1,2 +0,0 @@
-on property:sys.boot_completed=1
-    exec_background - root root -- /system/bin/snapshotctl merge --logcat --log-to-file
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
index 69b3150..3fec608 100644
--- a/fs_mgr/tests/fs_mgr_test.cpp
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -27,6 +27,7 @@
 #include <android-base/file.h>
 #include <android-base/properties.h>
 #include <android-base/strings.h>
+#include <fs_mgr.h>
 #include <fstab/fstab.h>
 #include <gtest/gtest.h>
 
@@ -1015,6 +1016,10 @@
     }
     Fstab fstab;
     ASSERT_TRUE(ReadDefaultFstab(&fstab)) << "Failed to read default fstab";
-    ASSERT_NE(nullptr, GetMountedEntryForUserdata(&fstab))
+    Fstab proc_mounts;
+    ASSERT_TRUE(ReadFstabFromFile("/proc/mounts", &proc_mounts)) << "Failed to read /proc/mounts";
+    auto mounted_entry = GetEntryForMountPoint(&proc_mounts, "/data");
+    ASSERT_NE(mounted_entry, nullptr) << "/data is not mounted";
+    ASSERT_NE(nullptr, fs_mgr_get_mounted_entry_for_userdata(&fstab, *mounted_entry))
             << "/data wasn't mounted from default fstab";
 }
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index 1d65b1c..c81a80e 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -159,8 +159,8 @@
 
 #define GK_ERROR *gkResponse = GKResponse::error(), Status::ok()
 
-    Status enroll(int32_t uid, const std::unique_ptr<std::vector<uint8_t>>& currentPasswordHandle,
-                  const std::unique_ptr<std::vector<uint8_t>>& currentPassword,
+    Status enroll(int32_t uid, const std::optional<std::vector<uint8_t>>& currentPasswordHandle,
+                  const std::optional<std::vector<uint8_t>>& currentPassword,
                   const std::vector<uint8_t>& desiredPassword, GKResponse* gkResponse) override {
         IPCThreadState* ipc = IPCThreadState::self();
         const int calling_pid = ipc->getCallingPid();
diff --git a/init/init.cpp b/init/init.cpp
index bfef9e5..63aefc1 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -120,7 +120,7 @@
         }
     };
 
-    if (auto result = epoll->RegisterHandler(epoll_fd, drain_socket); !result) {
+    if (auto result = epoll->RegisterHandler(epoll_fd, drain_socket); !result.ok()) {
         LOG(FATAL) << result.error();
     }
 }
@@ -778,11 +778,10 @@
     if (false) DumpState();
 
     // Make the GSI status available before scripts start running.
-    if (android::gsi::IsGsiRunning()) {
-        SetProperty("ro.gsid.image_running", "1");
-    } else {
-        SetProperty("ro.gsid.image_running", "0");
-    }
+    auto is_running = android::gsi::IsGsiRunning() ? "1" : "0";
+    SetProperty(gsi::kGsiBootedProp, is_running);
+    auto is_installed = android::gsi::IsGsiInstalled() ? "1" : "0";
+    SetProperty(gsi::kGsiInstalledProp, is_installed);
 
     am.QueueBuiltinAction(SetupCgroupsAction, "SetupCgroups");
     am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict");
diff --git a/init/mount_namespace.cpp b/init/mount_namespace.cpp
index aa36849..2175075 100644
--- a/init/mount_namespace.cpp
+++ b/init/mount_namespace.cpp
@@ -323,10 +323,20 @@
     }
     if (bootstrap_ns_id != GetMountNamespaceId() && bootstrap_ns_fd.get() != -1 &&
         IsApexUpdatable()) {
+        // The property service thread and its descendent threads must be in the correct mount
+        // namespace to call Service::Start(), however setns() only operates on a single thread and
+        // fails when secondary threads attempt to join the same mount namespace.  Therefore, we
+        // must join the property service thread and its descendents before the setns() call.  Those
+        // threads are then started again after the setns() call, and they'll be in the proper
+        // namespace.
+        PausePropertyService();
+
         if (setns(bootstrap_ns_fd.get(), CLONE_NEWNS) == -1) {
             PLOG(ERROR) << "Failed to switch to bootstrap mount namespace.";
             return false;
         }
+
+        ResumePropertyService();
     }
     return true;
 }
diff --git a/init/property_service.cpp b/init/property_service.cpp
index b140ee4..319a241 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -813,7 +813,9 @@
 static void update_sys_usb_config() {
     bool is_debuggable = android::base::GetBoolProperty("ro.debuggable", false);
     std::string config = android::base::GetProperty("persist.sys.usb.config", "");
-    if (config.empty()) {
+    // b/150130503, add (config == "none") condition here to prevent appending
+    // ",adb" if "none" is explicitly defined in default prop.
+    if (config.empty() || config == "none") {
         InitPropertySet("persist.sys.usb.config", is_debuggable ? "adb" : "none");
     } else if (is_debuggable && config.find("adb") == std::string::npos &&
                config.length() + 4 < PROP_VALUE_MAX) {
diff --git a/init/reboot.cpp b/init/reboot.cpp
index f7cc36e..cad192d 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -96,8 +96,10 @@
     return ret;
 }
 
-static void PersistRebootReason(const char* reason) {
-    SetProperty(LAST_REBOOT_REASON_PROPERTY, reason);
+static void PersistRebootReason(const char* reason, bool write_to_property) {
+    if (write_to_property) {
+        SetProperty(LAST_REBOOT_REASON_PROPERTY, reason);
+    }
     WriteStringToFile(reason, LAST_REBOOT_REASON_FILE);
 }
 
@@ -535,14 +537,6 @@
     Timer t;
     LOG(INFO) << "Reboot start, reason: " << reason << ", reboot_target: " << reboot_target;
 
-    // If /data isn't mounted then we can skip the extra reboot steps below, since we don't need to
-    // worry about unmounting it.
-    if (!IsDataMounted()) {
-        sync();
-        RebootSystem(cmd, reboot_target);
-        abort();
-    }
-
     // Ensure last reboot reason is reduced to canonical
     // alias reported in bootloader or system boot reason.
     size_t skip = 0;
@@ -552,9 +546,17 @@
          reasons[1] == "hard" || reasons[1] == "warm")) {
         skip = strlen("reboot,");
     }
-    PersistRebootReason(reason.c_str() + skip);
+    PersistRebootReason(reason.c_str() + skip, true);
     sync();
 
+    // If /data isn't mounted then we can skip the extra reboot steps below, since we don't need to
+    // worry about unmounting it.
+    if (!IsDataMounted()) {
+        sync();
+        RebootSystem(cmd, reboot_target);
+        abort();
+    }
+
     bool is_thermal_shutdown = cmd == ANDROID_RB_THERMOFF;
 
     auto shutdown_timeout = 0ms;
@@ -818,6 +820,7 @@
         LOG(INFO) << "Re-enabling service '" << s->name() << "'";
         s->Enable();
     }
+    ServiceList::GetInstance().ResetState();
     LeaveShutdown();
     ActionManager::GetInstance().QueueEventTrigger("userspace-reboot-resume");
     guard.Disable();  // Go on with userspace reboot.
@@ -836,7 +839,8 @@
     if (!WaitForProperty("sys.boot_completed", "1", timeout)) {
         LOG(ERROR) << "Failed to boot in " << timeout.count() << "ms. Switching to full reboot";
         // In this case device is in a boot loop. Only way to recover is to do dirty reboot.
-        PersistRebootReason("userspace_failed,watchdog_triggered");
+        // Since init might be wedged, don't try to write reboot reason into a persistent property.
+        PersistRebootReason("userspace_failed,watchdog_triggered", false);
         RebootSystem(ANDROID_RB_RESTART2, "userspace_failed,watchdog_triggered");
     }
     LOG(INFO) << "Device booted, stopping userspace reboot watchdog";
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 2faa167..acbcbd6 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -66,6 +66,7 @@
 #include <android-base/unique_fd.h>
 #include <fs_avb/fs_avb.h>
 #include <libgsi/libgsi.h>
+#include <libsnapshot/snapshot.h>
 #include <selinux/android.h>
 
 #include "debug_ramdisk.h"
@@ -78,6 +79,7 @@
 using android::base::Timer;
 using android::base::unique_fd;
 using android::fs_mgr::AvbHandle;
+using android::snapshot::SnapshotManager;
 
 namespace android {
 namespace init {
@@ -538,6 +540,8 @@
     // adb remount, snapshot-based updates, and DSUs all create files during
     // first-stage init.
     selinux_android_restorecon("/metadata", SELINUX_ANDROID_RESTORECON_RECURSE);
+
+    selinux_android_restorecon(SnapshotManager::GetGlobalRollbackIndicatorPath().c_str(), 0);
 }
 
 int SelinuxKlogCallback(int type, const char* fmt, ...) {
diff --git a/init/service_list.h b/init/service_list.h
index 8cbc878..280a228 100644
--- a/init/service_list.h
+++ b/init/service_list.h
@@ -81,6 +81,11 @@
     bool IsServicesUpdated() const { return services_update_finished_; }
     void DelayService(const Service& service) REQUIRES(service_lock);
 
+    void ResetState() {
+        post_data_ = false;
+        services_update_finished_ = false;
+    }
+
   private:
     std::vector<std::unique_ptr<Service>> services_;
 
diff --git a/libcutils/include/cutils/trace.h b/libcutils/include/cutils/trace.h
index e12c32c..c74ee3e 100644
--- a/libcutils/include/cutils/trace.h
+++ b/libcutils/include/cutils/trace.h
@@ -88,12 +88,6 @@
 #error ATRACE_TAG must be defined to be one of the tags defined in cutils/trace.h
 #endif
 
-// Set this to 0 to revert to the old Binder-based atrace implementation.
-// This is only here in case rollbacks do not apply cleanly.
-// TODO(fmayer): Remove this once we are confident this won't need to be
-// rolled back, no later than 2020-03-01.
-#define ATRACE_SHMEM 1
-
 /**
  * Opens the trace file for writing and reads the property for initial tags.
  * The atrace.tags.enableflags property sets the tags to trace.
@@ -121,15 +115,11 @@
  * prevent tracing within the Zygote process.
  */
 void atrace_set_tracing_enabled(bool enabled);
+
 /**
- * If !ATRACE_SHMEM:
- *   Flag indicating whether setup has been completed, initialized to 0.
- *   Nonzero indicates setup has completed.
- *   Note: This does NOT indicate whether or not setup was successful.
- * If ATRACE_SHMEM:
- *   This is always set to false. This forces code that uses an old version
- *   of this header to always call into atrace_setup, in which we call
- *   atrace_init unconditionally.
+ * This is always set to false. This forces code that uses an old version
+ * of this header to always call into atrace_setup, in which we call
+ * atrace_init unconditionally.
  */
 extern atomic_bool atrace_is_ready;
 
@@ -154,28 +144,8 @@
 #define ATRACE_INIT() atrace_init()
 #define ATRACE_GET_ENABLED_TAGS() atrace_get_enabled_tags()
 
-#if ATRACE_SHMEM
 void atrace_init();
 uint64_t atrace_get_enabled_tags();
-#else
-static inline void atrace_init()
-{
-    if (CC_UNLIKELY(!atomic_load_explicit(&atrace_is_ready, memory_order_acquire))) {
-        atrace_setup();
-    }
-}
-
-/**
- * Get the mask of all tags currently enabled.
- * It can be used as a guard condition around more expensive trace calculations.
- * Every trace function calls this, which ensures atrace_init is run.
- */
-static inline uint64_t atrace_get_enabled_tags()
-{
-    atrace_init();
-    return atrace_enabled_tags;
-}
-#endif
 
 /**
  * Test if a given tag is currently enabled.
diff --git a/libcutils/trace-dev.cpp b/libcutils/trace-dev.cpp
index 9ca1729..5a09a2d 100644
--- a/libcutils/trace-dev.cpp
+++ b/libcutils/trace-dev.cpp
@@ -41,9 +41,6 @@
     } else {
       atrace_enabled_tags = atrace_get_property();
     }
-#if !ATRACE_SHMEM
-    atomic_store_explicit(&atrace_is_ready, true, memory_order_release);
-#endif
 }
 
 static void atrace_seq_number_changed(uint32_t prev_seq_no, uint32_t seq_no) {
@@ -69,11 +66,7 @@
 
 void atrace_setup()
 {
-#if ATRACE_SHMEM
     atrace_init();
-#else
-    pthread_once(&atrace_once_control, atrace_init_once);
-#endif
 }
 
 void atrace_begin_body(const char* name)
diff --git a/libcutils/trace-dev.inc b/libcutils/trace-dev.inc
index a57a4c5..3ec98b3 100644
--- a/libcutils/trace-dev.inc
+++ b/libcutils/trace-dev.inc
@@ -71,8 +71,6 @@
 static const prop_info* atrace_property_info = reinterpret_cast<const prop_info*>(empty_pi);
 #endif
 
-#if ATRACE_SHMEM
-
 /**
  * This is called when the sequence number of debug.atrace.tags.enableflags
  * changes and we need to reload the enabled tags.
@@ -96,7 +94,6 @@
     atrace_init();
     return atrace_enabled_tags;
 }
-#endif
 
 // Set whether this process is debuggable, which determines whether
 // application-level tracing is allowed when the ro.debuggable system property
@@ -186,19 +183,17 @@
 void atrace_update_tags()
 {
     uint64_t tags;
-    if (ATRACE_SHMEM || CC_UNLIKELY(atomic_load_explicit(&atrace_is_ready, memory_order_acquire))) {
-        if (atomic_load_explicit(&atrace_is_enabled, memory_order_acquire)) {
-            tags = atrace_get_property();
-            pthread_mutex_lock(&atrace_tags_mutex);
-            atrace_enabled_tags = tags;
-            pthread_mutex_unlock(&atrace_tags_mutex);
-        } else {
-            // Tracing is disabled for this process, so we simply don't
-            // initialize the tags.
-            pthread_mutex_lock(&atrace_tags_mutex);
-            atrace_enabled_tags = ATRACE_TAG_NOT_READY;
-            pthread_mutex_unlock(&atrace_tags_mutex);
-        }
+    if (atomic_load_explicit(&atrace_is_enabled, memory_order_acquire)) {
+        tags = atrace_get_property();
+        pthread_mutex_lock(&atrace_tags_mutex);
+        atrace_enabled_tags = tags;
+        pthread_mutex_unlock(&atrace_tags_mutex);
+    } else {
+        // Tracing is disabled for this process, so we simply don't
+        // initialize the tags.
+        pthread_mutex_lock(&atrace_tags_mutex);
+        atrace_enabled_tags = ATRACE_TAG_NOT_READY;
+        pthread_mutex_unlock(&atrace_tags_mutex);
     }
 }
 
diff --git a/libcutils/trace-host.cpp b/libcutils/trace-host.cpp
index c21d0ee..9781ad3 100644
--- a/libcutils/trace-host.cpp
+++ b/libcutils/trace-host.cpp
@@ -30,10 +30,8 @@
 void atrace_async_end_body(const char* /*name*/, int32_t /*cookie*/) {}
 void atrace_int_body(const char* /*name*/, int32_t /*value*/) {}
 void atrace_int64_body(const char* /*name*/, int64_t /*value*/) {}
-#if ATRACE_SHMEM
 void atrace_init() {}
 uint64_t atrace_get_enabled_tags()
 {
     return ATRACE_TAG_NOT_READY;
 }
-#endif
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 7f183c2..f1e5118 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -101,11 +101,6 @@
         versions: ["29", "30"],
     },
 
-    // TODO(tomcherry): Renable this before release branch is cut
-    header_abi_checker: {
-        enabled: false,
-    },
-
     cflags: [
         "-Wall",
         "-Werror",
diff --git a/liblog/include/android/log.h b/liblog/include/android/log.h
index c98455d..b9839d6 100644
--- a/liblog/include/android/log.h
+++ b/liblog/include/android/log.h
@@ -156,7 +156,7 @@
  * Let the logging function choose the best log target.
  * This is not part of the enum since adding either -1 or 0xFFFFFFFF forces the enum to be signed or
  * unsigned, which breaks unfortunately common arithmetic against LOG_ID_MIN and LOG_ID_MAX. */
-#define LOG_ID_DEFAULT -1
+#define LOG_ID_DEFAULT (-1)
 
 /**
  * Writes the constant string `text` to the log buffer `id`,
diff --git a/liblog/logger_write.cpp b/liblog/logger_write.cpp
index 1b6b0c6..0dbb94f 100644
--- a/liblog/logger_write.cpp
+++ b/liblog/logger_write.cpp
@@ -27,6 +27,7 @@
 #include <android/set_abort_message.h>
 #endif
 
+#include <atomic>
 #include <shared_mutex>
 
 #include <android-base/errno_restorer.h>
@@ -148,11 +149,9 @@
   GetDefaultTag().assign(tag, 0, LOGGER_ENTRY_MAX_PAYLOAD);
 }
 
-static int minimum_log_priority = ANDROID_LOG_DEFAULT;
+static std::atomic_int minimum_log_priority = ANDROID_LOG_DEFAULT;
 int __android_log_set_minimum_priority(int priority) {
-  int old_minimum_log_priority = minimum_log_priority;
-  minimum_log_priority = priority;
-  return old_minimum_log_priority;
+  return minimum_log_priority.exchange(priority, std::memory_order_relaxed);
 }
 
 int __android_log_get_minimum_priority() {
diff --git a/libsync/OWNERS b/libsync/OWNERS
index dc61733..e75b15b 100644
--- a/libsync/OWNERS
+++ b/libsync/OWNERS
@@ -1,3 +1,3 @@
-ghackmann@google.com
+chrisforbes@google.com
+hridya@google.com
 jessehall@google.com
-marissaw@google.com
diff --git a/libsystem/OWNERS b/libsystem/OWNERS
index fdea804..4f800d4 100644
--- a/libsystem/OWNERS
+++ b/libsystem/OWNERS
@@ -1,7 +1,6 @@
 # graphics/composer
 adyabr@google.com
 lpy@google.com
-marissaw@google.com
 stoza@google.com
 vhau@google.com
 
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 3695f72..36449eb 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -116,12 +116,6 @@
         x86_64: {
             srcs: ["AsmGetRegsX86_64.S"],
         },
-        mips: {
-            srcs: ["AsmGetRegsMips.S"],
-        },
-        mips64: {
-            srcs: ["AsmGetRegsMips64.S"],
-        },
     },
 
     static_libs: [
diff --git a/libunwindstack/AsmGetRegsMips.S b/libunwindstack/AsmGetRegsMips.S
deleted file mode 100644
index 183d0a9..0000000
--- a/libunwindstack/AsmGetRegsMips.S
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-  .text
-  .type     AsmGetRegs, %function
-  .globl    AsmGetRegs
-  .ent      AsmGetRegs
-  .balign   16
-AsmGetRegs:
-  .cfi_startproc
-  .cfi_def_cfa $sp, 0
-  .set push
-  .set noreorder
-  .cpload $t9
-  sw   $zero, 0($a0)
-  .set noat
-  sw   $at, 4($a0)
-  .set at
-  sw   $v0, 8($a0)
-  sw   $v1, 12($a0)
-  sw   $a0, 16($a0)
-  sw   $a1, 20($a0)
-  sw   $a2, 24($a0)
-  sw   $a3, 28($a0)
-  sw   $t0, 32($a0)
-  sw   $t1, 36($a0)
-  sw   $t2, 40($a0)
-  sw   $t3, 44($a0)
-  sw   $t4, 48($a0)
-  sw   $t5, 52($a0)
-  sw   $t6, 56($a0)
-  sw   $t7, 60($a0)
-  sw   $s0, 64($a0)
-  sw   $s1, 68($a0)
-  sw   $s2, 72($a0)
-  sw   $s3, 76($a0)
-  sw   $s4, 80($a0)
-  sw   $s5, 84($a0)
-  sw   $s6, 88($a0)
-  sw   $s7, 92($a0)
-  sw   $t8, 96($a0)
-  sw   $t9, 100($a0)
-  sw   $k0, 104($a0)
-  sw   $k1, 108($a0)
-  sw   $gp, 112($a0)
-  sw   $sp, 116($a0)
-  sw   $s8, 120($a0)
-  sw   $ra, 124($a0)
-  jalr $zero, $ra
-  sw   $ra, 128($a0)   // set PC to the calling function
-
-  .set pop
-  .cfi_endproc
-  .size     AsmGetRegs, .-AsmGetRegs
-  .end      AsmGetRegs
diff --git a/libunwindstack/AsmGetRegsMips64.S b/libunwindstack/AsmGetRegsMips64.S
deleted file mode 100644
index 7a244f6..0000000
--- a/libunwindstack/AsmGetRegsMips64.S
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-  .text
-  .type     AsmGetRegs, %function
-  .globl    AsmGetRegs
-  .ent      AsmGetRegs
-  .balign    16
-AsmGetRegs:
-  .cfi_startproc
-  .cfi_def_cfa $sp, 0
-  .set push
-  .set noreorder
-  .cpload $t9
-  sd   $zero, 0($a0)
-  .set noat
-  sd   $at, 8($a0)
-  .set at
-  sd   $v0, 16($a0)
-  sd   $v1, 24($a0)
-  sd   $a0, 32($a0)
-  sd   $a1, 40($a0)
-  sd   $a2, 48($a0)
-  sd   $a3, 56($a0)
-  sd   $a4, 64($a0)
-  sd   $a5, 72($a0)
-  sd   $a6, 80($a0)
-  sd   $a7, 88($a0)
-  sd   $t0, 96($a0)
-  sd   $t1, 104($a0)
-  sd   $t2, 112($a0)
-  sd   $t3, 120($a0)
-  sd   $s0, 128($a0)
-  sd   $s1, 136($a0)
-  sd   $s2, 144($a0)
-  sd   $s3, 152($a0)
-  sd   $s4, 160($a0)
-  sd   $s5, 168($a0)
-  sd   $s6, 176($a0)
-  sd   $s7, 184($a0)
-  sd   $t8, 192($a0)
-  sd   $t9, 200($a0)
-  sd   $k0, 208($a0)
-  sd   $k1, 216($a0)
-  sd   $gp, 224($a0)
-  sd   $sp, 232($a0)
-  sd   $s8, 240($a0)
-  sd   $ra, 248($a0)
-  jalr $zero, $ra
-  sd   $ra, 256($a0)   // set PC to the calling function
-
-  .set pop
-  .cfi_endproc
-  .size AsmGetRegs, .-AsmGetRegs
-  .end      AsmGetRegs
diff --git a/libunwindstack/Regs.cpp b/libunwindstack/Regs.cpp
index c7dec52..e0a785b 100644
--- a/libunwindstack/Regs.cpp
+++ b/libunwindstack/Regs.cpp
@@ -100,10 +100,6 @@
   return ARCH_X86;
 #elif defined(__x86_64__)
   return ARCH_X86_64;
-#elif defined(__mips__) && !defined(__LP64__)
-  return ARCH_MIPS;
-#elif defined(__mips__) && defined(__LP64__)
-  return ARCH_MIPS64;
 #else
   abort();
 #endif
@@ -119,10 +115,6 @@
   regs = new RegsX86();
 #elif defined(__x86_64__)
   regs = new RegsX86_64();
-#elif defined(__mips__) && !defined(__LP64__)
-  regs = new RegsMips();
-#elif defined(__mips__) && defined(__LP64__)
-  regs = new RegsMips64();
 #else
   abort();
 #endif
diff --git a/libunwindstack/include/unwindstack/RegsGetLocal.h b/libunwindstack/include/unwindstack/RegsGetLocal.h
index f0b5e3a..300a3ec 100644
--- a/libunwindstack/include/unwindstack/RegsGetLocal.h
+++ b/libunwindstack/include/unwindstack/RegsGetLocal.h
@@ -81,7 +81,7 @@
       : "x12", "x13", "memory");
 }
 
-#elif defined(__i386__) || defined(__x86_64__) || defined(__mips__)
+#elif defined(__i386__) || defined(__x86_64__)
 
 extern "C" void AsmGetRegs(void* regs);
 
diff --git a/libutils/include/utils/String16.h b/libutils/include/utils/String16.h
index 013705b..1a4b47e 100644
--- a/libutils/include/utils/String16.h
+++ b/libutils/include/utils/String16.h
@@ -187,7 +187,7 @@
 ANDROID_TRIVIAL_MOVE_TRAIT(String16)
 
 static inline std::ostream& operator<<(std::ostream& os, const String16& str) {
-    os << String8(str).c_str();
+    os << String8(str);
     return os;
 }
 
diff --git a/libutils/include/utils/String8.h b/libutils/include/utils/String8.h
index d0ad314..0bcb716 100644
--- a/libutils/include/utils/String8.h
+++ b/libutils/include/utils/String8.h
@@ -17,7 +17,8 @@
 #ifndef ANDROID_STRING8_H
 #define ANDROID_STRING8_H
 
-#include <string> // for std::string
+#include <iostream>
+#include <string>
 
 #include <utils/Errors.h>
 #include <utils/Unicode.h>
@@ -232,6 +233,11 @@
 // require any change to the underlying SharedBuffer contents or reference count.
 ANDROID_TRIVIAL_MOVE_TRAIT(String8)
 
+static inline std::ostream& operator<<(std::ostream& os, const String8& str) {
+    os << str.c_str();
+    return os;
+}
+
 // ---------------------------------------------------------------------------
 // No user servicable parts below.
 
diff --git a/logwrapper/logwrap.cpp b/logwrapper/logwrap.cpp
index 5337801..5a518bc 100644
--- a/logwrapper/logwrap.cpp
+++ b/logwrapper/logwrap.cpp
@@ -374,7 +374,7 @@
     }
 
     if (log_target & LOG_FILE) {
-        fd = open(file_path, O_WRONLY | O_CREAT, 0664);
+        fd = open(file_path, O_WRONLY | O_CREAT | O_CLOEXEC, 0664);
         if (fd < 0) {
             ERROR("Cannot log to file %s\n", file_path);
             log_target &= ~LOG_FILE;
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 91dd7a5..fdc9d32 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -701,9 +701,7 @@
 
     # A tmpfs directory, which will contain all apps CE DE data directory that
     # bind mount from the original source.
-    chown root root /data_mirror
-    chmod 0700 /data_mirror
-    mount tmpfs tmpfs /data_mirror mode=0700,uid=0,gid=1000 nodev noexec nosuid
+    mount tmpfs tmpfs /data_mirror nodev noexec nosuid mode=0700,uid=0,gid=1000
     restorecon /data_mirror
     mkdir /data_mirror/data_ce 0700 root root
     mkdir /data_mirror/data_de 0700 root root
@@ -732,8 +730,15 @@
     # Create root dir for Incremental Service
     mkdir /data/incremental 0771 system system encryption=Require
 
+    # Create directories for statsd
+    mkdir /data/misc/stats-active-metric/ 0770 statsd system
+    mkdir /data/misc/stats-data/ 0770 statsd system
+    mkdir /data/misc/stats-metadata/ 0770 statsd system
+    mkdir /data/misc/stats-service/ 0770 statsd system
+    mkdir /data/misc/train-info/ 0770 statsd system
+
     # Wait for apexd to finish activating APEXes before starting more processes.
-    wait_for_prop apexd.status ready
+    wait_for_prop apexd.status activated
     perform_apex_config
 
     # Special-case /data/media/obb per b/64566063
@@ -748,7 +753,7 @@
     # Allow apexd to snapshot and restore device encrypted apex data in the case
     # of a rollback. This should be done immediately after DE_user data keys
     # are loaded. APEXes should not access this data until this has been
-    # completed.
+    # completed and apexd.status becomes "ready".
     exec_start apexd-snapshotde
 
     # Set SELinux security contexts on upgrade or policy update.
diff --git a/run-as/run-as.cpp b/run-as/run-as.cpp
index 432c434..cc92c68 100644
--- a/run-as/run-as.cpp
+++ b/run-as/run-as.cpp
@@ -247,12 +247,12 @@
 
   std::string seinfo = std::string(info.seinfo) + ":fromRunAs";
   if (selinux_android_setcontext(uid, 0, seinfo.c_str(), pkgname) < 0) {
-    error(1, errno, "couldn't set SELinux security context");
+    error(1, errno, "couldn't set SELinux security context '%s'", seinfo.c_str());
   }
 
   // cd into the data directory, and set $HOME correspondingly.
   if (TEMP_FAILURE_RETRY(chdir(info.data_dir)) == -1) {
-    error(1, errno, "couldn't chdir to package's data directory");
+    error(1, errno, "couldn't chdir to package's data directory '%s'", info.data_dir);
   }
   setenv("HOME", info.data_dir, 1);
 
diff --git a/trusty/keymaster/Android.bp b/trusty/keymaster/Android.bp
index f32a69e..6840baa 100644
--- a/trusty/keymaster/Android.bp
+++ b/trusty/keymaster/Android.bp
@@ -14,70 +14,6 @@
 // limitations under the License.
 //
 
-// WARNING: Everything listed here will be built on ALL platforms,
-// including x86, the emulator, and the SDK.  Modules must be uniquely
-// named (liblights.panda), and must build everywhere, or limit themselves
-// to only building on ARM if they include assembly. Individual makefiles
-// are responsible for having their own logic, for fine-grained control.
-
-// trusty_keymaster is a binary used only for on-device testing.  It
-// runs Trusty Keymaster through a basic set of operations with RSA
-// and ECDSA keys.
-cc_binary {
-    name: "trusty_keymaster_tipc",
-    vendor: true,
-    srcs: [
-        "ipc/trusty_keymaster_ipc.cpp",
-        "legacy/trusty_keymaster_device.cpp",
-        "legacy/trusty_keymaster_main.cpp",
-    ],
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-
-    local_include_dirs: ["include"],
-
-    shared_libs: [
-        "libcrypto",
-        "libcutils",
-        "libkeymaster_portable",
-        "libtrusty",
-        "libkeymaster_messages",
-        "libsoftkeymasterdevice",
-        "liblog",
-    ],
-}
-
-// keystore.trusty is the HAL used by keystore on Trusty devices.
-cc_library_shared {
-    name: "keystore.trusty",
-    vendor: true,
-    relative_install_path: "hw",
-    srcs: [
-        "ipc/trusty_keymaster_ipc.cpp",
-        "legacy/module.cpp",
-        "legacy/trusty_keymaster_device.cpp",
-    ],
-
-    cflags: [
-        "-fvisibility=hidden",
-        "-Wall",
-        "-Werror",
-    ],
-
-    local_include_dirs: ["include"],
-
-    shared_libs: [
-        "libcrypto",
-        "libkeymaster_messages",
-        "libtrusty",
-        "liblog",
-        "libcutils",
-    ],
-    header_libs: ["libhardware_headers"],
-}
-
 cc_binary {
     name: "android.hardware.keymaster@3.0-service.trusty",
     defaults: ["hidl_defaults"],
diff --git a/trusty/keymaster/legacy/Makefile b/trusty/keymaster/legacy/Makefile
deleted file mode 100644
index f575381..0000000
--- a/trusty/keymaster/legacy/Makefile
+++ /dev/null
@@ -1,199 +0,0 @@
-#####
-# Local unit test Makefile
-#
-# This makefile builds and runs the trusty_keymaster unit tests locally on the development
-# machine, not on an Android device.
-#
-# To build and run these tests, one pre-requisite must be manually installed: BoringSSL.
-# This Makefile expects to find BoringSSL in a directory adjacent to $ANDROID_BUILD_TOP.
-# To get and build it, first install the Ninja build tool (e.g. apt-get install
-# ninja-build), then do:
-#
-# cd $ANDROID_BUILD_TOP/..
-# git clone https://boringssl.googlesource.com/boringssl
-# cd boringssl
-# mdkir build
-# cd build
-# cmake -GNinja ..
-# ninja
-#
-# Then return to $ANDROID_BUILD_TOP/system/keymaster and run "make".
-#####
-
-BASE=../../../..
-SUBS=system/core \
-	system/keymaster \
-	hardware/libhardware \
-	external/gtest
-GTEST=$(BASE)/external/gtest
-KM=$(BASE)/system/keymaster
-
-INCLUDES=$(foreach dir,$(SUBS),-I $(BASE)/$(dir)/include) \
-	-I $(BASE)/libnativehelper/include/nativehelper \
-	-I ../tipc/include \
-	-I $(BASE)/system/keymaster \
-	-I $(GTEST) \
-	-I$(BASE)/../boringssl/include
-
-ifdef USE_CLANG
-CC=/usr/bin/clang
-CXX=/usr/bin/clang
-CLANG_TEST_DEFINE=-DKEYMASTER_CLANG_TEST_BUILD
-COMPILER_SPECIFIC_ARGS=-std=c++11 $(CLANG_TEST_DEFINE)
-else
-COMPILER_SPECIFIC_ARGS=-std=c++0x -fprofile-arcs
-endif
-
-CPPFLAGS=$(INCLUDES) -g -O0 -MD
-CXXFLAGS=-Wall -Werror -Wno-unused -Winit-self -Wpointer-arith	-Wunused-parameter \
-	-Wmissing-declarations -ftest-coverage \
-	-Wno-deprecated-declarations -fno-exceptions -DKEYMASTER_NAME_TAGS \
-	$(COMPILER_SPECIFIC_ARGS)
-LDLIBS=-L$(BASE)/../boringssl/build/crypto -lcrypto -lpthread -lstdc++
-
-CPPSRCS=\
-	$(KM)/aead_mode_operation.cpp \
-	$(KM)/aes_key.cpp \
-	$(KM)/aes_operation.cpp \
-	$(KM)/android_keymaster.cpp \
-	$(KM)/android_keymaster_messages.cpp \
-	$(KM)/android_keymaster_messages_test.cpp \
-	$(KM)/android_keymaster_test.cpp \
-	$(KM)/android_keymaster_test_utils.cpp \
-	$(KM)/android_keymaster_utils.cpp \
-	$(KM)/asymmetric_key.cpp \
-	$(KM)/auth_encrypted_key_blob.cpp \
-	$(KM)/auth_encrypted_key_blob.cpp \
-	$(KM)/authorization_set.cpp \
-	$(KM)/authorization_set_test.cpp \
-	$(KM)/ec_key.cpp \
-	$(KM)/ec_keymaster0_key.cpp \
-	$(KM)/ecdsa_operation.cpp \
-	$(KM)/hmac_key.cpp \
-	$(KM)/hmac_operation.cpp \
-	$(KM)/integrity_assured_key_blob.cpp \
-	$(KM)/key.cpp \
-	$(KM)/key_blob_test.cpp \
-	$(KM)/keymaster0_engine.cpp \
-	$(KM)/logger.cpp \
-	$(KM)/ocb_utils.cpp \
-	$(KM)/openssl_err.cpp \
-	$(KM)/openssl_utils.cpp \
-	$(KM)/operation.cpp \
-	$(KM)/operation_table.cpp \
-	$(KM)/rsa_key.cpp \
-	$(KM)/rsa_keymaster0_key.cpp \
-	$(KM)/rsa_operation.cpp \
-	$(KM)/serializable.cpp \
-	$(KM)/soft_keymaster_context.cpp \
-	$(KM)/symmetric_key.cpp \
-	$(KM)/unencrypted_key_blob.cpp \
-	trusty_keymaster_device.cpp \
-	trusty_keymaster_device_test.cpp
-CCSRCS=$(GTEST)/src/gtest-all.cc
-CSRCS=ocb.c
-
-OBJS=$(CPPSRCS:.cpp=.o) $(CCSRCS:.cc=.o) $(CSRCS:.c=.o)
-DEPS=$(CPPSRCS:.cpp=.d) $(CCSRCS:.cc=.d) $(CSRCS:.c=.d)
-GCDA=$(CPPSRCS:.cpp=.gcda) $(CCSRCS:.cc=.gcda) $(CSRCS:.c=.gcda)
-GCNO=$(CPPSRCS:.cpp=.gcno) $(CCSRCS:.cc=.gcno) $(CSRCS:.c=.gcno)
-
-LINK.o=$(LINK.cc)
-
-BINARIES=trusty_keymaster_device_test
-
-ifdef TRUSTY
-BINARIES += trusty_keymaster_device_test
-endif # TRUSTY
-
-.PHONY: coverage memcheck massif clean run
-
-%.run: %
-	./$<
-	touch $@
-
-run: $(BINARIES:=.run)
-
-coverage: coverage.info
-	genhtml coverage.info --output-directory coverage
-
-coverage.info: run
-	lcov --capture --directory=. --output-file coverage.info
-
-%.coverage : %
-	$(MAKE) clean && $(MAKE) $<
-	./$<
-	lcov --capture --directory=. --output-file coverage.info
-	genhtml coverage.info --output-directory coverage
-
-#UNINIT_OPTS=--track-origins=yes
-UNINIT_OPTS=--undef-value-errors=no
-
-MEMCHECK_OPTS=--leak-check=full \
-	--show-reachable=yes \
-	--vgdb=full \
-	$(UNINIT_OPTS) \
-	--error-exitcode=1
-
-MASSIF_OPTS=--tool=massif \
-	--stacks=yes
-
-%.memcheck : %
-	valgrind $(MEMCHECK_OPTS) ./$< && \
-	touch $@
-
-%.massif : %
-	valgrind $(MASSIF_OPTS) --massif-out-file=$@ ./$<
-
-memcheck: $(BINARIES:=.memcheck)
-
-massif: $(BINARIES:=.massif)
-
-trusty_keymaster_device_test: trusty_keymaster_device_test.o \
-	trusty_keymaster_device.o \
-	$(KM)/aead_mode_operation.o \
-	$(KM)/aes_key.o \
-	$(KM)/aes_operation.o \
-	$(KM)/android_keymaster.o \
-	$(KM)/android_keymaster_messages.o \
-	$(KM)/android_keymaster_test_utils.o \
-	$(KM)/android_keymaster_utils.o \
-	$(KM)/asymmetric_key.o \
-	$(KM)/auth_encrypted_key_blob.o \
-	$(KM)/auth_encrypted_key_blob.o \
-	$(KM)/authorization_set.o \
-	$(KM)/ec_key.o \
-	$(KM)/ec_keymaster0_key.cpp \
-	$(KM)/ecdsa_operation.o \
-	$(KM)/hmac_key.o \
-	$(KM)/hmac_operation.o \
-	$(KM)/integrity_assured_key_blob.o \
-	$(KM)/key.o \
-	$(KM)/keymaster0_engine.o \
-	$(KM)/logger.o \
-	$(KM)/ocb.o \
-	$(KM)/ocb_utils.o \
-	$(KM)/openssl_err.o \
-	$(KM)/openssl_utils.o \
-	$(KM)/operation.o \
-	$(KM)/operation_table.o \
-	$(KM)/rsa_key.o \
-	$(KM)/rsa_keymaster0_key.o \
-	$(KM)/rsa_operation.o \
-	$(KM)/serializable.o \
-	$(KM)/soft_keymaster_context.o \
-	$(KM)/symmetric_key.o \
-	$(GTEST)/src/gtest-all.o
-
-$(GTEST)/src/gtest-all.o: CXXFLAGS:=$(subst -Wmissing-declarations,,$(CXXFLAGS))
-ocb.o: CFLAGS=$(CLANG_TEST_DEFINE)
-
-clean:
-	rm -f $(OBJS) $(DEPS) $(GCDA) $(GCNO) $(BINARIES) \
-		$(BINARIES:=.run) $(BINARIES:=.memcheck) $(BINARIES:=.massif) \
-		coverage.info
-	rm -rf coverage
-
--include $(CPPSRCS:.cpp=.d)
--include $(CCSRCS:.cc=.d)
-
diff --git a/trusty/keymaster/legacy/module.cpp b/trusty/keymaster/legacy/module.cpp
deleted file mode 100644
index 7aa1a4e..0000000
--- a/trusty/keymaster/legacy/module.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2014 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 <errno.h>
-#include <string.h>
-
-#include <hardware/hardware.h>
-#include <hardware/keymaster0.h>
-
-#include <trusty_keymaster/legacy/trusty_keymaster_device.h>
-
-using keymaster::TrustyKeymasterDevice;
-
-/*
- * Generic device handling
- */
-static int trusty_keymaster_open(const hw_module_t* module, const char* name,
-                                 hw_device_t** device) {
-    if (strcmp(name, KEYSTORE_KEYMASTER) != 0) {
-        return -EINVAL;
-    }
-
-    TrustyKeymasterDevice* dev = new TrustyKeymasterDevice(module);
-    if (dev == NULL) {
-        return -ENOMEM;
-    }
-    *device = dev->hw_device();
-    // Do not delete dev; it will get cleaned up when the caller calls device->close(), and must
-    // exist until then.
-    return 0;
-}
-
-static struct hw_module_methods_t keystore_module_methods = {
-        .open = trusty_keymaster_open,
-};
-
-struct keystore_module HAL_MODULE_INFO_SYM __attribute__((visibility("default"))) = {
-        .common =
-                {
-                        .tag = HARDWARE_MODULE_TAG,
-                        .module_api_version = KEYMASTER_MODULE_API_VERSION_2_0,
-                        .hal_api_version = HARDWARE_HAL_API_VERSION,
-                        .id = KEYSTORE_HARDWARE_MODULE_ID,
-                        .name = "Trusty Keymaster HAL",
-                        .author = "The Android Open Source Project",
-                        .methods = &keystore_module_methods,
-                        .dso = 0,
-                        .reserved = {},
-                },
-};
diff --git a/trusty/keymaster/legacy/trusty_keymaster_device.cpp b/trusty/keymaster/legacy/trusty_keymaster_device.cpp
deleted file mode 100644
index 88c3e7b..0000000
--- a/trusty/keymaster/legacy/trusty_keymaster_device.cpp
+++ /dev/null
@@ -1,761 +0,0 @@
-/*
- * Copyright 2014 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 "TrustyKeymaster"
-
-#include <assert.h>
-#include <errno.h>
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <algorithm>
-#include <type_traits>
-
-#include <hardware/keymaster2.h>
-#include <keymaster/authorization_set.h>
-#include <log/log.h>
-
-#include <trusty_keymaster/ipc/keymaster_ipc.h>
-#include <trusty_keymaster/ipc/trusty_keymaster_ipc.h>
-#include <trusty_keymaster/legacy/trusty_keymaster_device.h>
-
-const size_t kMaximumAttestationChallengeLength = 128;
-const size_t kMaximumFinishInputLength = 2048;
-
-namespace keymaster {
-
-TrustyKeymasterDevice::TrustyKeymasterDevice(const hw_module_t* module) {
-    static_assert(std::is_standard_layout<TrustyKeymasterDevice>::value,
-                  "TrustyKeymasterDevice must be standard layout");
-    static_assert(offsetof(TrustyKeymasterDevice, device_) == 0,
-                  "device_ must be the first member of TrustyKeymasterDevice");
-    static_assert(offsetof(TrustyKeymasterDevice, device_.common) == 0,
-                  "common must be the first member of keymaster2_device");
-
-    ALOGI("Creating device");
-    ALOGD("Device address: %p", this);
-
-    device_ = {};
-
-    device_.common.tag = HARDWARE_DEVICE_TAG;
-    device_.common.version = 1;
-    device_.common.module = const_cast<hw_module_t*>(module);
-    device_.common.close = close_device;
-
-    device_.flags = KEYMASTER_SUPPORTS_EC;
-
-    device_.configure = configure;
-    device_.add_rng_entropy = add_rng_entropy;
-    device_.generate_key = generate_key;
-    device_.get_key_characteristics = get_key_characteristics;
-    device_.import_key = import_key;
-    device_.export_key = export_key;
-    device_.attest_key = attest_key;
-    device_.upgrade_key = upgrade_key;
-    device_.delete_key = delete_key;
-    device_.delete_all_keys = delete_all_keys;
-    device_.begin = begin;
-    device_.update = update;
-    device_.finish = finish;
-    device_.abort = abort;
-
-    int rc = trusty_keymaster_connect();
-    error_ = translate_error(rc);
-    if (rc < 0) {
-        ALOGE("failed to connect to keymaster (%d)", rc);
-        return;
-    }
-
-    GetVersionRequest version_request;
-    GetVersionResponse version_response;
-    error_ = trusty_keymaster_send(KM_GET_VERSION, version_request, &version_response);
-    if (error_ == KM_ERROR_INVALID_ARGUMENT || error_ == KM_ERROR_UNIMPLEMENTED) {
-        ALOGE("\"Bad parameters\" error on GetVersion call.  Version 0 is not supported.");
-        error_ = KM_ERROR_VERSION_MISMATCH;
-        return;
-    }
-    message_version_ = MessageVersion(version_response.major_ver, version_response.minor_ver,
-                                      version_response.subminor_ver);
-    if (message_version_ < 0) {
-        // Can't translate version?  Keymaster implementation must be newer.
-        ALOGE("Keymaster version %d.%d.%d not supported.", version_response.major_ver,
-              version_response.minor_ver, version_response.subminor_ver);
-        error_ = KM_ERROR_VERSION_MISMATCH;
-    }
-}
-
-TrustyKeymasterDevice::~TrustyKeymasterDevice() {
-    trusty_keymaster_disconnect();
-}
-
-namespace {
-
-// Allocates a new buffer with malloc and copies the contents of |buffer| to it. Caller takes
-// ownership of the returned buffer.
-uint8_t* DuplicateBuffer(const uint8_t* buffer, size_t size) {
-    uint8_t* tmp = reinterpret_cast<uint8_t*>(malloc(size));
-    if (tmp) {
-        memcpy(tmp, buffer, size);
-    }
-    return tmp;
-}
-
-template <typename RequestType>
-void AddClientAndAppData(const keymaster_blob_t* client_id, const keymaster_blob_t* app_data,
-                         RequestType* request) {
-    request->additional_params.Clear();
-    if (client_id && client_id->data_length > 0) {
-        request->additional_params.push_back(TAG_APPLICATION_ID, *client_id);
-    }
-    if (app_data && app_data->data_length > 0) {
-        request->additional_params.push_back(TAG_APPLICATION_DATA, *app_data);
-    }
-}
-
-}  //  unnamed namespace
-
-keymaster_error_t TrustyKeymasterDevice::configure(const keymaster_key_param_set_t* params) {
-    ALOGD("Device received configure\n");
-
-    if (error_ != KM_ERROR_OK) {
-        return error_;
-    }
-    if (!params) {
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-    }
-
-    AuthorizationSet params_copy(*params);
-    ConfigureRequest request(message_version_);
-    if (!params_copy.GetTagValue(TAG_OS_VERSION, &request.os_version) ||
-        !params_copy.GetTagValue(TAG_OS_PATCHLEVEL, &request.os_patchlevel)) {
-        ALOGD("Configuration parameters must contain OS version and patch level");
-        return KM_ERROR_INVALID_ARGUMENT;
-    }
-
-    ConfigureResponse response(message_version_);
-    keymaster_error_t err = trusty_keymaster_send(KM_CONFIGURE, request, &response);
-    if (err != KM_ERROR_OK) {
-        return err;
-    }
-
-    return KM_ERROR_OK;
-}
-
-keymaster_error_t TrustyKeymasterDevice::add_rng_entropy(const uint8_t* data, size_t data_length) {
-    ALOGD("Device received add_rng_entropy");
-
-    if (error_ != KM_ERROR_OK) {
-        return error_;
-    }
-
-    AddEntropyRequest request(message_version_);
-    request.random_data.Reinitialize(data, data_length);
-    AddEntropyResponse response(message_version_);
-    return trusty_keymaster_send(KM_ADD_RNG_ENTROPY, request, &response);
-}
-
-keymaster_error_t TrustyKeymasterDevice::generate_key(
-        const keymaster_key_param_set_t* params, keymaster_key_blob_t* key_blob,
-        keymaster_key_characteristics_t* characteristics) {
-    ALOGD("Device received generate_key");
-
-    if (error_ != KM_ERROR_OK) {
-        return error_;
-    }
-    if (!params) {
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-    }
-    if (!key_blob) {
-        return KM_ERROR_OUTPUT_PARAMETER_NULL;
-    }
-
-    GenerateKeyRequest request(message_version_);
-    request.key_description.Reinitialize(*params);
-    request.key_description.push_back(TAG_CREATION_DATETIME, java_time(time(NULL)));
-
-    GenerateKeyResponse response(message_version_);
-    keymaster_error_t err = trusty_keymaster_send(KM_GENERATE_KEY, request, &response);
-    if (err != KM_ERROR_OK) {
-        return err;
-    }
-
-    key_blob->key_material_size = response.key_blob.key_material_size;
-    key_blob->key_material =
-            DuplicateBuffer(response.key_blob.key_material, response.key_blob.key_material_size);
-    if (!key_blob->key_material) {
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-    }
-
-    if (characteristics) {
-        response.enforced.CopyToParamSet(&characteristics->hw_enforced);
-        response.unenforced.CopyToParamSet(&characteristics->sw_enforced);
-    }
-
-    return KM_ERROR_OK;
-}
-
-keymaster_error_t TrustyKeymasterDevice::get_key_characteristics(
-        const keymaster_key_blob_t* key_blob, const keymaster_blob_t* client_id,
-        const keymaster_blob_t* app_data, keymaster_key_characteristics_t* characteristics) {
-    ALOGD("Device received get_key_characteristics");
-
-    if (error_ != KM_ERROR_OK) {
-        return error_;
-    }
-    if (!key_blob || !key_blob->key_material) {
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-    }
-    if (!characteristics) {
-        return KM_ERROR_OUTPUT_PARAMETER_NULL;
-    }
-
-    GetKeyCharacteristicsRequest request(message_version_);
-    request.SetKeyMaterial(*key_blob);
-    AddClientAndAppData(client_id, app_data, &request);
-
-    GetKeyCharacteristicsResponse response(message_version_);
-    keymaster_error_t err = trusty_keymaster_send(KM_GET_KEY_CHARACTERISTICS, request, &response);
-    if (err != KM_ERROR_OK) {
-        return err;
-    }
-
-    response.enforced.CopyToParamSet(&characteristics->hw_enforced);
-    response.unenforced.CopyToParamSet(&characteristics->sw_enforced);
-
-    return KM_ERROR_OK;
-}
-
-keymaster_error_t TrustyKeymasterDevice::import_key(
-        const keymaster_key_param_set_t* params, keymaster_key_format_t key_format,
-        const keymaster_blob_t* key_data, keymaster_key_blob_t* key_blob,
-        keymaster_key_characteristics_t* characteristics) {
-    ALOGD("Device received import_key");
-
-    if (error_ != KM_ERROR_OK) {
-        return error_;
-    }
-    if (!params || !key_data) {
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-    }
-    if (!key_blob) {
-        return KM_ERROR_OUTPUT_PARAMETER_NULL;
-    }
-
-    ImportKeyRequest request(message_version_);
-    request.key_description.Reinitialize(*params);
-    request.key_description.push_back(TAG_CREATION_DATETIME, java_time(time(NULL)));
-
-    request.key_format = key_format;
-    request.SetKeyMaterial(key_data->data, key_data->data_length);
-
-    ImportKeyResponse response(message_version_);
-    keymaster_error_t err = trusty_keymaster_send(KM_IMPORT_KEY, request, &response);
-    if (err != KM_ERROR_OK) {
-        return err;
-    }
-
-    key_blob->key_material_size = response.key_blob.key_material_size;
-    key_blob->key_material =
-            DuplicateBuffer(response.key_blob.key_material, response.key_blob.key_material_size);
-    if (!key_blob->key_material) {
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-    }
-
-    if (characteristics) {
-        response.enforced.CopyToParamSet(&characteristics->hw_enforced);
-        response.unenforced.CopyToParamSet(&characteristics->sw_enforced);
-    }
-
-    return KM_ERROR_OK;
-}
-
-keymaster_error_t TrustyKeymasterDevice::export_key(keymaster_key_format_t export_format,
-                                                    const keymaster_key_blob_t* key_to_export,
-                                                    const keymaster_blob_t* client_id,
-                                                    const keymaster_blob_t* app_data,
-                                                    keymaster_blob_t* export_data) {
-    ALOGD("Device received export_key");
-
-    if (error_ != KM_ERROR_OK) {
-        return error_;
-    }
-    if (!key_to_export || !key_to_export->key_material) {
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-    }
-    if (!export_data) {
-        return KM_ERROR_OUTPUT_PARAMETER_NULL;
-    }
-
-    export_data->data = nullptr;
-    export_data->data_length = 0;
-
-    ExportKeyRequest request(message_version_);
-    request.key_format = export_format;
-    request.SetKeyMaterial(*key_to_export);
-    AddClientAndAppData(client_id, app_data, &request);
-
-    ExportKeyResponse response(message_version_);
-    keymaster_error_t err = trusty_keymaster_send(KM_EXPORT_KEY, request, &response);
-    if (err != KM_ERROR_OK) {
-        return err;
-    }
-
-    export_data->data_length = response.key_data_length;
-    export_data->data = DuplicateBuffer(response.key_data, response.key_data_length);
-    if (!export_data->data) {
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-    }
-
-    return KM_ERROR_OK;
-}
-
-keymaster_error_t TrustyKeymasterDevice::attest_key(const keymaster_key_blob_t* key_to_attest,
-                                                    const keymaster_key_param_set_t* attest_params,
-                                                    keymaster_cert_chain_t* cert_chain) {
-    ALOGD("Device received attest_key");
-
-    if (error_ != KM_ERROR_OK) {
-        return error_;
-    }
-    if (!key_to_attest || !attest_params) {
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-    }
-    if (!cert_chain) {
-        return KM_ERROR_OUTPUT_PARAMETER_NULL;
-    }
-
-    cert_chain->entry_count = 0;
-    cert_chain->entries = nullptr;
-
-    AttestKeyRequest request(message_version_);
-    request.SetKeyMaterial(*key_to_attest);
-    request.attest_params.Reinitialize(*attest_params);
-
-    keymaster_blob_t attestation_challenge = {};
-    request.attest_params.GetTagValue(TAG_ATTESTATION_CHALLENGE, &attestation_challenge);
-    if (attestation_challenge.data_length > kMaximumAttestationChallengeLength) {
-        ALOGE("%zu-byte attestation challenge; only %zu bytes allowed",
-              attestation_challenge.data_length, kMaximumAttestationChallengeLength);
-        return KM_ERROR_INVALID_INPUT_LENGTH;
-    }
-
-    AttestKeyResponse response(message_version_);
-    keymaster_error_t err = trusty_keymaster_send(KM_ATTEST_KEY, request, &response);
-    if (err != KM_ERROR_OK) {
-        return err;
-    }
-
-    // Allocate and clear storage for cert_chain.
-    keymaster_cert_chain_t& rsp_chain = response.certificate_chain;
-    cert_chain->entries = reinterpret_cast<keymaster_blob_t*>(
-            malloc(rsp_chain.entry_count * sizeof(*cert_chain->entries)));
-    if (!cert_chain->entries) {
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-    }
-    cert_chain->entry_count = rsp_chain.entry_count;
-    for (keymaster_blob_t& entry : array_range(cert_chain->entries, cert_chain->entry_count)) {
-        entry = {};
-    }
-
-    // Copy cert_chain contents
-    size_t i = 0;
-    for (keymaster_blob_t& entry : array_range(rsp_chain.entries, rsp_chain.entry_count)) {
-        cert_chain->entries[i].data = DuplicateBuffer(entry.data, entry.data_length);
-        if (!cert_chain->entries[i].data) {
-            keymaster_free_cert_chain(cert_chain);
-            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-        }
-        cert_chain->entries[i].data_length = entry.data_length;
-        ++i;
-    }
-
-    return KM_ERROR_OK;
-}
-
-keymaster_error_t TrustyKeymasterDevice::upgrade_key(
-        const keymaster_key_blob_t* key_to_upgrade, const keymaster_key_param_set_t* upgrade_params,
-        keymaster_key_blob_t* upgraded_key) {
-    ALOGD("Device received upgrade_key");
-
-    if (error_ != KM_ERROR_OK) {
-        return error_;
-    }
-    if (!key_to_upgrade || !upgrade_params) {
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-    }
-    if (!upgraded_key) {
-        return KM_ERROR_OUTPUT_PARAMETER_NULL;
-    }
-
-    UpgradeKeyRequest request(message_version_);
-    request.SetKeyMaterial(*key_to_upgrade);
-    request.upgrade_params.Reinitialize(*upgrade_params);
-
-    UpgradeKeyResponse response(message_version_);
-    keymaster_error_t err = trusty_keymaster_send(KM_UPGRADE_KEY, request, &response);
-    if (err != KM_ERROR_OK) {
-        return err;
-    }
-
-    upgraded_key->key_material_size = response.upgraded_key.key_material_size;
-    upgraded_key->key_material = DuplicateBuffer(response.upgraded_key.key_material,
-                                                 response.upgraded_key.key_material_size);
-    if (!upgraded_key->key_material) {
-        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-    }
-
-    return KM_ERROR_OK;
-}
-
-keymaster_error_t TrustyKeymasterDevice::begin(keymaster_purpose_t purpose,
-                                               const keymaster_key_blob_t* key,
-                                               const keymaster_key_param_set_t* in_params,
-                                               keymaster_key_param_set_t* out_params,
-                                               keymaster_operation_handle_t* operation_handle) {
-    ALOGD("Device received begin");
-
-    if (error_ != KM_ERROR_OK) {
-        return error_;
-    }
-    if (!key || !key->key_material) {
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-    }
-    if (!operation_handle) {
-        return KM_ERROR_OUTPUT_PARAMETER_NULL;
-    }
-
-    if (out_params) {
-        *out_params = {};
-    }
-
-    BeginOperationRequest request(message_version_);
-    request.purpose = purpose;
-    request.SetKeyMaterial(*key);
-    request.additional_params.Reinitialize(*in_params);
-
-    BeginOperationResponse response(message_version_);
-    keymaster_error_t err = trusty_keymaster_send(KM_BEGIN_OPERATION, request, &response);
-    if (err != KM_ERROR_OK) {
-        return err;
-    }
-
-    if (response.output_params.size() > 0) {
-        if (out_params) {
-            response.output_params.CopyToParamSet(out_params);
-        } else {
-            return KM_ERROR_OUTPUT_PARAMETER_NULL;
-        }
-    }
-    *operation_handle = response.op_handle;
-
-    return KM_ERROR_OK;
-}
-
-keymaster_error_t TrustyKeymasterDevice::update(keymaster_operation_handle_t operation_handle,
-                                                const keymaster_key_param_set_t* in_params,
-                                                const keymaster_blob_t* input,
-                                                size_t* input_consumed,
-                                                keymaster_key_param_set_t* out_params,
-                                                keymaster_blob_t* output) {
-    ALOGD("Device received update");
-
-    if (error_ != KM_ERROR_OK) {
-        return error_;
-    }
-    if (!input) {
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-    }
-    if (!input_consumed) {
-        return KM_ERROR_OUTPUT_PARAMETER_NULL;
-    }
-
-    if (out_params) {
-        *out_params = {};
-    }
-    if (output) {
-        *output = {};
-    }
-
-    UpdateOperationRequest request(message_version_);
-    request.op_handle = operation_handle;
-    if (in_params) {
-        request.additional_params.Reinitialize(*in_params);
-    }
-    if (input && input->data_length > 0) {
-        size_t max_input_size = TRUSTY_KEYMASTER_SEND_BUF_SIZE - request.SerializedSize();
-        request.input.Reinitialize(input->data, std::min(input->data_length, max_input_size));
-    }
-
-    UpdateOperationResponse response(message_version_);
-    keymaster_error_t err = trusty_keymaster_send(KM_UPDATE_OPERATION, request, &response);
-    if (err != KM_ERROR_OK) {
-        return err;
-    }
-
-    if (response.output_params.size() > 0) {
-        if (out_params) {
-            response.output_params.CopyToParamSet(out_params);
-        } else {
-            return KM_ERROR_OUTPUT_PARAMETER_NULL;
-        }
-    }
-    *input_consumed = response.input_consumed;
-    if (output) {
-        output->data_length = response.output.available_read();
-        output->data = DuplicateBuffer(response.output.peek_read(), output->data_length);
-        if (!output->data) {
-            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-        }
-    } else if (response.output.available_read() > 0) {
-        return KM_ERROR_OUTPUT_PARAMETER_NULL;
-    }
-
-    return KM_ERROR_OK;
-}
-
-keymaster_error_t TrustyKeymasterDevice::finish(keymaster_operation_handle_t operation_handle,
-                                                const keymaster_key_param_set_t* in_params,
-                                                const keymaster_blob_t* input,
-                                                const keymaster_blob_t* signature,
-                                                keymaster_key_param_set_t* out_params,
-                                                keymaster_blob_t* output) {
-    ALOGD("Device received finish");
-
-    if (error_ != KM_ERROR_OK) {
-        return error_;
-    }
-    if (input && input->data_length > kMaximumFinishInputLength) {
-        ALOGE("%zu-byte input to finish; only %zu bytes allowed", input->data_length,
-              kMaximumFinishInputLength);
-        return KM_ERROR_INVALID_INPUT_LENGTH;
-    }
-
-    if (out_params) {
-        *out_params = {};
-    }
-    if (output) {
-        *output = {};
-    }
-
-    FinishOperationRequest request(message_version_);
-    request.op_handle = operation_handle;
-    if (signature && signature->data && signature->data_length > 0) {
-        request.signature.Reinitialize(signature->data, signature->data_length);
-    }
-    if (input && input->data && input->data_length) {
-        request.input.Reinitialize(input->data, input->data_length);
-    }
-    if (in_params) {
-        request.additional_params.Reinitialize(*in_params);
-    }
-
-    FinishOperationResponse response(message_version_);
-    keymaster_error_t err = trusty_keymaster_send(KM_FINISH_OPERATION, request, &response);
-    if (err != KM_ERROR_OK) {
-        return err;
-    }
-
-    if (response.output_params.size() > 0) {
-        if (out_params) {
-            response.output_params.CopyToParamSet(out_params);
-        } else {
-            return KM_ERROR_OUTPUT_PARAMETER_NULL;
-        }
-    }
-    if (output) {
-        output->data_length = response.output.available_read();
-        output->data = DuplicateBuffer(response.output.peek_read(), output->data_length);
-        if (!output->data) {
-            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
-        }
-    } else if (response.output.available_read() > 0) {
-        return KM_ERROR_OUTPUT_PARAMETER_NULL;
-    }
-
-    return KM_ERROR_OK;
-}
-
-keymaster_error_t TrustyKeymasterDevice::abort(keymaster_operation_handle_t operation_handle) {
-    ALOGD("Device received abort");
-
-    if (error_ != KM_ERROR_OK) {
-        return error_;
-    }
-
-    AbortOperationRequest request(message_version_);
-    request.op_handle = operation_handle;
-    AbortOperationResponse response(message_version_);
-    return trusty_keymaster_send(KM_ABORT_OPERATION, request, &response);
-}
-
-keymaster_error_t TrustyKeymasterDevice::delete_key(const keymaster_key_blob_t* key) {
-    ALOGD("Device received delete_key");
-
-    if (error_ != KM_ERROR_OK) {
-        return error_;
-    }
-
-    if (!key || !key->key_material)
-        return KM_ERROR_UNEXPECTED_NULL_POINTER;
-
-    DeleteKeyRequest request(message_version_);
-    request.SetKeyMaterial(*key);
-    DeleteKeyResponse response(message_version_);
-    return trusty_keymaster_send(KM_DELETE_KEY, request, &response);
-}
-
-keymaster_error_t TrustyKeymasterDevice::delete_all_keys() {
-    ALOGD("Device received delete_all_key");
-
-    if (error_ != KM_ERROR_OK) {
-        return error_;
-    }
-
-    DeleteAllKeysRequest request(message_version_);
-    DeleteAllKeysResponse response(message_version_);
-    return trusty_keymaster_send(KM_DELETE_ALL_KEYS, request, &response);
-}
-
-hw_device_t* TrustyKeymasterDevice::hw_device() {
-    return &device_.common;
-}
-
-static inline TrustyKeymasterDevice* convert_device(const keymaster2_device_t* dev) {
-    return reinterpret_cast<TrustyKeymasterDevice*>(const_cast<keymaster2_device_t*>(dev));
-}
-
-/* static */
-int TrustyKeymasterDevice::close_device(hw_device_t* dev) {
-    delete reinterpret_cast<TrustyKeymasterDevice*>(dev);
-    return 0;
-}
-
-/* static */
-keymaster_error_t TrustyKeymasterDevice::configure(const keymaster2_device_t* dev,
-                                                   const keymaster_key_param_set_t* params) {
-    return convert_device(dev)->configure(params);
-}
-
-/* static */
-keymaster_error_t TrustyKeymasterDevice::add_rng_entropy(const keymaster2_device_t* dev,
-                                                         const uint8_t* data, size_t data_length) {
-    return convert_device(dev)->add_rng_entropy(data, data_length);
-}
-
-/* static */
-keymaster_error_t TrustyKeymasterDevice::generate_key(
-        const keymaster2_device_t* dev, const keymaster_key_param_set_t* params,
-        keymaster_key_blob_t* key_blob, keymaster_key_characteristics_t* characteristics) {
-    return convert_device(dev)->generate_key(params, key_blob, characteristics);
-}
-
-/* static */
-keymaster_error_t TrustyKeymasterDevice::get_key_characteristics(
-        const keymaster2_device_t* dev, const keymaster_key_blob_t* key_blob,
-        const keymaster_blob_t* client_id, const keymaster_blob_t* app_data,
-        keymaster_key_characteristics_t* characteristics) {
-    return convert_device(dev)->get_key_characteristics(key_blob, client_id, app_data,
-                                                        characteristics);
-}
-
-/* static */
-keymaster_error_t TrustyKeymasterDevice::import_key(
-        const keymaster2_device_t* dev, const keymaster_key_param_set_t* params,
-        keymaster_key_format_t key_format, const keymaster_blob_t* key_data,
-        keymaster_key_blob_t* key_blob, keymaster_key_characteristics_t* characteristics) {
-    return convert_device(dev)->import_key(params, key_format, key_data, key_blob, characteristics);
-}
-
-/* static */
-keymaster_error_t TrustyKeymasterDevice::export_key(const keymaster2_device_t* dev,
-                                                    keymaster_key_format_t export_format,
-                                                    const keymaster_key_blob_t* key_to_export,
-                                                    const keymaster_blob_t* client_id,
-                                                    const keymaster_blob_t* app_data,
-                                                    keymaster_blob_t* export_data) {
-    return convert_device(dev)->export_key(export_format, key_to_export, client_id, app_data,
-                                           export_data);
-}
-
-/* static */
-keymaster_error_t TrustyKeymasterDevice::attest_key(const keymaster2_device_t* dev,
-                                                    const keymaster_key_blob_t* key_to_attest,
-                                                    const keymaster_key_param_set_t* attest_params,
-                                                    keymaster_cert_chain_t* cert_chain) {
-    return convert_device(dev)->attest_key(key_to_attest, attest_params, cert_chain);
-}
-
-/* static */
-keymaster_error_t TrustyKeymasterDevice::upgrade_key(
-        const keymaster2_device_t* dev, const keymaster_key_blob_t* key_to_upgrade,
-        const keymaster_key_param_set_t* upgrade_params, keymaster_key_blob_t* upgraded_key) {
-    return convert_device(dev)->upgrade_key(key_to_upgrade, upgrade_params, upgraded_key);
-}
-
-/* static */
-keymaster_error_t TrustyKeymasterDevice::begin(const keymaster2_device_t* dev,
-                                               keymaster_purpose_t purpose,
-                                               const keymaster_key_blob_t* key,
-                                               const keymaster_key_param_set_t* in_params,
-                                               keymaster_key_param_set_t* out_params,
-                                               keymaster_operation_handle_t* operation_handle) {
-    return convert_device(dev)->begin(purpose, key, in_params, out_params, operation_handle);
-}
-
-/* static */
-keymaster_error_t TrustyKeymasterDevice::update(
-        const keymaster2_device_t* dev, keymaster_operation_handle_t operation_handle,
-        const keymaster_key_param_set_t* in_params, const keymaster_blob_t* input,
-        size_t* input_consumed, keymaster_key_param_set_t* out_params, keymaster_blob_t* output) {
-    return convert_device(dev)->update(operation_handle, in_params, input, input_consumed,
-                                       out_params, output);
-}
-
-/* static */
-keymaster_error_t TrustyKeymasterDevice::finish(const keymaster2_device_t* dev,
-                                                keymaster_operation_handle_t operation_handle,
-                                                const keymaster_key_param_set_t* in_params,
-                                                const keymaster_blob_t* input,
-                                                const keymaster_blob_t* signature,
-                                                keymaster_key_param_set_t* out_params,
-                                                keymaster_blob_t* output) {
-    return convert_device(dev)->finish(operation_handle, in_params, input, signature, out_params,
-                                       output);
-}
-
-/* static */
-keymaster_error_t TrustyKeymasterDevice::abort(const keymaster2_device_t* dev,
-                                               keymaster_operation_handle_t operation_handle) {
-    return convert_device(dev)->abort(operation_handle);
-}
-
-/* static */
-keymaster_error_t TrustyKeymasterDevice::delete_key(const keymaster2_device_t* dev,
-                                               const keymaster_key_blob_t* key) {
-   return convert_device(dev)->delete_key(key);
-}
-
-/* static */
-keymaster_error_t TrustyKeymasterDevice::delete_all_keys(const keymaster2_device_t* dev) {
-   return convert_device(dev)->delete_all_keys();
-}
-
-}  // namespace keymaster
diff --git a/trusty/keymaster/legacy/trusty_keymaster_device_test.cpp b/trusty/keymaster/legacy/trusty_keymaster_device_test.cpp
deleted file mode 100644
index 68def58..0000000
--- a/trusty/keymaster/legacy/trusty_keymaster_device_test.cpp
+++ /dev/null
@@ -1,561 +0,0 @@
-/*
- * Copyright (C) 2014 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 <algorithm>
-#include <fstream>
-#include <memory>
-
-#include <gtest/gtest.h>
-#include <openssl/engine.h>
-
-#include <hardware/keymaster0.h>
-
-#include <keymaster/android_keymaster.h>
-#include <keymaster/android_keymaster_messages.h>
-#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/keymaster_tags.h>
-#include <keymaster/soft_keymaster_context.h>
-
-#include <trusty_keymaster/legacy/trusty_keymaster_device.h>
-#include "android_keymaster_test_utils.h"
-#include "openssl_utils.h"
-
-using std::ifstream;
-using std::istreambuf_iterator;
-using std::string;
-
-static keymaster::AndroidKeymaster* impl_ = nullptr;
-
-extern "C" {
-int __android_log_print();
-}
-
-int __android_log_print() {
-    return 0;
-}
-
-int main(int argc, char** argv) {
-    ::testing::InitGoogleTest(&argc, argv);
-    int result = RUN_ALL_TESTS();
-    // Clean up stuff OpenSSL leaves around, so Valgrind doesn't complain.
-    CRYPTO_cleanup_all_ex_data();
-    ERR_free_strings();
-    return result;
-}
-
-int trusty_keymaster_connect() {
-    impl_ = new keymaster::AndroidKeymaster(new keymaster::SoftKeymasterContext(nullptr), 16);
-}
-
-void trusty_keymaster_disconnect() {
-    delete static_cast<keymaster::AndroidKeymaster*>(priv_);
-}
-
-template <typename Req, typename Rsp>
-static int fake_call(keymaster::AndroidKeymaster* device,
-                     void (keymaster::AndroidKeymaster::*method)(const Req&, Rsp*), void* in_buf,
-                     uint32_t in_size, void* out_buf, uint32_t* out_size) {
-    Req req;
-    const uint8_t* in = static_cast<uint8_t*>(in_buf);
-    req.Deserialize(&in, in + in_size);
-    Rsp rsp;
-    (device->*method)(req, &rsp);
-
-    *out_size = rsp.SerializedSize();
-    uint8_t* out = static_cast<uint8_t*>(out_buf);
-    rsp.Serialize(out, out + *out_size);
-    return 0;
-}
-
-int trusty_keymaster_call(uint32_t cmd, void* in_buf, uint32_t in_size, void* out_buf,
-                          uint32_t* out_size) {
-    switch (cmd) {
-        case KM_GENERATE_KEY:
-            return fake_call(impl_, &keymaster::AndroidKeymaster::GenerateKey, in_buf, in_size,
-                             out_buf, out_size);
-        case KM_BEGIN_OPERATION:
-            return fake_call(impl_, &keymaster::AndroidKeymaster::BeginOperation, in_buf, in_size,
-                             out_buf, out_size);
-        case KM_UPDATE_OPERATION:
-            return fake_call(impl_, &keymaster::AndroidKeymaster::UpdateOperation, in_buf, in_size,
-                             out_buf, out_size);
-        case KM_FINISH_OPERATION:
-            return fake_call(impl_, &keymaster::AndroidKeymaster::FinishOperation, in_buf, in_size,
-                             out_buf, out_size);
-        case KM_IMPORT_KEY:
-            return fake_call(impl_, &keymaster::AndroidKeymaster::ImportKey, in_buf, in_size,
-                             out_buf, out_size);
-        case KM_EXPORT_KEY:
-            return fake_call(impl_, &keymaster::AndroidKeymaster::ExportKey, in_buf, in_size,
-                             out_buf, out_size);
-    }
-    return -EINVAL;
-}
-
-namespace keymaster {
-namespace test {
-
-class TrustyKeymasterTest : public testing::Test {
-  protected:
-    TrustyKeymasterTest() : device(NULL) {}
-
-    keymaster_rsa_keygen_params_t build_rsa_params() {
-        keymaster_rsa_keygen_params_t rsa_params;
-        rsa_params.public_exponent = 65537;
-        rsa_params.modulus_size = 2048;
-        return rsa_params;
-    }
-
-    uint8_t* build_message(size_t length) {
-        uint8_t* msg = new uint8_t[length];
-        memset(msg, 'a', length);
-        return msg;
-    }
-
-    size_t dsa_message_len(const keymaster_dsa_keygen_params_t& params) {
-        switch (params.key_size) {
-            case 256:
-            case 1024:
-                return 48;
-            case 2048:
-            case 4096:
-                return 72;
-            default:
-                // Oops.
-                return 0;
-        }
-    }
-
-    TrustyKeymasterDevice device;
-};
-
-class Malloc_Delete {
-  public:
-    Malloc_Delete(void* p) : p_(p) {}
-    ~Malloc_Delete() { free(p_); }
-
-  private:
-    void* p_;
-};
-
-typedef TrustyKeymasterTest KeyGenTest;
-TEST_F(KeyGenTest, RsaSuccess) {
-    keymaster_rsa_keygen_params_t params = build_rsa_params();
-    uint8_t* ptr = NULL;
-    size_t size;
-    ASSERT_EQ(0, device.generate_keypair(TYPE_RSA, &params, &ptr, &size));
-    EXPECT_GT(size, 0U);
-    Malloc_Delete key_deleter(ptr);
-}
-
-TEST_F(KeyGenTest, EcdsaSuccess) {
-    keymaster_ec_keygen_params_t ec_params = {256};
-    uint8_t* ptr = NULL;
-    size_t size;
-    ASSERT_EQ(0, device.generate_keypair(TYPE_EC, &ec_params, &ptr, &size));
-    EXPECT_GT(size, 0U);
-    Malloc_Delete key_deleter(ptr);
-}
-
-typedef TrustyKeymasterTest SigningTest;
-TEST_F(SigningTest, RsaSuccess) {
-    keymaster_rsa_keygen_params_t params = build_rsa_params();
-    uint8_t* ptr = NULL;
-    size_t size;
-    ASSERT_EQ(0, device.generate_keypair(TYPE_RSA, &params, &ptr, &size));
-    EXPECT_GT(size, 0U);
-    Malloc_Delete key_deleter(ptr);
-
-    keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
-    size_t message_len = params.modulus_size / 8;
-    std::unique_ptr<uint8_t[]> message(build_message(message_len));
-    uint8_t* signature;
-    size_t siglen;
-    EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
-                                            &signature, &siglen));
-    Malloc_Delete sig_deleter(signature);
-    EXPECT_EQ(message_len, siglen);
-}
-
-TEST_F(SigningTest, RsaShortMessage) {
-    keymaster_rsa_keygen_params_t params = build_rsa_params();
-    uint8_t* ptr = NULL;
-    size_t size;
-    ASSERT_EQ(0, device.generate_keypair(TYPE_RSA, &params, &ptr, &size));
-    EXPECT_GT(size, 0U);
-    Malloc_Delete key_deleter(ptr);
-
-    keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
-    size_t message_len = params.modulus_size / 8 - 1;
-    std::unique_ptr<uint8_t[]> message(build_message(message_len));
-    uint8_t* signature;
-    size_t siglen;
-    EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, device.sign_data(&sig_params, ptr, size, message.get(),
-                                                       message_len, &signature, &siglen));
-}
-
-TEST_F(SigningTest, RsaLongMessage) {
-    keymaster_rsa_keygen_params_t params = build_rsa_params();
-    uint8_t* ptr = NULL;
-    size_t size;
-    ASSERT_EQ(0, device.generate_keypair(TYPE_RSA, &params, &ptr, &size));
-    EXPECT_GT(size, 0U);
-    Malloc_Delete key_deleter(ptr);
-
-    keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
-    size_t message_len = params.modulus_size / 8 + 1;
-    std::unique_ptr<uint8_t[]> message(build_message(message_len));
-    uint8_t* signature;
-    size_t siglen;
-    EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, device.sign_data(&sig_params, ptr, size, message.get(),
-                                                       message_len, &signature, &siglen));
-}
-
-TEST_F(SigningTest, EcdsaSuccess) {
-    keymaster_ec_keygen_params_t params = {256};
-    uint8_t* ptr = NULL;
-    size_t size;
-    ASSERT_EQ(0, device.generate_keypair(TYPE_EC, &params, &ptr, &size));
-    EXPECT_GT(size, 0U);
-    Malloc_Delete key_deleter(ptr);
-
-    keymaster_ec_sign_params_t sig_params = {DIGEST_NONE};
-    uint8_t message[] = "12345678901234567890123456789012";
-    uint8_t* signature;
-    size_t siglen;
-    ASSERT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message,
-                                            array_size(message) - 1, &signature, &siglen));
-    Malloc_Delete sig_deleter(signature);
-    EXPECT_GT(siglen, 69U);
-    EXPECT_LT(siglen, 73U);
-}
-
-TEST_F(SigningTest, EcdsaEmptyMessageSuccess) {
-    keymaster_ec_keygen_params_t params = {256};
-    uint8_t* ptr = NULL;
-    size_t size;
-    ASSERT_EQ(0, device.generate_keypair(TYPE_EC, &params, &ptr, &size));
-    EXPECT_GT(size, 0U);
-    Malloc_Delete key_deleter(ptr);
-
-    keymaster_ec_sign_params_t sig_params = {DIGEST_NONE};
-    uint8_t message[] = "";
-    uint8_t* signature;
-    size_t siglen;
-    ASSERT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message,
-                                            array_size(message) - 1, &signature, &siglen));
-    Malloc_Delete sig_deleter(signature);
-    EXPECT_GT(siglen, 69U);
-    EXPECT_LT(siglen, 73U);
-}
-
-TEST_F(SigningTest, EcdsaLargeMessageSuccess) {
-    keymaster_ec_keygen_params_t params = {256};
-    uint8_t* ptr = NULL;
-    size_t size;
-    ASSERT_EQ(0, device.generate_keypair(TYPE_EC, &params, &ptr, &size));
-    EXPECT_GT(size, 0U);
-    Malloc_Delete key_deleter(ptr);
-
-    keymaster_ec_sign_params_t sig_params = {DIGEST_NONE};
-    size_t message_len = 1024 * 7;
-    std::unique_ptr<uint8_t[]> message(new uint8_t[message_len]);
-    // contents of message don't matter.
-    uint8_t* signature;
-    size_t siglen;
-    ASSERT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
-                                            &signature, &siglen));
-    Malloc_Delete sig_deleter(signature);
-    EXPECT_GT(siglen, 69U);
-    EXPECT_LT(siglen, 73U);
-}
-
-typedef TrustyKeymasterTest VerificationTest;
-TEST_F(VerificationTest, RsaSuccess) {
-    keymaster_rsa_keygen_params_t params = build_rsa_params();
-    uint8_t* ptr = NULL;
-    size_t size;
-    ASSERT_EQ(0, device.generate_keypair(TYPE_RSA, &params, &ptr, &size));
-    EXPECT_GT(size, 0U);
-    Malloc_Delete key_deleter(ptr);
-
-    keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
-    size_t message_len = params.modulus_size / 8;
-    std::unique_ptr<uint8_t[]> message(build_message(message_len));
-    uint8_t* signature;
-    size_t siglen;
-    EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
-                                            &signature, &siglen));
-    Malloc_Delete sig_deleter(signature);
-
-    EXPECT_EQ(KM_ERROR_OK, device.verify_data(&sig_params, ptr, size, message.get(), message_len,
-                                              signature, siglen));
-}
-
-TEST_F(VerificationTest, RsaBadSignature) {
-    keymaster_rsa_keygen_params_t params = build_rsa_params();
-    uint8_t* ptr = NULL;
-    size_t size;
-    ASSERT_EQ(0, device.generate_keypair(TYPE_RSA, &params, &ptr, &size));
-    EXPECT_GT(size, 0U);
-    Malloc_Delete key_deleter(ptr);
-
-    keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
-    size_t message_len = params.modulus_size / 8;
-    std::unique_ptr<uint8_t[]> message(build_message(message_len));
-    uint8_t* signature;
-    size_t siglen;
-    EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
-                                            &signature, &siglen));
-
-    Malloc_Delete sig_deleter(signature);
-    signature[siglen / 2]++;
-    EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED,
-              device.verify_data(&sig_params, ptr, size, message.get(), message_len, signature,
-                                 siglen));
-}
-
-TEST_F(VerificationTest, RsaBadMessage) {
-    keymaster_rsa_keygen_params_t params = build_rsa_params();
-    uint8_t* ptr = NULL;
-    size_t size;
-    ASSERT_EQ(0, device.generate_keypair(TYPE_RSA, &params, &ptr, &size));
-    EXPECT_GT(size, 0U);
-    Malloc_Delete key_deleter(ptr);
-
-    keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
-    size_t message_len = params.modulus_size / 8;
-    std::unique_ptr<uint8_t[]> message(build_message(message_len));
-    uint8_t* signature;
-    size_t siglen;
-    EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
-                                            &signature, &siglen));
-    Malloc_Delete sig_deleter(signature);
-    message[0]++;
-    EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED,
-              device.verify_data(&sig_params, ptr, size, message.get(), message_len, signature,
-                                 siglen));
-}
-
-TEST_F(VerificationTest, RsaShortMessage) {
-    keymaster_rsa_keygen_params_t params = build_rsa_params();
-    uint8_t* ptr = NULL;
-    size_t size;
-    ASSERT_EQ(0, device.generate_keypair(TYPE_RSA, &params, &ptr, &size));
-    EXPECT_GT(size, 0U);
-    Malloc_Delete key_deleter(ptr);
-
-    keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
-    size_t message_len = params.modulus_size / 8;
-    std::unique_ptr<uint8_t[]> message(build_message(message_len));
-    uint8_t* signature;
-    size_t siglen;
-    EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
-                                            &signature, &siglen));
-
-    Malloc_Delete sig_deleter(signature);
-    EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH,
-              device.verify_data(&sig_params, ptr, size, message.get(), message_len - 1, signature,
-                                 siglen));
-}
-
-TEST_F(VerificationTest, RsaLongMessage) {
-    keymaster_rsa_keygen_params_t params = build_rsa_params();
-    uint8_t* ptr = NULL;
-    size_t size;
-    ASSERT_EQ(0, device.generate_keypair(TYPE_RSA, &params, &ptr, &size));
-    EXPECT_GT(size, 0U);
-    Malloc_Delete key_deleter(ptr);
-
-    keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
-    size_t message_len = params.modulus_size / 8;
-    std::unique_ptr<uint8_t[]> message(build_message(message_len + 1));
-    uint8_t* signature;
-    size_t siglen;
-    EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
-                                            &signature, &siglen));
-    Malloc_Delete sig_deleter(signature);
-    EXPECT_EQ(KM_ERROR_INVALID_INPUT_LENGTH,
-              device.verify_data(&sig_params, ptr, size, message.get(), message_len + 1, signature,
-                                 siglen));
-}
-
-TEST_F(VerificationTest, EcdsaSuccess) {
-    keymaster_ec_keygen_params_t params = {256};
-    uint8_t* ptr = NULL;
-    size_t size;
-    ASSERT_EQ(0, device.generate_keypair(TYPE_EC, &params, &ptr, &size));
-    EXPECT_GT(size, 0U);
-    Malloc_Delete key_deleter(ptr);
-
-    keymaster_ec_sign_params_t sig_params = {DIGEST_NONE};
-    uint8_t message[] = "12345678901234567890123456789012";
-    uint8_t* signature;
-    size_t siglen;
-    ASSERT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message,
-                                            array_size(message) - 1, &signature, &siglen));
-    Malloc_Delete sig_deleter(signature);
-    EXPECT_EQ(KM_ERROR_OK, device.verify_data(&sig_params, ptr, size, message,
-                                              array_size(message) - 1, signature, siglen));
-}
-
-TEST_F(VerificationTest, EcdsaLargeMessageSuccess) {
-    keymaster_ec_keygen_params_t params = {256};
-    uint8_t* ptr = NULL;
-    size_t size;
-    ASSERT_EQ(0, device.generate_keypair(TYPE_EC, &params, &ptr, &size));
-    EXPECT_GT(size, 0U);
-    Malloc_Delete key_deleter(ptr);
-
-    keymaster_ec_sign_params_t sig_params = {DIGEST_NONE};
-    size_t message_len = 1024 * 7;
-    std::unique_ptr<uint8_t[]> message(new uint8_t[message_len]);
-    // contents of message don't matter.
-    uint8_t* signature;
-    size_t siglen;
-    ASSERT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
-                                            &signature, &siglen));
-    Malloc_Delete sig_deleter(signature);
-    EXPECT_EQ(KM_ERROR_OK, device.verify_data(&sig_params, ptr, size, message.get(), message_len,
-                                              signature, siglen));
-}
-
-static string read_file(const string& file_name) {
-    ifstream file_stream(file_name, std::ios::binary);
-    istreambuf_iterator<char> file_begin(file_stream);
-    istreambuf_iterator<char> file_end;
-    return string(file_begin, file_end);
-}
-
-typedef TrustyKeymasterTest ImportKeyTest;
-TEST_F(ImportKeyTest, RsaSuccess) {
-    string pk8_key = read_file("../../../../system/keymaster/rsa_privkey_pk8.der");
-    ASSERT_EQ(633U, pk8_key.size());
-
-    uint8_t* key = NULL;
-    size_t size;
-    ASSERT_EQ(KM_ERROR_OK, device.import_keypair(reinterpret_cast<const uint8_t*>(pk8_key.data()),
-                                                 pk8_key.size(), &key, &size));
-    Malloc_Delete key_deleter(key);
-
-    keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
-    size_t message_size = 1024 /* key size */ / 8;
-    std::unique_ptr<uint8_t[]> message(new uint8_t[message_size]);
-    memset(message.get(), 'a', message_size);
-    uint8_t* signature;
-    size_t siglen;
-    ASSERT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, key, size, message.get(), message_size,
-                                            &signature, &siglen));
-    Malloc_Delete sig_deleter(signature);
-    EXPECT_EQ(KM_ERROR_OK, device.verify_data(&sig_params, key, size, message.get(), message_size,
-                                              signature, siglen));
-}
-
-TEST_F(ImportKeyTest, EcdsaSuccess) {
-    string pk8_key = read_file("../../../../system/keymaster/ec_privkey_pk8.der");
-    ASSERT_EQ(138U, pk8_key.size());
-
-    uint8_t* key = NULL;
-    size_t size;
-    ASSERT_EQ(KM_ERROR_OK, device.import_keypair(reinterpret_cast<const uint8_t*>(pk8_key.data()),
-                                                 pk8_key.size(), &key, &size));
-    Malloc_Delete key_deleter(key);
-
-    keymaster_ec_sign_params_t sig_params = {DIGEST_NONE};
-    uint8_t message[] = "12345678901234567890123456789012";
-    uint8_t* signature;
-    size_t siglen;
-    ASSERT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, key, size, message,
-                                            array_size(message) - 1, &signature, &siglen));
-    Malloc_Delete sig_deleter(signature);
-    EXPECT_EQ(KM_ERROR_OK, device.verify_data(&sig_params, key, size, message,
-                                              array_size(message) - 1, signature, siglen));
-}
-
-struct EVP_PKEY_CTX_Delete {
-    void operator()(EVP_PKEY_CTX* p) { EVP_PKEY_CTX_free(p); }
-};
-
-static void VerifySignature(const uint8_t* key, size_t key_len, const uint8_t* signature,
-                            size_t signature_len, const uint8_t* message, size_t message_len) {
-    std::unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(d2i_PUBKEY(NULL, &key, key_len));
-    ASSERT_TRUE(pkey.get() != NULL);
-    std::unique_ptr<EVP_PKEY_CTX, EVP_PKEY_CTX_Delete> ctx(EVP_PKEY_CTX_new(pkey.get(), NULL));
-    ASSERT_TRUE(ctx.get() != NULL);
-    ASSERT_EQ(1, EVP_PKEY_verify_init(ctx.get()));
-    if (EVP_PKEY_type(pkey->type) == EVP_PKEY_RSA)
-        ASSERT_EQ(1, EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_NO_PADDING));
-    EXPECT_EQ(1, EVP_PKEY_verify(ctx.get(), signature, signature_len, message, message_len));
-}
-
-typedef TrustyKeymasterTest ExportKeyTest;
-TEST_F(ExportKeyTest, RsaSuccess) {
-    keymaster_rsa_keygen_params_t params = build_rsa_params();
-    uint8_t* ptr = NULL;
-    size_t size;
-    ASSERT_EQ(0, device.generate_keypair(TYPE_RSA, &params, &ptr, &size));
-    EXPECT_GT(size, 0U);
-    Malloc_Delete key_deleter(ptr);
-
-    uint8_t* exported;
-    size_t exported_size;
-    EXPECT_EQ(KM_ERROR_OK, device.get_keypair_public(ptr, size, &exported, &exported_size));
-    Malloc_Delete exported_deleter(exported);
-
-    // Sign a message so we can verify it with the exported pubkey.
-    keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
-    size_t message_len = params.modulus_size / 8;
-    std::unique_ptr<uint8_t[]> message(build_message(message_len));
-    uint8_t* signature;
-    size_t siglen;
-    EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
-                                            &signature, &siglen));
-    Malloc_Delete sig_deleter(signature);
-    EXPECT_EQ(message_len, siglen);
-    const uint8_t* tmp = exported;
-
-    VerifySignature(exported, exported_size, signature, siglen, message.get(), message_len);
-}
-
-typedef TrustyKeymasterTest ExportKeyTest;
-TEST_F(ExportKeyTest, EcdsaSuccess) {
-    keymaster_ec_keygen_params_t params = {256};
-    uint8_t* key = NULL;
-    size_t size;
-    ASSERT_EQ(0, device.generate_keypair(TYPE_EC, &params, &key, &size));
-    EXPECT_GT(size, 0U);
-    Malloc_Delete key_deleter(key);
-
-    uint8_t* exported;
-    size_t exported_size;
-    EXPECT_EQ(KM_ERROR_OK, device.get_keypair_public(key, size, &exported, &exported_size));
-    Malloc_Delete exported_deleter(exported);
-
-    // Sign a message so we can verify it with the exported pubkey.
-    keymaster_ec_sign_params_t sig_params = {DIGEST_NONE};
-    uint8_t message[] = "12345678901234567890123456789012";
-    uint8_t* signature;
-    size_t siglen;
-    ASSERT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, key, size, message,
-                                            array_size(message) - 1, &signature, &siglen));
-    Malloc_Delete sig_deleter(signature);
-    EXPECT_EQ(KM_ERROR_OK, device.verify_data(&sig_params, key, size, message,
-                                              array_size(message) - 1, signature, siglen));
-
-    VerifySignature(exported, exported_size, signature, siglen, message, array_size(message) - 1);
-}
-
-}  // namespace test
-}  // namespace keymaster
diff --git a/trusty/keymaster/legacy/trusty_keymaster_main.cpp b/trusty/keymaster/legacy/trusty_keymaster_main.cpp
deleted file mode 100644
index e3e70e6..0000000
--- a/trusty/keymaster/legacy/trusty_keymaster_main.cpp
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * Copyright 2014 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 <keymaster/keymaster_configuration.h>
-
-#include <stdio.h>
-#include <memory>
-
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-
-#include <trusty_keymaster/legacy/trusty_keymaster_device.h>
-
-using keymaster::TrustyKeymasterDevice;
-
-unsigned char rsa_privkey_pk8_der[] = {
-        0x30, 0x82, 0x02, 0x75, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
-        0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x5f, 0x30, 0x82, 0x02, 0x5b,
-        0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xc6, 0x09, 0x54, 0x09, 0x04, 0x7d, 0x86, 0x34,
-        0x81, 0x2d, 0x5a, 0x21, 0x81, 0x76, 0xe4, 0x5c, 0x41, 0xd6, 0x0a, 0x75, 0xb1, 0x39, 0x01,
-        0xf2, 0x34, 0x22, 0x6c, 0xff, 0xe7, 0x76, 0x52, 0x1c, 0x5a, 0x77, 0xb9, 0xe3, 0x89, 0x41,
-        0x7b, 0x71, 0xc0, 0xb6, 0xa4, 0x4d, 0x13, 0xaf, 0xe4, 0xe4, 0xa2, 0x80, 0x5d, 0x46, 0xc9,
-        0xda, 0x29, 0x35, 0xad, 0xb1, 0xff, 0x0c, 0x1f, 0x24, 0xea, 0x06, 0xe6, 0x2b, 0x20, 0xd7,
-        0x76, 0x43, 0x0a, 0x4d, 0x43, 0x51, 0x57, 0x23, 0x3c, 0x6f, 0x91, 0x67, 0x83, 0xc3, 0x0e,
-        0x31, 0x0f, 0xcb, 0xd8, 0x9b, 0x85, 0xc2, 0xd5, 0x67, 0x71, 0x16, 0x97, 0x85, 0xac, 0x12,
-        0xbc, 0xa2, 0x44, 0xab, 0xda, 0x72, 0xbf, 0xb1, 0x9f, 0xc4, 0x4d, 0x27, 0xc8, 0x1e, 0x1d,
-        0x92, 0xde, 0x28, 0x4f, 0x40, 0x61, 0xed, 0xfd, 0x99, 0x28, 0x07, 0x45, 0xea, 0x6d, 0x25,
-        0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x80, 0x1b, 0xe0, 0xf0, 0x4d, 0x9c, 0xae, 0x37,
-        0x18, 0x69, 0x1f, 0x03, 0x53, 0x38, 0x30, 0x8e, 0x91, 0x56, 0x4b, 0x55, 0x89, 0x9f, 0xfb,
-        0x50, 0x84, 0xd2, 0x46, 0x0e, 0x66, 0x30, 0x25, 0x7e, 0x05, 0xb3, 0xce, 0xab, 0x02, 0x97,
-        0x2d, 0xfa, 0xbc, 0xd6, 0xce, 0x5f, 0x6e, 0xe2, 0x58, 0x9e, 0xb6, 0x79, 0x11, 0xed, 0x0f,
-        0xac, 0x16, 0xe4, 0x3a, 0x44, 0x4b, 0x8c, 0x86, 0x1e, 0x54, 0x4a, 0x05, 0x93, 0x36, 0x57,
-        0x72, 0xf8, 0xba, 0xf6, 0xb2, 0x2f, 0xc9, 0xe3, 0xc5, 0xf1, 0x02, 0x4b, 0x06, 0x3a, 0xc0,
-        0x80, 0xa7, 0xb2, 0x23, 0x4c, 0xf8, 0xae, 0xe8, 0xf6, 0xc4, 0x7b, 0xbf, 0x4f, 0xd3, 0xac,
-        0xe7, 0x24, 0x02, 0x90, 0xbe, 0xf1, 0x6c, 0x0b, 0x3f, 0x7f, 0x3c, 0xdd, 0x64, 0xce, 0x3a,
-        0xb5, 0x91, 0x2c, 0xf6, 0xe3, 0x2f, 0x39, 0xab, 0x18, 0x83, 0x58, 0xaf, 0xcc, 0xcd, 0x80,
-        0x81, 0x02, 0x41, 0x00, 0xe4, 0xb4, 0x9e, 0xf5, 0x0f, 0x76, 0x5d, 0x3b, 0x24, 0xdd, 0xe0,
-        0x1a, 0xce, 0xaa, 0xf1, 0x30, 0xf2, 0xc7, 0x66, 0x70, 0xa9, 0x1a, 0x61, 0xae, 0x08, 0xaf,
-        0x49, 0x7b, 0x4a, 0x82, 0xbe, 0x6d, 0xee, 0x8f, 0xcd, 0xd5, 0xe3, 0xf7, 0xba, 0x1c, 0xfb,
-        0x1f, 0x0c, 0x92, 0x6b, 0x88, 0xf8, 0x8c, 0x92, 0xbf, 0xab, 0x13, 0x7f, 0xba, 0x22, 0x85,
-        0x22, 0x7b, 0x83, 0xc3, 0x42, 0xff, 0x7c, 0x55, 0x02, 0x41, 0x00, 0xdd, 0xab, 0xb5, 0x83,
-        0x9c, 0x4c, 0x7f, 0x6b, 0xf3, 0xd4, 0x18, 0x32, 0x31, 0xf0, 0x05, 0xb3, 0x1a, 0xa5, 0x8a,
-        0xff, 0xdd, 0xa5, 0xc7, 0x9e, 0x4c, 0xce, 0x21, 0x7f, 0x6b, 0xc9, 0x30, 0xdb, 0xe5, 0x63,
-        0xd4, 0x80, 0x70, 0x6c, 0x24, 0xe9, 0xeb, 0xfc, 0xab, 0x28, 0xa6, 0xcd, 0xef, 0xd3, 0x24,
-        0xb7, 0x7e, 0x1b, 0xf7, 0x25, 0x1b, 0x70, 0x90, 0x92, 0xc2, 0x4f, 0xf5, 0x01, 0xfd, 0x91,
-        0x02, 0x40, 0x23, 0xd4, 0x34, 0x0e, 0xda, 0x34, 0x45, 0xd8, 0xcd, 0x26, 0xc1, 0x44, 0x11,
-        0xda, 0x6f, 0xdc, 0xa6, 0x3c, 0x1c, 0xcd, 0x4b, 0x80, 0xa9, 0x8a, 0xd5, 0x2b, 0x78, 0xcc,
-        0x8a, 0xd8, 0xbe, 0xb2, 0x84, 0x2c, 0x1d, 0x28, 0x04, 0x05, 0xbc, 0x2f, 0x6c, 0x1b, 0xea,
-        0x21, 0x4a, 0x1d, 0x74, 0x2a, 0xb9, 0x96, 0xb3, 0x5b, 0x63, 0xa8, 0x2a, 0x5e, 0x47, 0x0f,
-        0xa8, 0x8d, 0xbf, 0x82, 0x3c, 0xdd, 0x02, 0x40, 0x1b, 0x7b, 0x57, 0x44, 0x9a, 0xd3, 0x0d,
-        0x15, 0x18, 0x24, 0x9a, 0x5f, 0x56, 0xbb, 0x98, 0x29, 0x4d, 0x4b, 0x6a, 0xc1, 0x2f, 0xfc,
-        0x86, 0x94, 0x04, 0x97, 0xa5, 0xa5, 0x83, 0x7a, 0x6c, 0xf9, 0x46, 0x26, 0x2b, 0x49, 0x45,
-        0x26, 0xd3, 0x28, 0xc1, 0x1e, 0x11, 0x26, 0x38, 0x0f, 0xde, 0x04, 0xc2, 0x4f, 0x91, 0x6d,
-        0xec, 0x25, 0x08, 0x92, 0xdb, 0x09, 0xa6, 0xd7, 0x7c, 0xdb, 0xa3, 0x51, 0x02, 0x40, 0x77,
-        0x62, 0xcd, 0x8f, 0x4d, 0x05, 0x0d, 0xa5, 0x6b, 0xd5, 0x91, 0xad, 0xb5, 0x15, 0xd2, 0x4d,
-        0x7c, 0xcd, 0x32, 0xcc, 0xa0, 0xd0, 0x5f, 0x86, 0x6d, 0x58, 0x35, 0x14, 0xbd, 0x73, 0x24,
-        0xd5, 0xf3, 0x36, 0x45, 0xe8, 0xed, 0x8b, 0x4a, 0x1c, 0xb3, 0xcc, 0x4a, 0x1d, 0x67, 0x98,
-        0x73, 0x99, 0xf2, 0xa0, 0x9f, 0x5b, 0x3f, 0xb6, 0x8c, 0x88, 0xd5, 0xe5, 0xd9, 0x0a, 0xc3,
-        0x34, 0x92, 0xd6};
-unsigned int rsa_privkey_pk8_der_len = 633;
-
-unsigned char dsa_privkey_pk8_der[] = {
-        0x30, 0x82, 0x01, 0x4b, 0x02, 0x01, 0x00, 0x30, 0x82, 0x01, 0x2b, 0x06, 0x07, 0x2a, 0x86,
-        0x48, 0xce, 0x38, 0x04, 0x01, 0x30, 0x82, 0x01, 0x1e, 0x02, 0x81, 0x81, 0x00, 0xa3, 0xf3,
-        0xe9, 0xb6, 0x7e, 0x7d, 0x88, 0xf6, 0xb7, 0xe5, 0xf5, 0x1f, 0x3b, 0xee, 0xac, 0xd7, 0xad,
-        0xbc, 0xc9, 0xd1, 0x5a, 0xf8, 0x88, 0xc4, 0xef, 0x6e, 0x3d, 0x74, 0x19, 0x74, 0xe7, 0xd8,
-        0xe0, 0x26, 0x44, 0x19, 0x86, 0xaf, 0x19, 0xdb, 0x05, 0xe9, 0x3b, 0x8b, 0x58, 0x58, 0xde,
-        0xe5, 0x4f, 0x48, 0x15, 0x01, 0xea, 0xe6, 0x83, 0x52, 0xd7, 0xc1, 0x21, 0xdf, 0xb9, 0xb8,
-        0x07, 0x66, 0x50, 0xfb, 0x3a, 0x0c, 0xb3, 0x85, 0xee, 0xbb, 0x04, 0x5f, 0xc2, 0x6d, 0x6d,
-        0x95, 0xfa, 0x11, 0x93, 0x1e, 0x59, 0x5b, 0xb1, 0x45, 0x8d, 0xe0, 0x3d, 0x73, 0xaa, 0xf2,
-        0x41, 0x14, 0x51, 0x07, 0x72, 0x3d, 0xa2, 0xf7, 0x58, 0xcd, 0x11, 0xa1, 0x32, 0xcf, 0xda,
-        0x42, 0xb7, 0xcc, 0x32, 0x80, 0xdb, 0x87, 0x82, 0xec, 0x42, 0xdb, 0x5a, 0x55, 0x24, 0x24,
-        0xa2, 0xd1, 0x55, 0x29, 0xad, 0xeb, 0x02, 0x15, 0x00, 0xeb, 0xea, 0x17, 0xd2, 0x09, 0xb3,
-        0xd7, 0x21, 0x9a, 0x21, 0x07, 0x82, 0x8f, 0xab, 0xfe, 0x88, 0x71, 0x68, 0xf7, 0xe3, 0x02,
-        0x81, 0x80, 0x19, 0x1c, 0x71, 0xfd, 0xe0, 0x03, 0x0c, 0x43, 0xd9, 0x0b, 0xf6, 0xcd, 0xd6,
-        0xa9, 0x70, 0xe7, 0x37, 0x86, 0x3a, 0x78, 0xe9, 0xa7, 0x47, 0xa7, 0x47, 0x06, 0x88, 0xb1,
-        0xaf, 0xd7, 0xf3, 0xf1, 0xa1, 0xd7, 0x00, 0x61, 0x28, 0x88, 0x31, 0x48, 0x60, 0xd8, 0x11,
-        0xef, 0xa5, 0x24, 0x1a, 0x81, 0xc4, 0x2a, 0xe2, 0xea, 0x0e, 0x36, 0xd2, 0xd2, 0x05, 0x84,
-        0x37, 0xcf, 0x32, 0x7d, 0x09, 0xe6, 0x0f, 0x8b, 0x0c, 0xc8, 0xc2, 0xa4, 0xb1, 0xdc, 0x80,
-        0xca, 0x68, 0xdf, 0xaf, 0xd2, 0x90, 0xc0, 0x37, 0x58, 0x54, 0x36, 0x8f, 0x49, 0xb8, 0x62,
-        0x75, 0x8b, 0x48, 0x47, 0xc0, 0xbe, 0xf7, 0x9a, 0x92, 0xa6, 0x68, 0x05, 0xda, 0x9d, 0xaf,
-        0x72, 0x9a, 0x67, 0xb3, 0xb4, 0x14, 0x03, 0xae, 0x4f, 0x4c, 0x76, 0xb9, 0xd8, 0x64, 0x0a,
-        0xba, 0x3b, 0xa8, 0x00, 0x60, 0x4d, 0xae, 0x81, 0xc3, 0xc5, 0x04, 0x17, 0x02, 0x15, 0x00,
-        0x81, 0x9d, 0xfd, 0x53, 0x0c, 0xc1, 0x8f, 0xbe, 0x8b, 0xea, 0x00, 0x26, 0x19, 0x29, 0x33,
-        0x91, 0x84, 0xbe, 0xad, 0x81};
-unsigned int dsa_privkey_pk8_der_len = 335;
-
-unsigned char ec_privkey_pk8_der[] = {
-        0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce,
-        0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x04,
-        0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20, 0x73, 0x7c, 0x2e, 0xcd, 0x7b, 0x8d,
-        0x19, 0x40, 0xbf, 0x29, 0x30, 0xaa, 0x9b, 0x4e, 0xd3, 0xff, 0x94, 0x1e, 0xed, 0x09,
-        0x36, 0x6b, 0xc0, 0x32, 0x99, 0x98, 0x64, 0x81, 0xf3, 0xa4, 0xd8, 0x59, 0xa1, 0x44,
-        0x03, 0x42, 0x00, 0x04, 0xbf, 0x85, 0xd7, 0x72, 0x0d, 0x07, 0xc2, 0x54, 0x61, 0x68,
-        0x3b, 0xc6, 0x48, 0xb4, 0x77, 0x8a, 0x9a, 0x14, 0xdd, 0x8a, 0x02, 0x4e, 0x3b, 0xdd,
-        0x8c, 0x7d, 0xdd, 0x9a, 0xb2, 0xb5, 0x28, 0xbb, 0xc7, 0xaa, 0x1b, 0x51, 0xf1, 0x4e,
-        0xbb, 0xbb, 0x0b, 0xd0, 0xce, 0x21, 0xbc, 0xc4, 0x1c, 0x6e, 0xb0, 0x00, 0x83, 0xcf,
-        0x33, 0x76, 0xd1, 0x1f, 0xd4, 0x49, 0x49, 0xe0, 0xb2, 0x18, 0x3b, 0xfe};
-unsigned int ec_privkey_pk8_der_len = 138;
-
-keymaster_key_param_t ec_params[] = {
-        keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_EC),
-        keymaster_param_long(KM_TAG_EC_CURVE, KM_EC_CURVE_P_521),
-        keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_SIGN),
-        keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_VERIFY),
-        keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE),
-        keymaster_param_bool(KM_TAG_NO_AUTH_REQUIRED),
-};
-keymaster_key_param_set_t ec_param_set = {ec_params, sizeof(ec_params) / sizeof(*ec_params)};
-
-keymaster_key_param_t rsa_params[] = {
-        keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA),
-        keymaster_param_int(KM_TAG_KEY_SIZE, 1024),
-        keymaster_param_long(KM_TAG_RSA_PUBLIC_EXPONENT, 65537),
-        keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_SIGN),
-        keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_VERIFY),
-        keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE),
-        keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE),
-        keymaster_param_bool(KM_TAG_NO_AUTH_REQUIRED),
-};
-keymaster_key_param_set_t rsa_param_set = {rsa_params, sizeof(rsa_params) / sizeof(*rsa_params)};
-
-struct EVP_PKEY_Delete {
-    void operator()(EVP_PKEY* p) const { EVP_PKEY_free(p); }
-};
-
-struct EVP_PKEY_CTX_Delete {
-    void operator()(EVP_PKEY_CTX* p) { EVP_PKEY_CTX_free(p); }
-};
-
-static bool do_operation(TrustyKeymasterDevice* device, keymaster_purpose_t purpose,
-                         keymaster_key_blob_t* key, keymaster_blob_t* input,
-                         keymaster_blob_t* signature, keymaster_blob_t* output) {
-    keymaster_key_param_t params[] = {
-            keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE),
-            keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE),
-    };
-    keymaster_key_param_set_t param_set = {params, sizeof(params) / sizeof(*params)};
-    keymaster_operation_handle_t op_handle;
-    keymaster_error_t error = device->begin(purpose, key, &param_set, nullptr, &op_handle);
-    if (error != KM_ERROR_OK) {
-        printf("Keymaster begin() failed: %d\n", error);
-        return false;
-    }
-    size_t input_consumed;
-    error = device->update(op_handle, nullptr, input, &input_consumed, nullptr, nullptr);
-    if (error != KM_ERROR_OK) {
-        printf("Keymaster update() failed: %d\n", error);
-        return false;
-    }
-    if (input_consumed != input->data_length) {
-        // This should never happen. If it does, it's a bug in the keymaster implementation.
-        printf("Keymaster update() did not consume all data.\n");
-        device->abort(op_handle);
-        return false;
-    }
-    error = device->finish(op_handle, nullptr, nullptr, signature, nullptr, output);
-    if (error != KM_ERROR_OK) {
-        printf("Keymaster finish() failed: %d\n", error);
-        return false;
-    }
-    return true;
-}
-
-static bool test_import_rsa(TrustyKeymasterDevice* device) {
-    printf("===================\n");
-    printf("= RSA Import Test =\n");
-    printf("===================\n\n");
-
-    printf("=== Importing RSA keypair === \n");
-    keymaster_key_blob_t key;
-    keymaster_blob_t private_key = {rsa_privkey_pk8_der, rsa_privkey_pk8_der_len};
-    int error =
-            device->import_key(&rsa_param_set, KM_KEY_FORMAT_PKCS8, &private_key, &key, nullptr);
-    if (error != KM_ERROR_OK) {
-        printf("Error importing RSA key: %d\n\n", error);
-        return false;
-    }
-    std::unique_ptr<const uint8_t[]> key_deleter(key.key_material);
-
-    printf("=== Signing with imported RSA key ===\n");
-    size_t message_len = 1024 / 8;
-    std::unique_ptr<uint8_t[]> message(new uint8_t[message_len]);
-    memset(message.get(), 'a', message_len);
-    keymaster_blob_t input = {message.get(), message_len}, signature;
-
-    if (!do_operation(device, KM_PURPOSE_SIGN, &key, &input, nullptr, &signature)) {
-        printf("Error signing data with imported RSA key\n\n");
-        return false;
-    }
-    std::unique_ptr<const uint8_t[]> signature_deleter(signature.data);
-
-    printf("=== Verifying with imported RSA key === \n");
-    if (!do_operation(device, KM_PURPOSE_VERIFY, &key, &input, &signature, nullptr)) {
-        printf("Error verifying data with imported RSA key\n\n");
-        return false;
-    }
-
-    printf("\n");
-    return true;
-}
-
-static bool test_rsa(TrustyKeymasterDevice* device) {
-    printf("============\n");
-    printf("= RSA Test =\n");
-    printf("============\n\n");
-
-    printf("=== Generating RSA key pair ===\n");
-    keymaster_key_blob_t key;
-    int error = device->generate_key(&rsa_param_set, &key, nullptr);
-    if (error != KM_ERROR_OK) {
-        printf("Error generating RSA key pair: %d\n\n", error);
-        return false;
-    }
-    std::unique_ptr<const uint8_t[]> key_deleter(key.key_material);
-
-    printf("=== Signing with RSA key === \n");
-    size_t message_len = 1024 / 8;
-    std::unique_ptr<uint8_t[]> message(new uint8_t[message_len]);
-    memset(message.get(), 'a', message_len);
-    keymaster_blob_t input = {message.get(), message_len}, signature;
-
-    if (!do_operation(device, KM_PURPOSE_SIGN, &key, &input, nullptr, &signature)) {
-        printf("Error signing data with RSA key\n\n");
-        return false;
-    }
-    std::unique_ptr<const uint8_t[]> signature_deleter(signature.data);
-
-    printf("=== Verifying with RSA key === \n");
-    if (!do_operation(device, KM_PURPOSE_VERIFY, &key, &input, &signature, nullptr)) {
-        printf("Error verifying data with RSA key\n\n");
-        return false;
-    }
-
-    printf("=== Exporting RSA public key ===\n");
-    keymaster_blob_t exported_key;
-    error = device->export_key(KM_KEY_FORMAT_X509, &key, nullptr, nullptr, &exported_key);
-    if (error != KM_ERROR_OK) {
-        printf("Error exporting RSA public key: %d\n\n", error);
-        return false;
-    }
-
-    printf("=== Verifying with exported key ===\n");
-    const uint8_t* tmp = exported_key.data;
-    std::unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
-            d2i_PUBKEY(NULL, &tmp, exported_key.data_length));
-    std::unique_ptr<EVP_PKEY_CTX, EVP_PKEY_CTX_Delete> ctx(EVP_PKEY_CTX_new(pkey.get(), NULL));
-    if (EVP_PKEY_verify_init(ctx.get()) != 1) {
-        printf("Error initializing openss EVP context\n\n");
-        return false;
-    }
-    if (EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) {
-        printf("Exported key was the wrong type?!?\n\n");
-        return false;
-    }
-
-    EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_NO_PADDING);
-    if (EVP_PKEY_verify(ctx.get(), signature.data, signature.data_length, message.get(),
-                        message_len) != 1) {
-        printf("Verification with exported pubkey failed.\n\n");
-        return false;
-    } else {
-        printf("Verification succeeded\n");
-    }
-
-    printf("\n");
-    return true;
-}
-
-static bool test_import_ecdsa(TrustyKeymasterDevice* device) {
-    printf("=====================\n");
-    printf("= ECDSA Import Test =\n");
-    printf("=====================\n\n");
-
-    printf("=== Importing ECDSA keypair === \n");
-    keymaster_key_blob_t key;
-    keymaster_blob_t private_key = {ec_privkey_pk8_der, ec_privkey_pk8_der_len};
-    int error = device->import_key(&ec_param_set, KM_KEY_FORMAT_PKCS8, &private_key, &key, nullptr);
-    if (error != KM_ERROR_OK) {
-        printf("Error importing ECDSA key: %d\n\n", error);
-        return false;
-    }
-    std::unique_ptr<const uint8_t[]> deleter(key.key_material);
-
-    printf("=== Signing with imported ECDSA key ===\n");
-    size_t message_len = 30 /* arbitrary */;
-    std::unique_ptr<uint8_t[]> message(new uint8_t[message_len]);
-    memset(message.get(), 'a', message_len);
-    keymaster_blob_t input = {message.get(), message_len}, signature;
-
-    if (!do_operation(device, KM_PURPOSE_SIGN, &key, &input, nullptr, &signature)) {
-        printf("Error signing data with imported ECDSA key\n\n");
-        return false;
-    }
-    std::unique_ptr<const uint8_t[]> signature_deleter(signature.data);
-
-    printf("=== Verifying with imported ECDSA key === \n");
-    if (!do_operation(device, KM_PURPOSE_VERIFY, &key, &input, &signature, nullptr)) {
-        printf("Error verifying data with imported ECDSA key\n\n");
-        return false;
-    }
-
-    printf("\n");
-    return true;
-}
-
-static bool test_ecdsa(TrustyKeymasterDevice* device) {
-    printf("==============\n");
-    printf("= ECDSA Test =\n");
-    printf("==============\n\n");
-
-    printf("=== Generating ECDSA key pair ===\n");
-    keymaster_key_blob_t key;
-    int error = device->generate_key(&ec_param_set, &key, nullptr);
-    if (error != KM_ERROR_OK) {
-        printf("Error generating ECDSA key pair: %d\n\n", error);
-        return false;
-    }
-    std::unique_ptr<const uint8_t[]> key_deleter(key.key_material);
-
-    printf("=== Signing with ECDSA key === \n");
-    size_t message_len = 30 /* arbitrary */;
-    std::unique_ptr<uint8_t[]> message(new uint8_t[message_len]);
-    memset(message.get(), 'a', message_len);
-    keymaster_blob_t input = {message.get(), message_len}, signature;
-
-    if (!do_operation(device, KM_PURPOSE_SIGN, &key, &input, nullptr, &signature)) {
-        printf("Error signing data with ECDSA key\n\n");
-        return false;
-    }
-    std::unique_ptr<const uint8_t[]> signature_deleter(signature.data);
-
-    printf("=== Verifying with ECDSA key === \n");
-    if (!do_operation(device, KM_PURPOSE_VERIFY, &key, &input, &signature, nullptr)) {
-        printf("Error verifying data with ECDSA key\n\n");
-        return false;
-    }
-
-    printf("=== Exporting ECDSA public key ===\n");
-    keymaster_blob_t exported_key;
-    error = device->export_key(KM_KEY_FORMAT_X509, &key, nullptr, nullptr, &exported_key);
-    if (error != KM_ERROR_OK) {
-        printf("Error exporting ECDSA public key: %d\n\n", error);
-        return false;
-    }
-
-    printf("=== Verifying with exported key ===\n");
-    const uint8_t* tmp = exported_key.data;
-    std::unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
-            d2i_PUBKEY(NULL, &tmp, exported_key.data_length));
-    std::unique_ptr<EVP_PKEY_CTX, EVP_PKEY_CTX_Delete> ctx(EVP_PKEY_CTX_new(pkey.get(), NULL));
-    if (EVP_PKEY_verify_init(ctx.get()) != 1) {
-        printf("Error initializing openssl EVP context\n\n");
-        return false;
-    }
-    if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) {
-        printf("Exported key was the wrong type?!?\n\n");
-        return false;
-    }
-
-    if (EVP_PKEY_verify(ctx.get(), signature.data, signature.data_length, message.get(),
-                        message_len) != 1) {
-        printf("Verification with exported pubkey failed.\n\n");
-        return false;
-    } else {
-        printf("Verification succeeded\n");
-    }
-
-    printf("\n");
-    return true;
-}
-
-int main(void) {
-    TrustyKeymasterDevice device(NULL);
-    keymaster::ConfigureDevice(reinterpret_cast<keymaster2_device_t*>(&device));
-    if (device.session_error() != KM_ERROR_OK) {
-        printf("Failed to initialize Trusty session: %d\n", device.session_error());
-        return 1;
-    }
-    printf("Trusty session initialized\n");
-
-    bool success = true;
-    success &= test_rsa(&device);
-    success &= test_import_rsa(&device);
-    success &= test_ecdsa(&device);
-    success &= test_import_ecdsa(&device);
-
-    if (success) {
-        printf("\nTESTS PASSED!\n");
-    } else {
-        printf("\n!!!!TESTS FAILED!!!\n");
-    }
-
-    return success ? 0 : 1;
-}