Merge "ueventd: Add dynamic kernel module loading"
diff --git a/adb/adb.h b/adb/adb.h
index 7e9af9e..26b5fa1 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -133,7 +133,7 @@
 int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply_fd);
 
 /* initialize a transport object's func pointers and state */
-int init_socket_transport(atransport* t, int s, int port, int local);
+int init_socket_transport(atransport* t, unique_fd s, int port, int local);
 void init_usb_transport(atransport* t, usb_handle* usb);
 
 std::string getEmulatorSerialString(int console_port);
diff --git a/adb/adb_unique_fd.h b/adb/adb_unique_fd.h
index be63262..bad501a 100644
--- a/adb/adb_unique_fd.h
+++ b/adb/adb_unique_fd.h
@@ -31,3 +31,7 @@
 #if !defined(_WIN32)
 bool Pipe(unique_fd* read, unique_fd* write, int flags = 0);
 #endif
+
+template <typename T>
+int adb_close(const android::base::unique_fd_impl<T>&)
+        __attribute__((__unavailable__("adb_close called on unique_fd")));
diff --git a/adb/client/bugreport.cpp b/adb/client/bugreport.cpp
index abef86a..346bb4b 100644
--- a/adb/client/bugreport.cpp
+++ b/adb/client/bugreport.cpp
@@ -25,8 +25,9 @@
 #include <android-base/strings.h>
 
 #include "sysdeps.h"
+
 #include "adb_utils.h"
-#include "file_sync_service.h"
+#include "client/file_sync_client.h"
 
 static constexpr char BUGZ_BEGIN_PREFIX[] = "BEGIN:";
 static constexpr char BUGZ_PROGRESS_PREFIX[] = "PROGRESS:";
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 7791895..a7a94e7 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -56,10 +56,10 @@
 #include "adb_unique_fd.h"
 #include "adb_utils.h"
 #include "bugreport.h"
+#include "client/file_sync_client.h"
 #include "commandline.h"
-#include "file_sync_service.h"
 #include "services.h"
-#include "shell_service.h"
+#include "shell_protocol.h"
 #include "sysdeps/chrono.h"
 #include "sysdeps/memory.h"
 
diff --git a/adb/client/file_sync_client.cpp b/adb/client/file_sync_client.cpp
index a438dbb..cb9bcfa 100644
--- a/adb/client/file_sync_client.cpp
+++ b/adb/client/file_sync_client.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "client/file_sync_client.h"
+
 #include <dirent.h>
 #include <inttypes.h>
 #include <limits.h>
@@ -39,7 +41,7 @@
 #include "adb_client.h"
 #include "adb_io.h"
 #include "adb_utils.h"
-#include "file_sync_service.h"
+#include "file_sync_protocol.h"
 #include "line_printer.h"
 #include "sysdeps/errno.h"
 #include "sysdeps/stat.h"
diff --git a/adb/client/file_sync_client.h b/adb/client/file_sync_client.h
new file mode 100644
index 0000000..df7f14c
--- /dev/null
+++ b/adb/client/file_sync_client.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+bool do_sync_ls(const char* path);
+bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sync);
+bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs,
+                  const char* name = nullptr);
+
+bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only);
diff --git a/adb/daemon/file_sync_service.cpp b/adb/daemon/file_sync_service.cpp
index 0b71363..8c39a20 100644
--- a/adb/daemon/file_sync_service.cpp
+++ b/adb/daemon/file_sync_service.cpp
@@ -16,8 +16,9 @@
 
 #define TRACE_TAG SYNC
 
+#include "daemon/file_sync_service.h"
+
 #include "sysdeps.h"
-#include "file_sync_service.h"
 
 #include <dirent.h>
 #include <errno.h>
@@ -42,6 +43,7 @@
 #include "adb_io.h"
 #include "adb_trace.h"
 #include "adb_utils.h"
+#include "file_sync_protocol.h"
 #include "security_log_tags.h"
 #include "sysdeps/errno.h"
 
@@ -525,7 +527,7 @@
     return true;
 }
 
-void file_sync_service(android::base::unique_fd fd) {
+void file_sync_service(unique_fd fd) {
     std::vector<char> buffer(SYNC_DATA_MAX);
 
     while (handle_sync_command(fd.get(), buffer)) {
diff --git a/adb/remount_service.h b/adb/daemon/file_sync_service.h
similarity index 65%
copy from adb/remount_service.h
copy to adb/daemon/file_sync_service.h
index 45821ee..f300e7b 100644
--- a/adb/remount_service.h
+++ b/adb/daemon/file_sync_service.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,14 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef _REMOUNT_SERVICE_H_
-#define _REMOUNT_SERVICE_H_
+#pragma once
 
-#include <string>
+#include "adb_unique_fd.h"
 
-#include <android-base/unique_fd.h>
-
-bool make_block_device_writable(const std::string&);
-void remount_service(android::base::unique_fd, const std::string&);
-
-#endif
+void file_sync_service(unique_fd fd);
diff --git a/adb/daemon/framebuffer_service.cpp b/adb/daemon/framebuffer_service.cpp
index 9a620ab..8d28c49 100644
--- a/adb/daemon/framebuffer_service.cpp
+++ b/adb/daemon/framebuffer_service.cpp
@@ -57,7 +57,7 @@
     unsigned int alpha_length;
 } __attribute__((packed));
 
-void framebuffer_service(android::base::unique_fd fd) {
+void framebuffer_service(unique_fd fd) {
     struct fbinfo fbinfo;
     unsigned int i, bsize;
     char buf[640];
diff --git a/adb/daemon/framebuffer_service.h b/adb/daemon/framebuffer_service.h
index d99c6fe..264da59 100644
--- a/adb/daemon/framebuffer_service.h
+++ b/adb/daemon/framebuffer_service.h
@@ -14,11 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef _DAEMON_FRAMEBUFFER_SERVICE_H_
-#define _DAEMON_FRAMEBUFFER_SERVICE_H_
+#pragma once
 
-#include <android-base/unique_fd.h>
+#include "adb_unique_fd.h"
 
-void framebuffer_service(android::base::unique_fd fd);
-
-#endif  // _DAEMON_FRAMEBUFFER_SERVICE_H_
+void framebuffer_service(unique_fd fd);
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index c02cafa..f6f1acc 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -18,6 +18,7 @@
 
 #include "sysdeps.h"
 
+#include <android/fdsan.h>
 #include <errno.h>
 #include <getopt.h>
 #include <malloc.h>
@@ -177,6 +178,11 @@
 
     signal(SIGPIPE, SIG_IGN);
 
+    auto fdsan_level = android_fdsan_get_error_level();
+    if (fdsan_level == ANDROID_FDSAN_ERROR_LEVEL_DISABLED) {
+        android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
+    }
+
     init_transport_registration();
 
     // We need to call this even if auth isn't enabled because the file
diff --git a/adb/daemon/remount_service.cpp b/adb/daemon/remount_service.cpp
index 1bb2fbb..76a1452 100644
--- a/adb/daemon/remount_service.cpp
+++ b/adb/daemon/remount_service.cpp
@@ -215,7 +215,7 @@
     android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_cmd.c_str());
 }
 
-void remount_service(android::base::unique_fd fd, const std::string& cmd) {
+void remount_service(unique_fd fd, const std::string& cmd) {
     bool user_requested_reboot = cmd != "-R";
 
     if (getuid() != 0) {
@@ -251,7 +251,7 @@
     if (user_requested_reboot) {
         if (!dedup.empty() || verity_enabled) {
             if (verity_enabled) {
-                set_verity_enabled_state_service(android::base::unique_fd(dup(fd.get())), false);
+                set_verity_enabled_state_service(unique_fd(dup(fd.get())), false);
             }
             reboot_for_remount(fd.get(), !dedup.empty());
             return;
diff --git a/adb/remount_service.h b/adb/daemon/remount_service.h
similarity index 80%
rename from adb/remount_service.h
rename to adb/daemon/remount_service.h
index 45821ee..e4e2550 100644
--- a/adb/remount_service.h
+++ b/adb/daemon/remount_service.h
@@ -14,14 +14,11 @@
  * limitations under the License.
  */
 
-#ifndef _REMOUNT_SERVICE_H_
-#define _REMOUNT_SERVICE_H_
+#pragma once
 
 #include <string>
 
-#include <android-base/unique_fd.h>
+#include "adb_unique_fd.h"
 
 bool make_block_device_writable(const std::string&);
-void remount_service(android::base::unique_fd, const std::string&);
-
-#endif
+void remount_service(unique_fd, const std::string&);
diff --git a/adb/daemon/set_verity_enable_state_service.cpp b/adb/daemon/set_verity_enable_state_service.cpp
index 0f804e9..8c98c2d 100644
--- a/adb/daemon/set_verity_enable_state_service.cpp
+++ b/adb/daemon/set_verity_enable_state_service.cpp
@@ -132,7 +132,7 @@
     return true;
 }
 
-void set_verity_enabled_state_service(android::base::unique_fd fd, bool enable) {
+void set_verity_enabled_state_service(unique_fd fd, bool enable) {
     bool any_changed = false;
 
     // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by
diff --git a/adb/daemon/set_verity_enable_state_service.h b/adb/daemon/set_verity_enable_state_service.h
index 9f84f35..c1413c8 100644
--- a/adb/daemon/set_verity_enable_state_service.h
+++ b/adb/daemon/set_verity_enable_state_service.h
@@ -14,11 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef _DAEMON_SET_VERITY_ENABLED_STATE_SERVICE_H_
-#define _DAEMON_SET_VERITY_ENABLED_STATE_SERVICE_H_
+#pragma once
 
-#include <android-base/unique_fd.h>
+#include "adb_unique_fd.h"
 
-void set_verity_enabled_state_service(android::base::unique_fd fd, bool enable);
-
-#endif  // _DAEMON_SET_VERITY_ENABLED_STATE_SERVICE_H_
+void set_verity_enabled_state_service(unique_fd fd, bool enable);
diff --git a/adb/daemon/shell_service.cpp b/adb/daemon/shell_service.cpp
index 56d647a..b042e5f 100644
--- a/adb/daemon/shell_service.cpp
+++ b/adb/daemon/shell_service.cpp
@@ -106,6 +106,7 @@
 #include "adb_unique_fd.h"
 #include "adb_utils.h"
 #include "security_log_tags.h"
+#include "shell_protocol.h"
 
 namespace {
 
diff --git a/adb/daemon/shell_service.h b/adb/daemon/shell_service.h
new file mode 100644
index 0000000..3ffffa7
--- /dev/null
+++ b/adb/daemon/shell_service.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+enum class SubprocessType {
+    kPty,
+    kRaw,
+};
+
+enum class SubprocessProtocol {
+    kNone,
+    kShell,
+};
+
+// Forks and starts a new shell subprocess. If |name| is empty an interactive
+// shell is started, otherwise |name| is executed non-interactively.
+//
+// Returns an open FD connected to the subprocess or -1 on failure.
+int StartSubprocess(const char* name, const char* terminal_type, SubprocessType type,
+                    SubprocessProtocol protocol);
diff --git a/adb/daemon/shell_service_test.cpp b/adb/daemon/shell_service_test.cpp
index 4e27822..d073537 100644
--- a/adb/daemon/shell_service_test.cpp
+++ b/adb/daemon/shell_service_test.cpp
@@ -27,6 +27,7 @@
 
 #include "adb.h"
 #include "adb_io.h"
+#include "shell_protocol.h"
 #include "sysdeps.h"
 
 class ShellServiceTest : public ::testing::Test {
diff --git a/adb/file_sync_protocol.h b/adb/file_sync_protocol.h
new file mode 100644
index 0000000..108639a
--- /dev/null
+++ b/adb/file_sync_protocol.h
@@ -0,0 +1,78 @@
+/*
+ * 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
+
+#define MKID(a, b, c, d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
+
+#define ID_LSTAT_V1 MKID('S', 'T', 'A', 'T')
+#define ID_STAT_V2 MKID('S', 'T', 'A', '2')
+#define ID_LSTAT_V2 MKID('L', 'S', 'T', '2')
+#define ID_LIST MKID('L', 'I', 'S', 'T')
+#define ID_SEND MKID('S', 'E', 'N', 'D')
+#define ID_RECV MKID('R', 'E', 'C', 'V')
+#define ID_DENT MKID('D', 'E', 'N', 'T')
+#define ID_DONE MKID('D', 'O', 'N', 'E')
+#define ID_DATA MKID('D', 'A', 'T', 'A')
+#define ID_OKAY MKID('O', 'K', 'A', 'Y')
+#define ID_FAIL MKID('F', 'A', 'I', 'L')
+#define ID_QUIT MKID('Q', 'U', 'I', 'T')
+
+struct SyncRequest {
+    uint32_t id;           // ID_STAT, et cetera.
+    uint32_t path_length;  // <= 1024
+    // Followed by 'path_length' bytes of path (not NUL-terminated).
+} __attribute__((packed));
+
+union syncmsg {
+    struct __attribute__((packed)) {
+        uint32_t id;
+        uint32_t mode;
+        uint32_t size;
+        uint32_t time;
+    } stat_v1;
+    struct __attribute__((packed)) {
+        uint32_t id;
+        uint32_t error;
+        uint64_t dev;
+        uint64_t ino;
+        uint32_t mode;
+        uint32_t nlink;
+        uint32_t uid;
+        uint32_t gid;
+        uint64_t size;
+        int64_t atime;
+        int64_t mtime;
+        int64_t ctime;
+    } stat_v2;
+    struct __attribute__((packed)) {
+        uint32_t id;
+        uint32_t mode;
+        uint32_t size;
+        uint32_t time;
+        uint32_t namelen;
+    } dent;
+    struct __attribute__((packed)) {
+        uint32_t id;
+        uint32_t size;
+    } data;
+    struct __attribute__((packed)) {
+        uint32_t id;
+        uint32_t msglen;
+    } status;
+};
+
+#define SYNC_DATA_MAX (64 * 1024)
diff --git a/adb/file_sync_service.h b/adb/file_sync_service.h
deleted file mode 100644
index 608b3ad..0000000
--- a/adb/file_sync_service.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef _FILE_SYNC_SERVICE_H_
-#define _FILE_SYNC_SERVICE_H_
-
-#include <string>
-#include <vector>
-
-#include <android-base/unique_fd.h>
-
-#define MKID(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
-
-#define ID_LSTAT_V1 MKID('S','T','A','T')
-#define ID_STAT_V2 MKID('S','T','A','2')
-#define ID_LSTAT_V2 MKID('L','S','T','2')
-#define ID_LIST MKID('L','I','S','T')
-#define ID_SEND MKID('S','E','N','D')
-#define ID_RECV MKID('R','E','C','V')
-#define ID_DENT MKID('D','E','N','T')
-#define ID_DONE MKID('D','O','N','E')
-#define ID_DATA MKID('D','A','T','A')
-#define ID_OKAY MKID('O','K','A','Y')
-#define ID_FAIL MKID('F','A','I','L')
-#define ID_QUIT MKID('Q','U','I','T')
-
-struct SyncRequest {
-    uint32_t id;  // ID_STAT, et cetera.
-    uint32_t path_length;  // <= 1024
-    // Followed by 'path_length' bytes of path (not NUL-terminated).
-} __attribute__((packed)) ;
-
-union syncmsg {
-    struct __attribute__((packed)) {
-        uint32_t id;
-        uint32_t mode;
-        uint32_t size;
-        uint32_t time;
-    } stat_v1;
-    struct __attribute__((packed)) {
-        uint32_t id;
-        uint32_t error;
-        uint64_t dev;
-        uint64_t ino;
-        uint32_t mode;
-        uint32_t nlink;
-        uint32_t uid;
-        uint32_t gid;
-        uint64_t size;
-        int64_t atime;
-        int64_t mtime;
-        int64_t ctime;
-    } stat_v2;
-    struct __attribute__((packed)) {
-        uint32_t id;
-        uint32_t mode;
-        uint32_t size;
-        uint32_t time;
-        uint32_t namelen;
-    } dent;
-    struct __attribute__((packed)) {
-        uint32_t id;
-        uint32_t size;
-    } data;
-    struct __attribute__((packed)) {
-        uint32_t id;
-        uint32_t msglen;
-    } status;
-};
-
-void file_sync_service(android::base::unique_fd fd);
-bool do_sync_ls(const char* path);
-bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sync);
-bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst,
-                  bool copy_attrs, const char* name=nullptr);
-
-bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only);
-
-#define SYNC_DATA_MAX (64*1024)
-
-#endif
diff --git a/adb/services.cpp b/adb/services.cpp
index 3d418cb..639bb46 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -37,7 +37,6 @@
 #include <android-base/parsenetaddress.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
-#include <android-base/unique_fd.h>
 #include <cutils/sockets.h>
 
 #if !ADB_HOST
@@ -49,31 +48,31 @@
 
 #include "adb.h"
 #include "adb_io.h"
+#include "adb_unique_fd.h"
 #include "adb_utils.h"
 #if !ADB_HOST
+#include "daemon/file_sync_service.h"
 #include "daemon/framebuffer_service.h"
+#include "daemon/remount_service.h"
 #include "daemon/set_verity_enable_state_service.h"
+#include "daemon/shell_service.h"
 #endif
-#include "file_sync_service.h"
-#include "remount_service.h"
 #include "services.h"
-#include "shell_service.h"
 #include "socket_spec.h"
 #include "sysdeps.h"
 #include "transport.h"
 
 namespace {
 
-void service_bootstrap_func(std::string service_name,
-                            std::function<void(android::base::unique_fd)> func,
-                            android::base::unique_fd fd) {
+void service_bootstrap_func(std::string service_name, std::function<void(unique_fd)> func,
+                            unique_fd fd) {
     adb_thread_setname(android::base::StringPrintf("%s svc %d", service_name.c_str(), fd.get()));
     func(std::move(fd));
 }
 
 #if !ADB_HOST
 
-void restart_root_service(android::base::unique_fd fd) {
+void restart_root_service(unique_fd fd) {
     if (getuid() == 0) {
         WriteFdExactly(fd.get(), "adbd is already running as root\n");
         return;
@@ -87,7 +86,7 @@
     WriteFdExactly(fd.get(), "restarting adbd as root\n");
 }
 
-void restart_unroot_service(android::base::unique_fd fd) {
+void restart_unroot_service(unique_fd fd) {
     if (getuid() != 0) {
         WriteFdExactly(fd.get(), "adbd not running as root\n");
         return;
@@ -96,7 +95,7 @@
     WriteFdExactly(fd.get(), "restarting adbd as non root\n");
 }
 
-void restart_tcp_service(android::base::unique_fd fd, int port) {
+void restart_tcp_service(unique_fd fd, int port) {
     if (port <= 0) {
         WriteFdFmt(fd.get(), "invalid port %d\n", port);
         return;
@@ -106,12 +105,12 @@
     WriteFdFmt(fd.get(), "restarting in TCP mode port: %d\n", port);
 }
 
-void restart_usb_service(android::base::unique_fd fd) {
+void restart_usb_service(unique_fd fd) {
     android::base::SetProperty("service.adb.tcp.port", "0");
     WriteFdExactly(fd.get(), "restarting in USB mode\n");
 }
 
-bool reboot_service_impl(android::base::unique_fd fd, const std::string& arg) {
+bool reboot_service_impl(unique_fd fd, const std::string& arg) {
     std::string reboot_arg = arg;
     bool auto_reboot = false;
 
@@ -152,7 +151,7 @@
     return true;
 }
 
-void reboot_service(android::base::unique_fd fd, const std::string& arg) {
+void reboot_service(unique_fd fd, const std::string& arg) {
     if (!reboot_service_impl(std::move(fd), arg)) {
         return;
     }
@@ -163,7 +162,7 @@
     }
 }
 
-void reconnect_service(android::base::unique_fd fd, atransport* t) {
+void reconnect_service(unique_fd fd, atransport* t) {
     WriteFdExactly(fd, "done");
     kick_transport(t);
 }
@@ -223,12 +222,11 @@
 
 #endif  // !ADB_HOST
 
-android::base::unique_fd create_service_thread(const char* service_name,
-                                               std::function<void(android::base::unique_fd)> func) {
+unique_fd create_service_thread(const char* service_name, std::function<void(unique_fd)> func) {
     int s[2];
     if (adb_socketpair(s)) {
         printf("cannot create service socket pair\n");
-        return android::base::unique_fd();
+        return unique_fd();
     }
     D("socketpair: (%d,%d)", s[0], s[1]);
 
@@ -241,10 +239,10 @@
     }
 #endif // !ADB_HOST
 
-    std::thread(service_bootstrap_func, service_name, func, android::base::unique_fd(s[1])).detach();
+    std::thread(service_bootstrap_func, service_name, func, unique_fd(s[1])).detach();
 
     D("service thread started, %d:%d",s[0], s[1]);
-    return android::base::unique_fd(s[0]);
+    return unique_fd(s[0]);
 }
 
 }  // namespace
@@ -407,7 +405,7 @@
     }
 }
 
-static void connect_service(android::base::unique_fd fd, std::string host) {
+static void connect_service(unique_fd fd, std::string host) {
     std::string response;
     if (!strncmp(host.c_str(), "emu:", 4)) {
         connect_emulator(host.c_str() + 4, &response);
diff --git a/adb/shell_service.h b/adb/shell_protocol.h
similarity index 79%
rename from adb/shell_service.h
rename to adb/shell_protocol.h
index e3d676a..2c82689 100644
--- a/adb/shell_service.h
+++ b/adb/shell_protocol.h
@@ -14,16 +14,7 @@
  * limitations under the License.
  */
 
-// This file contains classes and functionality to launch shell subprocesses
-// in adbd and communicate between those subprocesses and the adb client.
-//
-// The main features exposed here are:
-//   1. A ShellPacket class to wrap data in a simple protocol. Both adbd and
-//      the adb client use this class to transmit data between them.
-//   2. Functions to launch a subprocess on the adbd side.
-
-#ifndef SHELL_SERVICE_H_
-#define SHELL_SERVICE_H_
+#pragma once
 
 #include <stdint.h>
 
@@ -124,26 +115,3 @@
 
     DISALLOW_COPY_AND_ASSIGN(ShellProtocol);
 };
-
-#if !ADB_HOST
-
-enum class SubprocessType {
-    kPty,
-    kRaw,
-};
-
-enum class SubprocessProtocol {
-    kNone,
-    kShell,
-};
-
-// Forks and starts a new shell subprocess. If |name| is empty an interactive
-// shell is started, otherwise |name| is executed non-interactively.
-//
-// Returns an open FD connected to the subprocess or -1 on failure.
-int StartSubprocess(const char* name, const char* terminal_type,
-                    SubprocessType type, SubprocessProtocol protocol);
-
-#endif  // !ADB_HOST
-
-#endif  // SHELL_SERVICE_H_
diff --git a/adb/shell_service_protocol.cpp b/adb/shell_service_protocol.cpp
index 623629c..13b66ec 100644
--- a/adb/shell_service_protocol.cpp
+++ b/adb/shell_service_protocol.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "shell_service.h"
+#include "shell_protocol.h"
 
 #include <string.h>
 
diff --git a/adb/shell_service_protocol_test.cpp b/adb/shell_service_protocol_test.cpp
index b0fa3ed..a10b5c0 100644
--- a/adb/shell_service_protocol_test.cpp
+++ b/adb/shell_service_protocol_test.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "shell_service.h"
+#include "shell_protocol.h"
 
 #include <gtest/gtest.h>
 
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 638940c..793c283 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -1157,7 +1157,7 @@
 }
 #endif  // ADB_HOST
 
-int register_socket_transport(int s, const char* serial, int port, int local,
+int register_socket_transport(unique_fd s, const char* serial, int port, int local,
                               atransport::ReconnectCallback reconnect) {
     atransport* t = new atransport(std::move(reconnect), kCsOffline);
 
@@ -1167,8 +1167,8 @@
         serial = buf;
     }
 
-    D("transport: %s init'ing for socket %d, on port %d", serial, s, port);
-    if (init_socket_transport(t, s, port, local) < 0) {
+    D("transport: %s init'ing for socket %d, on port %d", serial, s.get(), port);
+    if (init_socket_transport(t, std::move(s), port, local) < 0) {
         delete t;
         return -1;
     }
diff --git a/adb/transport.h b/adb/transport.h
index e9c9d37..1844ae8 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -364,7 +364,7 @@
 void connect_device(const std::string& address, std::string* response);
 
 /* cause new transports to be init'd and added to the list */
-int register_socket_transport(int s, const char* serial, int port, int local,
+int register_socket_transport(unique_fd s, const char* serial, int port, int local,
                               atransport::ReconnectCallback reconnect);
 
 // This should only be used for transports with connection_state == kCsNoPerm.
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index fa38238..9398ceb 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -122,12 +122,12 @@
         // invoked if the atransport* has already been setup. This eventually
         // calls atransport->SetConnection() with a newly created Connection*
         // that will in turn send the CNXN packet.
-        return init_socket_transport(t, fd.release(), port, 0) >= 0;
+        return init_socket_transport(t, std::move(fd), port, 0) >= 0;
     };
 
-    int ret = register_socket_transport(fd.release(), serial.c_str(), port, 0, std::move(reconnect));
+    int ret =
+            register_socket_transport(std::move(fd), serial.c_str(), port, 0, std::move(reconnect));
     if (ret < 0) {
-        adb_close(fd);
         if (ret == -EALREADY) {
             *response = android::base::StringPrintf("already connected to %s", serial.c_str());
         } else {
@@ -140,7 +140,7 @@
 
 
 int local_connect_arbitrary_ports(int console_port, int adb_port, std::string* error) {
-    int fd = -1;
+    unique_fd fd;
 
 #if ADB_HOST
     if (find_emulator_transport_by_adb_port(adb_port) != nullptr ||
@@ -150,23 +150,22 @@
 
     const char *host = getenv("ADBHOST");
     if (host) {
-        fd = network_connect(host, adb_port, SOCK_STREAM, 0, error);
+        fd.reset(network_connect(host, adb_port, SOCK_STREAM, 0, error));
     }
 #endif
     if (fd < 0) {
-        fd = network_loopback_client(adb_port, SOCK_STREAM, error);
+        fd.reset(network_loopback_client(adb_port, SOCK_STREAM, error));
     }
 
     if (fd >= 0) {
-        D("client: connected on remote on fd %d", fd);
-        close_on_exec(fd);
-        disable_tcp_nagle(fd);
+        D("client: connected on remote on fd %d", fd.get());
+        close_on_exec(fd.get());
+        disable_tcp_nagle(fd.get());
         std::string serial = getEmulatorSerialString(console_port);
-        if (register_socket_transport(fd, serial.c_str(), adb_port, 1,
+        if (register_socket_transport(std::move(fd), serial.c_str(), adb_port, 1,
                                       [](atransport*) { return false; }) == 0) {
             return 0;
         }
-        adb_close(fd);
     }
     return -1;
 }
@@ -243,34 +242,31 @@
 #else // ADB_HOST
 
 static void server_socket_thread(int port) {
-    int serverfd, fd;
+    unique_fd serverfd;
 
     adb_thread_setname("server socket");
     D("transport: server_socket_thread() starting");
-    serverfd = -1;
-    for(;;) {
-        if(serverfd == -1) {
-            std::string error;
-            serverfd = network_inaddr_any_server(port, SOCK_STREAM, &error);
-            if(serverfd < 0) {
-                D("server: cannot bind socket yet: %s", error.c_str());
-                std::this_thread::sleep_for(1s);
-                continue;
-            }
-            close_on_exec(serverfd);
+    while (serverfd == -1) {
+        std::string error;
+        serverfd.reset(network_inaddr_any_server(port, SOCK_STREAM, &error));
+        if (serverfd < 0) {
+            D("server: cannot bind socket yet: %s", error.c_str());
+            std::this_thread::sleep_for(1s);
+            continue;
         }
+        close_on_exec(serverfd.get());
+    }
 
+    while (true) {
         D("server: trying to get new connection from %d", port);
-        fd = adb_socket_accept(serverfd, nullptr, nullptr);
-        if(fd >= 0) {
-            D("server: new connection on fd %d", fd);
-            close_on_exec(fd);
-            disable_tcp_nagle(fd);
-            std::string serial = android::base::StringPrintf("host-%d", fd);
-            if (register_socket_transport(fd, serial.c_str(), port, 1,
-                                          [](atransport*) { return false; }) != 0) {
-                adb_close(fd);
-            }
+        unique_fd fd(adb_socket_accept(serverfd, nullptr, nullptr));
+        if (fd >= 0) {
+            D("server: new connection on fd %d", fd.get());
+            close_on_exec(fd.get());
+            disable_tcp_nagle(fd.get());
+            std::string serial = android::base::StringPrintf("host-%d", fd.get());
+            register_socket_transport(std::move(fd), serial.c_str(), port, 1,
+                                      [](atransport*) { return false; });
         }
     }
     D("transport: server_socket_thread() exiting");
@@ -331,7 +327,6 @@
     /* 'ok' reply from the adb QEMUD service. */
     static const char _ok_resp[] = "ok";
 
-    int fd;
     char tmp[256];
     char con_name[32];
 
@@ -342,7 +337,7 @@
     snprintf(con_name, sizeof(con_name), "pipe:qemud:adb:%d", port);
 
     /* Connect to the adb QEMUD service. */
-    fd = qemu_pipe_open(con_name);
+    unique_fd fd(qemu_pipe_open(con_name));
     if (fd < 0) {
         /* This could be an older version of the emulator, that doesn't
          * implement adb QEMUD service. Fall back to the old TCP way. */
@@ -351,31 +346,28 @@
         return;
     }
 
-    for(;;) {
+    while (true) {
         /*
          * Wait till the host creates a new connection.
          */
 
         /* Send the 'accept' request. */
-        if (WriteFdExactly(fd, _accept_req, strlen(_accept_req))) {
+        if (WriteFdExactly(fd.get(), _accept_req, strlen(_accept_req))) {
             /* Wait for the response. In the response we expect 'ok' on success,
              * or 'ko' on failure. */
-            if (!ReadFdExactly(fd, tmp, 2) || memcmp(tmp, _ok_resp, 2)) {
+            if (!ReadFdExactly(fd.get(), tmp, 2) || memcmp(tmp, _ok_resp, 2)) {
                 D("Accepting ADB host connection has failed.");
-                adb_close(fd);
             } else {
                 /* Host is connected. Register the transport, and start the
                  * exchange. */
-                std::string serial = android::base::StringPrintf("host-%d", fd);
-                if (register_socket_transport(fd, serial.c_str(), port, 1,
-                                              [](atransport*) { return false; }) != 0 ||
-                    !WriteFdExactly(fd, _start_req, strlen(_start_req))) {
-                    adb_close(fd);
-                }
+                std::string serial = android::base::StringPrintf("host-%d", fd.get());
+                WriteFdExactly(fd.get(), _start_req, strlen(_start_req));
+                register_socket_transport(std::move(fd), serial.c_str(), port, 1,
+                                          [](atransport*) { return false; });
             }
 
             /* Prepare for accepting of the next ADB host connection. */
-            fd = qemu_pipe_open(con_name);
+            fd.reset(qemu_pipe_open(con_name));
             if (fd < 0) {
                 D("adb service become unavailable.");
                 return;
@@ -476,10 +468,9 @@
 }
 #endif
 
-int init_socket_transport(atransport* t, int s, int adb_port, int local) {
+int init_socket_transport(atransport* t, unique_fd fd, int adb_port, int local) {
     int fail = 0;
 
-    unique_fd fd(s);
     t->type = kTransportLocal;
 
 #if ADB_HOST
diff --git a/fastboot/usb.h b/fastboot/usb.h
index 5b44468..7ca44c4 100644
--- a/fastboot/usb.h
+++ b/fastboot/usb.h
@@ -52,6 +52,14 @@
     char device_path[256];
 };
 
+class UsbTransport : public Transport {
+    // Resets the underlying transport.  Returns 0 on success.
+    // This effectively simulates unplugging and replugging
+  public:
+    virtual int Reset() = 0;
+};
+
 typedef int (*ifc_match_func)(usb_ifc_info *ifc);
 
-Transport* usb_open(ifc_match_func callback);
+// 0 is non blocking
+UsbTransport* usb_open(ifc_match_func callback, uint32_t timeout_ms = 0);
diff --git a/fastboot/usb_linux.cpp b/fastboot/usb_linux.cpp
index 386dd30..9b779dd 100644
--- a/fastboot/usb_linux.cpp
+++ b/fastboot/usb_linux.cpp
@@ -52,7 +52,7 @@
 
 using namespace std::chrono_literals;
 
-#define MAX_RETRIES 5
+#define MAX_RETRIES 2
 
 /* Timeout in seconds for usb_wait_for_disconnect.
  * It doesn't usually take long for a device to disconnect (almost always
@@ -91,18 +91,21 @@
     unsigned char ep_out;
 };
 
-class LinuxUsbTransport : public Transport {
+class LinuxUsbTransport : public UsbTransport {
   public:
-    explicit LinuxUsbTransport(std::unique_ptr<usb_handle> handle) : handle_(std::move(handle)) {}
+    explicit LinuxUsbTransport(std::unique_ptr<usb_handle> handle, uint32_t ms_timeout = 0)
+        : handle_(std::move(handle)), ms_timeout_(ms_timeout) {}
     ~LinuxUsbTransport() override = default;
 
     ssize_t Read(void* data, size_t len) override;
     ssize_t Write(const void* data, size_t len) override;
     int Close() override;
+    int Reset() override;
     int WaitForDisconnect() override;
 
   private:
     std::unique_ptr<usb_handle> handle_;
+    const uint32_t ms_timeout_;
 
     DISALLOW_COPY_AND_ASSIGN(LinuxUsbTransport);
 };
@@ -402,7 +405,7 @@
         bulk.ep = handle_->ep_out;
         bulk.len = xfer;
         bulk.data = data;
-        bulk.timeout = 0;
+        bulk.timeout = ms_timeout_;
 
         n = ioctl(handle_->desc, USBDEVFS_BULK, &bulk);
         if(n != xfer) {
@@ -436,7 +439,7 @@
         bulk.ep = handle_->ep_in;
         bulk.len = xfer;
         bulk.data = data;
-        bulk.timeout = 0;
+        bulk.timeout = ms_timeout_;
         retry = 0;
 
         do {
@@ -447,7 +450,7 @@
             if (n < 0) {
                 DBG1("ERROR: n = %d, errno = %d (%s)\n",n, errno, strerror(errno));
                 if (++retry > MAX_RETRIES) return -1;
-                std::this_thread::sleep_for(1s);
+                std::this_thread::sleep_for(100ms);
             }
         } while (n < 0);
 
@@ -477,10 +480,19 @@
     return 0;
 }
 
-Transport* usb_open(ifc_match_func callback)
-{
+int LinuxUsbTransport::Reset() {
+    int ret = 0;
+    // We reset the USB connection
+    if ((ret = ioctl(handle_->desc, USBDEVFS_RESET, 0))) {
+        return ret;
+    }
+
+    return 0;
+}
+
+UsbTransport* usb_open(ifc_match_func callback, uint32_t timeout_ms) {
     std::unique_ptr<usb_handle> handle = find_usb_device("/sys/bus/usb/devices", callback);
-    return handle ? new LinuxUsbTransport(std::move(handle)) : nullptr;
+    return handle ? new LinuxUsbTransport(std::move(handle), timeout_ms) : nullptr;
 }
 
 /* Wait for the system to notice the device is gone, so that a subsequent
diff --git a/fastboot/usb_osx.cpp b/fastboot/usb_osx.cpp
index e95b049..4d48f6e 100644
--- a/fastboot/usb_osx.cpp
+++ b/fastboot/usb_osx.cpp
@@ -65,17 +65,21 @@
     unsigned int zero_mask;
 };
 
-class OsxUsbTransport : public Transport {
+class OsxUsbTransport : public UsbTransport {
   public:
-    OsxUsbTransport(std::unique_ptr<usb_handle> handle) : handle_(std::move(handle)) {}
+    // A timeout of 0 is blocking
+    OsxUsbTransport(std::unique_ptr<usb_handle> handle, uint32_t ms_timeout = 0)
+        : handle_(std::move(handle)), ms_timeout_(ms_timeout) {}
     ~OsxUsbTransport() override = default;
 
     ssize_t Read(void* data, size_t len) override;
     ssize_t Write(const void* data, size_t len) override;
     int Close() override;
+    int Reset() override;
 
   private:
     std::unique_ptr<usb_handle> handle_;
+    const uint32_t ms_timeout_;
 
     DISALLOW_COPY_AND_ASSIGN(OsxUsbTransport);
 };
@@ -456,7 +460,7 @@
  * Definitions of this file's public functions.
  */
 
-Transport* usb_open(ifc_match_func callback) {
+UsbTransport* usb_open(ifc_match_func callback, uint32_t timeout_ms) {
     std::unique_ptr<usb_handle> handle;
 
     if (init_usb(callback, &handle) < 0) {
@@ -464,7 +468,7 @@
         return nullptr;
     }
 
-    return new OsxUsbTransport(std::move(handle));
+    return new OsxUsbTransport(std::move(handle), timeout_ms);
 }
 
 int OsxUsbTransport::Close() {
@@ -472,6 +476,19 @@
     return 0;
 }
 
+/*
+  TODO: this SHOULD be easy to do with ResetDevice() from IOUSBDeviceInterface.
+  However to perform operations that manipulate the state of the device, you must
+  claim ownership of the device with USBDeviceOpenSeize(). However, this operation
+  always fails with kIOReturnExclusiveAccess.
+  It seems that the kext com.apple.driver.usb.AppleUSBHostCompositeDevice
+  always loads and claims ownership of the device and refuses to give it up.
+*/
+int OsxUsbTransport::Reset() {
+    ERR("USB reset is currently unsupported on osx\n");
+    return -1;
+}
+
 ssize_t OsxUsbTransport::Read(void* data, size_t len) {
     IOReturn result;
     UInt32 numBytes = len;
@@ -494,7 +511,14 @@
         return -1;
     }
 
-    result = (*handle_->interface)->ReadPipe(handle_->interface, handle_->bulkIn, data, &numBytes);
+    if (!ms_timeout_) {
+        result = (*handle_->interface)
+                         ->ReadPipe(handle_->interface, handle_->bulkIn, data, &numBytes);
+    } else {
+        result = (*handle_->interface)
+                         ->ReadPipeTO(handle_->interface, handle_->bulkIn, data, &numBytes,
+                                      ms_timeout_, ms_timeout_);
+    }
 
     if (result == 0) {
         return (int) numBytes;
@@ -541,8 +565,16 @@
         int lenToSend = lenRemaining > maxLenToSend
             ? maxLenToSend : lenRemaining;
 
-        result = (*handle_->interface)->WritePipe(
-                handle_->interface, handle_->bulkOut, (void *)data, lenToSend);
+        if (!ms_timeout_) {  // blocking
+            result = (*handle_->interface)
+                             ->WritePipe(handle_->interface, handle_->bulkOut, (void*)data,
+                                         lenToSend);
+        } else {
+            result = (*handle_->interface)
+                             ->WritePipeTO(handle_->interface, handle_->bulkOut, (void*)data,
+                                           lenToSend, ms_timeout_, ms_timeout_);
+        }
+
         if (result != 0) break;
 
         lenRemaining -= lenToSend;
diff --git a/fastboot/usb_windows.cpp b/fastboot/usb_windows.cpp
index 0e5fba1..8c60a71 100644
--- a/fastboot/usb_windows.cpp
+++ b/fastboot/usb_windows.cpp
@@ -66,7 +66,7 @@
     std::string interface_name;
 };
 
-class WindowsUsbTransport : public Transport {
+class WindowsUsbTransport : public UsbTransport {
   public:
     WindowsUsbTransport(std::unique_ptr<usb_handle> handle) : handle_(std::move(handle)) {}
     ~WindowsUsbTransport() override = default;
@@ -74,6 +74,7 @@
     ssize_t Read(void* data, size_t len) override;
     ssize_t Write(const void* data, size_t len) override;
     int Close() override;
+    int Reset() override;
 
   private:
     std::unique_ptr<usb_handle> handle_;
@@ -261,6 +262,12 @@
     return 0;
 }
 
+int WindowsUsbTransport::Reset() {
+    DBG("usb_reset currently unsupported\n\n");
+    // TODO, this is a bit complicated since it is using ADB
+    return -1;
+}
+
 int recognized_device(usb_handle* handle, ifc_match_func callback) {
     struct usb_ifc_info info;
     USB_DEVICE_DESCRIPTOR device_desc;
@@ -366,8 +373,7 @@
     return handle;
 }
 
-Transport* usb_open(ifc_match_func callback)
-{
+UsbTransport* usb_open(ifc_match_func callback, uint32_t) {
     std::unique_ptr<usb_handle> handle = find_usb_device(callback);
     return handle ? new WindowsUsbTransport(std::move(handle)) : nullptr;
 }
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index a3ce879..bf69096 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -30,7 +30,7 @@
     ],
 }
 
-cc_library_static {
+cc_library {
     name: "libfs_mgr",
     defaults: ["fs_mgr_defaults"],
     recovery_available: true,
@@ -44,15 +44,20 @@
         "fs_mgr_avb_ops.cpp",
         "fs_mgr_dm_linear.cpp",
     ],
-    static_libs: [
+    shared_libs: [
         "libfec",
         "libfec_rs",
         "libbase",
         "libcrypto_utils",
         "libcrypto",
+        "libcutils",
         "libext4_utils",
+        "libkeyutils",
+        "liblog",
         "libsquashfs_utils",
         "libselinux",
+    ],
+    static_libs: [
         "libavb",
         "libfstab",
         "libdm",
diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp
index 20b26df..7c18267 100644
--- a/fs_mgr/libdm/dm_target.cpp
+++ b/fs_mgr/libdm/dm_target.cpp
@@ -111,5 +111,9 @@
     return base + " " + std::to_string(optional_args_.size()) + " " + optional;
 }
 
+std::string DmTargetAndroidVerity::GetParameterString() const {
+    return keyid_ + " " + block_device_;
+}
+
 }  // namespace dm
 }  // namespace android
diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h
index d5974f4..31863c8 100644
--- a/fs_mgr/libdm/include/libdm/dm_target.h
+++ b/fs_mgr/libdm/include/libdm/dm_target.h
@@ -128,6 +128,20 @@
     bool valid_;
 };
 
+class DmTargetAndroidVerity final : public DmTarget {
+  public:
+    DmTargetAndroidVerity(uint64_t start, uint64_t length, const std::string& block_device,
+                          const std::string& keyid)
+        : DmTarget(start, length), keyid_(keyid), block_device_(block_device) {}
+
+    std::string name() const override { return "android-verity"; }
+    std::string GetParameterString() const override;
+
+  private:
+    std::string keyid_;
+    std::string block_device_;
+};
+
 // This is the same as DmTargetVerity, but the table may be specified as a raw
 // string. This code exists only for fs_mgr_verity and should be avoided. Use
 // DmTargetVerity for new code instead.
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index 5e11c84..45a81af 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -40,6 +40,7 @@
 using DmTarget = ::android::dm::DmTarget;
 using DmTargetLinear = ::android::dm::DmTargetLinear;
 using DmTargetZero = ::android::dm::DmTargetZero;
+using DmTargetAndroidVerity = ::android::dm::DmTargetAndroidVerity;
 using DmTargetTypeInfo = ::android::dm::DmTargetTypeInfo;
 using DmBlockDevice = ::android::dm::DeviceMapper::DmBlockDevice;
 
@@ -96,6 +97,16 @@
             }
             return std::make_unique<DmTargetLinear>(start_sector, num_sectors, block_device,
                                                     physical_sector);
+        } else if (target_type == "android-verity") {
+            if (!HasArgs(2)) {
+                std::cerr << "Expected \"android-verity\" <public-key-id> <block_device>"
+                          << std::endl;
+                return nullptr;
+            }
+            std::string keyid = NextArg();
+            std::string block_device = NextArg();
+            return std::make_unique<DmTargetAndroidVerity>(start_sector, num_sectors, keyid,
+                                                           block_device);
         } else {
             std::cerr << "Unrecognized target type: " << target_type << std::endl;
             return nullptr;
@@ -132,11 +143,11 @@
     while (arg_index < argc && argv[arg_index][0] == '-') {
         if (strcmp(argv[arg_index], "-ro") == 0) {
             table.set_readonly(true);
+            arg_index++;
         } else {
             std::cerr << "Unrecognized option: " << argv[arg_index] << std::endl;
             return -EINVAL;
         }
-        arg_index++;
     }
 
     // Parse everything else as target information.
diff --git a/gatekeeperd/OWNERS b/gatekeeperd/OWNERS
new file mode 100644
index 0000000..9c99c6e
--- /dev/null
+++ b/gatekeeperd/OWNERS
@@ -0,0 +1,2 @@
+swillden@google.com
+jdanis@google.com
diff --git a/liblog/include/log/log_main.h b/liblog/include/log/log_main.h
index 9c68ff2..1314330 100644
--- a/liblog/include/log/log_main.h
+++ b/liblog/include/log/log_main.h
@@ -47,7 +47,8 @@
  * so don't link with __clang_analyzer__ defined.
  */
 #ifdef __clang_analyzer__
-extern void __FAKE_USE_VA_ARGS(...);
+extern void __fake_use_va_args(int, ...);
+#define __FAKE_USE_VA_ARGS(...) __fake_use_va_args(0, ##__VA_ARGS__)
 #else
 #define __FAKE_USE_VA_ARGS(...) ((void)(0))
 #endif
diff --git a/libunwindstack/DexFile.cpp b/libunwindstack/DexFile.cpp
index b18b0ce..3d982f6 100644
--- a/libunwindstack/DexFile.cpp
+++ b/libunwindstack/DexFile.cpp
@@ -68,17 +68,51 @@
     return false;  // The DEX offset is not within the bytecode of this dex file.
   }
 
-  for (uint32_t i = 0; i < dex_file_->NumClassDefs(); ++i) {
-    const art::DexFile::ClassDef& class_def = dex_file_->GetClassDef(i);
+  if (dex_file_->IsCompactDexFile()) {
+    // The data section of compact dex files might be shared.
+    // Check the subrange unique to this compact dex.
+    const auto& cdex_header = dex_file_->AsCompactDexFile()->GetHeader();
+    uint32_t begin = cdex_header.data_off_ + cdex_header.OwnedDataBegin();
+    uint32_t end = cdex_header.data_off_ + cdex_header.OwnedDataEnd();
+    if (dex_offset < begin || dex_offset >= end) {
+      return false;  // The DEX offset is not within the bytecode of this dex file.
+    }
+  }
+
+  // The method data is cached in a std::map indexed by method end offset and
+  // contains the start offset and the method member index.
+  // Only cache the method data as it is searched. Do not read the entire
+  // set of method data into the cache at once.
+  // This is done because many unwinds only find a single frame with dex file
+  // info, so reading the entire method data is wasteful. However, still cache
+  // the data so that anything doing multiple unwinds will have this data
+  // cached for future use.
+
+  // First look in the method cache.
+  auto entry = method_cache_.upper_bound(dex_offset);
+  if (entry != method_cache_.end() && dex_offset >= entry->second.first) {
+    *method_name = dex_file_->PrettyMethod(entry->second.second, false);
+    *method_offset = dex_offset - entry->second.first;
+    return true;
+  }
+
+  // Check the methods we haven't cached.
+  for (; class_def_index_ < dex_file_->NumClassDefs(); class_def_index_++) {
+    const art::DexFile::ClassDef& class_def = dex_file_->GetClassDef(class_def_index_);
     const uint8_t* class_data = dex_file_->GetClassData(class_def);
     if (class_data == nullptr) {
       continue;
     }
-    for (art::ClassDataItemIterator it(*dex_file_.get(), class_data); it.HasNext(); it.Next()) {
-      if (!it.IsAtMethod()) {
+
+    if (class_it_.get() == nullptr || !class_it_->HasNext()) {
+      class_it_.reset(new art::ClassDataItemIterator(*dex_file_.get(), class_data));
+    }
+
+    for (; class_it_->HasNext(); class_it_->Next()) {
+      if (!class_it_->IsAtMethod()) {
         continue;
       }
-      const art::DexFile::CodeItem* code_item = it.GetMethodCodeItem();
+      const art::DexFile::CodeItem* code_item = class_it_->GetMethodCodeItem();
       if (code_item == nullptr) {
         continue;
       }
@@ -87,11 +121,15 @@
         continue;
       }
 
-      uint64_t offset = reinterpret_cast<const uint8_t*>(code.Insns()) - dex_file_->Begin();
-      size_t size = code.InsnsSizeInCodeUnits() * sizeof(uint16_t);
-      if (offset <= dex_offset && dex_offset < offset + size) {
-        *method_name = dex_file_->PrettyMethod(it.GetMemberIndex(), false);
+      uint32_t offset = reinterpret_cast<const uint8_t*>(code.Insns()) - dex_file_->Begin();
+      uint32_t offset_end = offset + code.InsnsSizeInCodeUnits() * sizeof(uint16_t);
+      uint32_t member_index = class_it_->GetMemberIndex();
+      method_cache_[offset_end] = std::make_pair(offset, member_index);
+      if (offset <= dex_offset && dex_offset < offset_end) {
+        *method_name = dex_file_->PrettyMethod(member_index, false);
         *method_offset = dex_offset - offset;
+        // Move past this element.
+        class_it_->Next();
         return true;
       }
     }
diff --git a/libunwindstack/DexFile.h b/libunwindstack/DexFile.h
index 3ce2f1e..508692d 100644
--- a/libunwindstack/DexFile.h
+++ b/libunwindstack/DexFile.h
@@ -19,8 +19,10 @@
 
 #include <stdint.h>
 
+#include <map>
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include <dex/dex_file-inl.h>
@@ -37,7 +39,13 @@
   static DexFile* Create(uint64_t dex_file_offset_in_memory, Memory* memory, MapInfo* info);
 
  protected:
+  void Init();
+
   std::unique_ptr<const art::DexFile> dex_file_;
+  std::map<uint32_t, std::pair<uint64_t, uint32_t>> method_cache_;  // dex offset to method index.
+
+  uint32_t class_def_index_ = 0;
+  std::unique_ptr<art::ClassDataItemIterator> class_it_;
 };
 
 class DexFileFromFile : public DexFile {
diff --git a/libunwindstack/tests/DexFileTest.cpp b/libunwindstack/tests/DexFileTest.cpp
index 0b02c5b..4dd8cb0 100644
--- a/libunwindstack/tests/DexFileTest.cpp
+++ b/libunwindstack/tests/DexFileTest.cpp
@@ -206,15 +206,42 @@
 
   std::string method;
   uint64_t method_offset;
-  dex_file->GetMethodInformation(0x102, &method, &method_offset);
+  ASSERT_TRUE(dex_file->GetMethodInformation(0x102, &method, &method_offset));
   EXPECT_EQ("Main.<init>", method);
   EXPECT_EQ(2U, method_offset);
 
-  method = "not_in_a_method";
-  method_offset = 0x123;
-  dex_file->GetMethodInformation(0x100000, &method, &method_offset);
-  EXPECT_EQ("not_in_a_method", method);
-  EXPECT_EQ(0x123U, method_offset);
+  ASSERT_TRUE(dex_file->GetMethodInformation(0x118, &method, &method_offset));
+  EXPECT_EQ("Main.main", method);
+  EXPECT_EQ(0U, method_offset);
+
+  // Make sure that any data that is cached is still retrievable.
+  ASSERT_TRUE(dex_file->GetMethodInformation(0x104, &method, &method_offset));
+  EXPECT_EQ("Main.<init>", method);
+  EXPECT_EQ(4U, method_offset);
+
+  ASSERT_TRUE(dex_file->GetMethodInformation(0x119, &method, &method_offset));
+  EXPECT_EQ("Main.main", method);
+  EXPECT_EQ(1U, method_offset);
+}
+
+TEST(DexFileTest, get_method_empty) {
+  MemoryFake memory;
+  memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
+  MapInfo info(0x100, 0x10000, 0x200, 0x5, "");
+  std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
+  ASSERT_TRUE(dex_file != nullptr);
+
+  std::string method;
+  uint64_t method_offset;
+  EXPECT_FALSE(dex_file->GetMethodInformation(0x100000, &method, &method_offset));
+
+  EXPECT_FALSE(dex_file->GetMethodInformation(0x98, &method, &method_offset));
+
+  // Make sure that once the whole dex file has been cached, no problems occur.
+  EXPECT_FALSE(dex_file->GetMethodInformation(0x98, &method, &method_offset));
+
+  // Choose a value that is in the cached map, but not in a valid method.
+  EXPECT_FALSE(dex_file->GetMethodInformation(0x110, &method, &method_offset));
 }
 
 }  // namespace unwindstack
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 1cfef34..c2487d6 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -332,7 +332,7 @@
         data->fd = -1;
         return -1;
     }
-    ALOG_ASSERT((size_t)size < buf_size - 1, data->filename " too large");
+    ALOG_ASSERT((size_t)size < buf_size - 1, "%s too large", data->filename);
     buf[size] = 0;
 
     return 0;
diff --git a/trusty/OWNERS b/trusty/OWNERS
index 357b4f4..e807d71 100644
--- a/trusty/OWNERS
+++ b/trusty/OWNERS
@@ -1,3 +1,7 @@
-bohr@google.com
-swillden@google.com
+arve@google.com
 dkrahn@google.com
+drewry@google.com
+gmar@google.com
+ncbray@google.com
+rpere@google.com
+swillden@google.com
diff --git a/trusty/libtrusty/tipc-test/tipc_test.c b/trusty/libtrusty/tipc-test/tipc_test.c
index 1fb34c9..d20d4ee 100644
--- a/trusty/libtrusty/tipc-test/tipc_test.c
+++ b/trusty/libtrusty/tipc-test/tipc_test.c
@@ -587,8 +587,15 @@
 
 static int ta2ta_ipc_test(void)
 {
+	enum test_message_header {
+		TEST_PASSED = 0,
+		TEST_FAILED = 1,
+		TEST_MESSAGE = 2,
+	};
+
 	int fd;
-	char rx_buf[64];
+	int ret;
+	unsigned char rx_buf[256];
 
 	if (!opt_silent) {
 		printf("%s:\n", __func__);
@@ -601,12 +608,31 @@
 		return fd;
 	}
 
-	/* wait for test to complete */
-	(void) read(fd, rx_buf, sizeof(rx_buf));
+	/* Wait for tests to complete and read status */
+	while (true) {
+		ret = read(fd, rx_buf, sizeof(rx_buf));
+		if (ret <= 0 || ret >= (int)sizeof(rx_buf)) {
+			fprintf(stderr, "%s: Read failed: %d\n", __func__, ret);
+			tipc_close(fd);
+			return -1;
+		}
+
+		if (rx_buf[0] == TEST_PASSED) {
+			break;
+		} else if (rx_buf[0] == TEST_FAILED) {
+			break;
+		} else if (rx_buf[0] == TEST_MESSAGE) {
+			write(STDOUT_FILENO, rx_buf + 1, ret - 1);
+		} else {
+			fprintf(stderr, "%s: Bad message header: %d\n",
+			        __func__, rx_buf[0]);
+			break;
+		}
+	}
 
 	tipc_close(fd);
 
-	return 0;
+	return rx_buf[0] == TEST_PASSED ? 0 : -1;
 }
 
 typedef struct uuid