Merge "logd: statistics truncate name"
diff --git a/adb/Android.mk b/adb/Android.mk
index e841205..d17b063 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -81,12 +81,14 @@
 
 LIBADB_darwin_SRC_FILES := \
     sysdeps_unix.cpp \
+    sysdeps/posix/network.cpp \
     client/usb_dispatch.cpp \
     client/usb_libusb.cpp \
     client/usb_osx.cpp \
 
 LIBADB_linux_SRC_FILES := \
     sysdeps_unix.cpp \
+    sysdeps/posix/network.cpp \
     client/usb_dispatch.cpp \
     client/usb_libusb.cpp \
     client/usb_linux.cpp \
@@ -123,6 +125,7 @@
     $(LIBADB_SRC_FILES) \
     adbd_auth.cpp \
     jdwp_service.cpp \
+    sysdeps/posix/network.cpp \
 
 LOCAL_SANITIZE := $(adb_target_sanitize)
 
@@ -217,9 +220,9 @@
 LOCAL_SRC_FILES_darwin := $(LIBADB_TEST_darwin_SRCS)
 LOCAL_SRC_FILES_windows := $(LIBADB_TEST_windows_SRCS)
 LOCAL_SANITIZE := $(adb_host_sanitize)
-LOCAL_SHARED_LIBRARIES := libbase
 LOCAL_STATIC_LIBRARIES := \
     libadb \
+    libbase \
     libcrypto_utils \
     libcrypto \
     libcutils \
diff --git a/adb/client/usb_linux.cpp b/adb/client/usb_linux.cpp
index 13b7674..3a45dbd 100644
--- a/adb/client/usb_linux.cpp
+++ b/adb/client/usb_linux.cpp
@@ -574,7 +574,7 @@
     register_usb_transport(done_usb, serial.c_str(), dev_path, done_usb->writeable);
 }
 
-static void device_poll_thread(void*) {
+static void device_poll_thread() {
     adb_thread_setname("device poll");
     D("Created device thread");
     while (true) {
@@ -593,8 +593,6 @@
     actions.sa_handler = [](int) {};
     sigaction(SIGALRM, &actions, nullptr);
 
-    if (!adb_thread_create(device_poll_thread, nullptr)) {
-        fatal_errno("cannot create device_poll thread");
-    }
+    std::thread(device_poll_thread).detach();
 }
 } // namespace native
diff --git a/adb/client/usb_osx.cpp b/adb/client/usb_osx.cpp
index d4fc7c0..8713b2c 100644
--- a/adb/client/usb_osx.cpp
+++ b/adb/client/usb_osx.cpp
@@ -405,7 +405,7 @@
 
 std::mutex& operate_device_lock = *new std::mutex();
 
-static void RunLoopThread(void* unused) {
+static void RunLoopThread() {
     adb_thread_setname("RunLoop");
 
     VLOG(USB) << "RunLoopThread started";
@@ -436,9 +436,7 @@
 
         usb_inited_flag = false;
 
-        if (!adb_thread_create(RunLoopThread, nullptr)) {
-            fatal_errno("cannot create RunLoop thread");
-        }
+        std::thread(RunLoopThread).detach();
 
         // Wait for initialization to finish
         while (!usb_inited_flag) {
diff --git a/adb/client/usb_windows.cpp b/adb/client/usb_windows.cpp
index 640e91e..9e00a5d 100644
--- a/adb/client/usb_windows.cpp
+++ b/adb/client/usb_windows.cpp
@@ -103,7 +103,7 @@
 
 /// Entry point for thread that polls (every second) for new usb interfaces.
 /// This routine calls find_devices in infinite loop.
-static void device_poll_thread(void*);
+static void device_poll_thread();
 
 /// Initializes this module
 void usb_init();
@@ -174,7 +174,7 @@
   return 1;
 }
 
-void device_poll_thread(void*) {
+void device_poll_thread() {
   adb_thread_setname("Device Poll");
   D("Created device thread");
 
@@ -203,7 +203,7 @@
   return DefWindowProcW(hwnd, uMsg, wParam, lParam);
 }
 
-static void _power_notification_thread(void*) {
+static void _power_notification_thread() {
   // This uses a thread with its own window message pump to get power
   // notifications. If adb runs from a non-interactive service account, this
   // might not work (not sure). If that happens to not work, we could use
@@ -258,12 +258,8 @@
 }
 
 void usb_init() {
-  if (!adb_thread_create(device_poll_thread, nullptr)) {
-    fatal_errno("cannot create device poll thread");
-  }
-  if (!adb_thread_create(_power_notification_thread, nullptr)) {
-    fatal_errno("cannot create power notification thread");
-  }
+  std::thread(device_poll_thread).detach();
+  std::thread(_power_notification_thread).detach();
 }
 
 usb_handle* do_usb_open(const wchar_t* interface_name) {
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index ed6693c..7702b0e 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -655,13 +655,8 @@
 #endif
 
     // TODO: combine read_and_dump with stdin_read_thread to make life simpler?
-    int exit_code = 1;
-    if (!adb_thread_create(stdin_read_thread_loop, args)) {
-        PLOG(ERROR) << "error starting stdin read thread";
-        delete args;
-    } else {
-        exit_code = read_and_dump(fd, use_shell_protocol);
-    }
+    std::thread(stdin_read_thread_loop, args).detach();
+    int exit_code = read_and_dump(fd, use_shell_protocol);
 
     // TODO: properly exit stdin_read_thread_loop and close |fd|.
 
diff --git a/adb/daemon/mdns.cpp b/adb/daemon/mdns.cpp
index 7811143..849378f 100644
--- a/adb/daemon/mdns.cpp
+++ b/adb/daemon/mdns.cpp
@@ -17,12 +17,14 @@
 #include "adb_mdns.h"
 #include "sysdeps.h"
 
-#include <chrono>
 #include <dns_sd.h>
 #include <endian.h>
-#include <mutex>
 #include <unistd.h>
 
+#include <chrono>
+#include <mutex>
+#include <thread>
+
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 
@@ -58,7 +60,7 @@
     }
 }
 
-static void setup_mdns_thread(void* /* unused */) {
+static void setup_mdns_thread() {
     start_mdns();
     std::lock_guard<std::mutex> lock(mdns_lock);
 
@@ -88,7 +90,7 @@
 
 void setup_mdns(int port_in) {
     port = port_in;
-    adb_thread_create(setup_mdns_thread, nullptr, nullptr);
+    std::thread(setup_mdns_thread).detach();
 
     // TODO: Make this more robust against a hard kill.
     atexit(teardown_mdns);
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index 92e9039..7e46b02 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -451,9 +451,7 @@
     h->close = usb_ffs_close;
 
     D("[ usb_init - starting thread ]");
-    if (!adb_thread_create(usb_ffs_open_thread, h)) {
-        fatal_errno("[ cannot create usb thread ]\n");
-    }
+    std::thread(usb_ffs_open_thread, h).detach();
 }
 
 void usb_init() {
diff --git a/adb/fdevent_test.cpp b/adb/fdevent_test.cpp
index c933ed5..bdb973a 100644
--- a/adb/fdevent_test.cpp
+++ b/adb/fdevent_test.cpp
@@ -21,6 +21,7 @@
 #include <limits>
 #include <queue>
 #include <string>
+#include <thread>
 #include <vector>
 
 #include "adb_io.h"
@@ -77,9 +78,9 @@
 };
 
 TEST_F(FdeventTest, fdevent_terminate) {
-    adb_thread_t thread;
     PrepareThread();
-    ASSERT_TRUE(adb_thread_create([](void*) { fdevent_loop(); }, nullptr, &thread));
+
+    std::thread thread(fdevent_loop);
     TerminateThread(thread);
 }
 
@@ -112,7 +113,6 @@
     int fd_pair2[2];
     ASSERT_EQ(0, adb_socketpair(fd_pair1));
     ASSERT_EQ(0, adb_socketpair(fd_pair2));
-    adb_thread_t thread;
     ThreadArg thread_arg;
     thread_arg.first_read_fd = fd_pair1[0];
     thread_arg.last_write_fd = fd_pair2[1];
@@ -121,8 +121,7 @@
     int reader = fd_pair2[0];
 
     PrepareThread();
-    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(FdEventThreadFunc), &thread_arg,
-                                  &thread));
+    std::thread thread(FdEventThreadFunc, &thread_arg);
 
     for (size_t i = 0; i < MESSAGE_LOOP_COUNT; ++i) {
         std::string read_buffer = MESSAGE;
@@ -152,7 +151,7 @@
     }
 }
 
-static void InvalidFdThreadFunc(void*) {
+static void InvalidFdThreadFunc() {
     const int INVALID_READ_FD = std::numeric_limits<int>::max() - 1;
     size_t happened_event_count = 0;
     InvalidFdArg read_arg;
@@ -171,7 +170,6 @@
 }
 
 TEST_F(FdeventTest, invalid_fd) {
-    adb_thread_t thread;
-    ASSERT_TRUE(adb_thread_create(InvalidFdThreadFunc, nullptr, &thread));
-    ASSERT_TRUE(adb_thread_join(thread));
+    std::thread thread(InvalidFdThreadFunc);
+    thread.join();
 }
diff --git a/adb/fdevent_test.h b/adb/fdevent_test.h
index ef65b74..f4215ae 100644
--- a/adb/fdevent_test.h
+++ b/adb/fdevent_test.h
@@ -16,6 +16,8 @@
 
 #include <gtest/gtest.h>
 
+#include <thread>
+
 #include "socket.h"
 #include "sysdeps.h"
 
@@ -59,10 +61,10 @@
 #endif
     }
 
-    void TerminateThread(adb_thread_t thread) {
+    void TerminateThread(std::thread& thread) {
         fdevent_terminate_loop();
         ASSERT_TRUE(WriteFdExactly(dummy, "", 1));
-        ASSERT_TRUE(adb_thread_join(thread));
+        thread.join();
         ASSERT_EQ(0, adb_close(dummy));
     }
 };
diff --git a/adb/services.cpp b/adb/services.cpp
index 47f0a03..f764c52 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -31,6 +31,8 @@
 #include <unistd.h>
 #endif
 
+#include <thread>
+
 #include <android-base/file.h>
 #include <android-base/parsenetaddress.h>
 #include <android-base/stringprintf.h>
@@ -259,13 +261,7 @@
     sti->cookie = cookie;
     sti->fd = s[1];
 
-    if (!adb_thread_create(service_bootstrap_func, sti)) {
-        free(sti);
-        adb_close(s[0]);
-        adb_close(s[1]);
-        printf("cannot create service thread\n");
-        return -1;
-    }
+    std::thread(service_bootstrap_func, sti).detach();
 
     D("service thread started, %d:%d",s[0], s[1]);
     return s[0];
diff --git a/adb/shell_service.cpp b/adb/shell_service.cpp
index d4f334b..ee821f8 100644
--- a/adb/shell_service.cpp
+++ b/adb/shell_service.cpp
@@ -90,6 +90,7 @@
 
 #include <memory>
 #include <string>
+#include <thread>
 #include <unordered_map>
 #include <vector>
 
@@ -392,12 +393,7 @@
 
 bool Subprocess::StartThread(std::unique_ptr<Subprocess> subprocess, std::string* error) {
     Subprocess* raw = subprocess.release();
-    if (!adb_thread_create(ThreadHandler, raw)) {
-        *error =
-            android::base::StringPrintf("failed to create subprocess thread: %s", strerror(errno));
-        kill(raw->pid_, SIGKILL);
-        return false;
-    }
+    std::thread(ThreadHandler, raw).detach();
 
     return true;
 }
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index f56f7f7..f7c66db 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -42,10 +42,6 @@
 
 class LocalSocketTest : public FdeventTest {};
 
-static void FdEventThreadFunc(void*) {
-    fdevent_loop();
-}
-
 constexpr auto SLEEP_FOR_FDEVENT = 100ms;
 
 TEST_F(LocalSocketTest, smoke) {
@@ -88,8 +84,7 @@
     connect(prev_tail, end);
 
     PrepareThread();
-    adb_thread_t thread;
-    ASSERT_TRUE(adb_thread_create(FdEventThreadFunc, nullptr, &thread));
+    std::thread thread(fdevent_loop);
 
     for (size_t i = 0; i < MESSAGE_LOOP_COUNT; ++i) {
         std::string read_buffer = MESSAGE;
@@ -152,9 +147,7 @@
     arg.cause_close_fd = cause_close_fd[1];
 
     PrepareThread();
-    adb_thread_t thread;
-    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(CloseWithPacketThreadFunc),
-                                  &arg, &thread));
+    std::thread thread(CloseWithPacketThreadFunc, &arg);
     // Wait until the fdevent_loop() starts.
     std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     ASSERT_EQ(0, adb_close(cause_close_fd[0]));
@@ -177,9 +170,7 @@
     arg.cause_close_fd = cause_close_fd[1];
 
     PrepareThread();
-    adb_thread_t thread;
-    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(CloseWithPacketThreadFunc),
-                                  &arg, &thread));
+    std::thread thread(CloseWithPacketThreadFunc, &arg);
     // Wait until the fdevent_loop() starts.
     std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     ASSERT_EQ(0, adb_close(cause_close_fd[0]));
@@ -211,10 +202,7 @@
     arg.cause_close_fd = cause_close_fd[1];
 
     PrepareThread();
-    adb_thread_t thread;
-    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(CloseWithPacketThreadFunc),
-                                  &arg, &thread));
-
+    std::thread thread(CloseWithPacketThreadFunc, &arg);
     // Wait until the fdevent_loop() starts.
     std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     EXPECT_EQ(2u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
@@ -252,9 +240,7 @@
     int listen_fd = network_inaddr_any_server(5038, SOCK_STREAM, &error);
     ASSERT_GE(listen_fd, 0);
 
-    adb_thread_t client_thread;
-    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(ClientThreadFunc), nullptr,
-                                  &client_thread));
+    std::thread client_thread(ClientThreadFunc);
 
     int accept_fd = adb_socket_accept(listen_fd, nullptr, nullptr);
     ASSERT_GE(accept_fd, 0);
@@ -262,16 +248,14 @@
     arg.socket_fd = accept_fd;
 
     PrepareThread();
-    adb_thread_t thread;
-    ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(CloseRdHupSocketThreadFunc),
-                                  &arg, &thread));
+    std::thread thread(CloseRdHupSocketThreadFunc, &arg);
 
     // Wait until the fdevent_loop() starts.
     std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     EXPECT_EQ(1u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
 
     // Wait until the client closes its socket.
-    ASSERT_TRUE(adb_thread_join(client_thread));
+    client_thread.join();
 
     std::this_thread::sleep_for(SLEEP_FOR_FDEVENT);
     ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index f95a855..49c7847 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -35,6 +35,7 @@
 #include <android-base/utf8.h>
 
 #include "sysdeps/errno.h"
+#include "sysdeps/network.h"
 #include "sysdeps/stat.h"
 
 /*
@@ -98,64 +99,6 @@
     return c == '\\' || c == '/';
 }
 
-typedef void (*adb_thread_func_t)(void* arg);
-typedef HANDLE adb_thread_t;
-
-struct adb_winthread_args {
-    adb_thread_func_t func;
-    void* arg;
-};
-
-static unsigned __stdcall adb_winthread_wrapper(void* heap_args) {
-    // Move the arguments from the heap onto the thread's stack.
-    adb_winthread_args thread_args = *static_cast<adb_winthread_args*>(heap_args);
-    delete static_cast<adb_winthread_args*>(heap_args);
-    thread_args.func(thread_args.arg);
-    return 0;
-}
-
-static __inline__ bool adb_thread_create(adb_thread_func_t func, void* arg,
-                                         adb_thread_t* thread = nullptr) {
-    adb_winthread_args* args = new adb_winthread_args{.func = func, .arg = arg};
-    uintptr_t handle = _beginthreadex(nullptr, 0, adb_winthread_wrapper, args, 0, nullptr);
-    if (handle != static_cast<uintptr_t>(0)) {
-        if (thread) {
-            *thread = reinterpret_cast<HANDLE>(handle);
-        } else {
-            CloseHandle(thread);
-        }
-        return true;
-    }
-    return false;
-}
-
-static __inline__ bool adb_thread_join(adb_thread_t thread) {
-    switch (WaitForSingleObject(thread, INFINITE)) {
-        case WAIT_OBJECT_0:
-            CloseHandle(thread);
-            return true;
-
-        case WAIT_FAILED:
-            fprintf(stderr, "adb_thread_join failed: %s\n",
-                    android::base::SystemErrorCodeToString(GetLastError()).c_str());
-            break;
-
-        default:
-            abort();
-    }
-
-    return false;
-}
-
-static __inline__ bool adb_thread_detach(adb_thread_t thread) {
-    CloseHandle(thread);
-    return true;
-}
-
-static __inline__ void __attribute__((noreturn)) adb_thread_exit() {
-    _endthreadex(0);
-}
-
 static __inline__ int adb_thread_setname(const std::string& name) {
     // TODO: See https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx for how to set
     // the thread name in Windows. Unfortunately, it only works during debugging, but
@@ -163,14 +106,6 @@
     return 0;
 }
 
-static __inline__ adb_thread_t adb_thread_self() {
-    return GetCurrentThread();
-}
-
-static __inline__ bool adb_thread_equal(adb_thread_t lhs, adb_thread_t rhs) {
-    return GetThreadId(lhs) == GetThreadId(rhs);
-}
-
 static __inline__  unsigned long adb_thread_id()
 {
     return GetCurrentThreadId();
@@ -248,8 +183,6 @@
 int unix_isatty(int fd);
 #define  isatty  ___xxx_isatty
 
-int network_loopback_client(int port, int type, std::string* error);
-int network_loopback_server(int port, int type, std::string* error);
 int network_inaddr_any_server(int port, int type, std::string* error);
 
 inline int network_local_client(const char* name, int namespace_id, int type, std::string* error) {
@@ -587,17 +520,6 @@
   return fd;
 }
 
-inline int network_loopback_client(int port, int type, std::string* error) {
-  return _fd_set_error_str(socket_network_client("localhost", port, type), error);
-}
-
-inline int network_loopback_server(int port, int type, std::string* error) {
-  int fd = socket_loopback_server(port, type);
-  if (fd < 0 && errno == EAFNOSUPPORT)
-      return _fd_set_error_str(socket_loopback_server6(port, type), error);
-  return _fd_set_error_str(fd, error);
-}
-
 inline int network_inaddr_any_server(int port, int type, std::string* error) {
   return _fd_set_error_str(socket_inaddr_any_server(port, type), error);
 }
@@ -656,55 +578,6 @@
 #define  unix_write  adb_write
 #define  unix_close  adb_close
 
-// Win32 is limited to DWORDs for thread return values; limit the POSIX systems to this as well to
-// ensure compatibility.
-typedef void (*adb_thread_func_t)(void* arg);
-typedef pthread_t adb_thread_t;
-
-struct adb_pthread_args {
-    adb_thread_func_t func;
-    void* arg;
-};
-
-static void* adb_pthread_wrapper(void* heap_args) {
-    // Move the arguments from the heap onto the thread's stack.
-    adb_pthread_args thread_args = *reinterpret_cast<adb_pthread_args*>(heap_args);
-    delete static_cast<adb_pthread_args*>(heap_args);
-    thread_args.func(thread_args.arg);
-    return nullptr;
-}
-
-static __inline__ bool adb_thread_create(adb_thread_func_t start, void* arg,
-                                         adb_thread_t* thread = nullptr) {
-    pthread_t temp;
-    pthread_attr_t attr;
-    pthread_attr_init(&attr);
-    pthread_attr_setdetachstate(&attr, thread ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED);
-    auto* pthread_args = new adb_pthread_args{.func = start, .arg = arg};
-    errno = pthread_create(&temp, &attr, adb_pthread_wrapper, pthread_args);
-    if (errno == 0) {
-        if (thread) {
-            *thread = temp;
-        }
-        return true;
-    }
-    return false;
-}
-
-static __inline__ bool adb_thread_join(adb_thread_t thread) {
-    errno = pthread_join(thread, nullptr);
-    return errno == 0;
-}
-
-static __inline__ bool adb_thread_detach(adb_thread_t thread) {
-    errno = pthread_detach(thread);
-    return errno == 0;
-}
-
-static __inline__ void __attribute__((noreturn)) adb_thread_exit() {
-    pthread_exit(nullptr);
-}
-
 static __inline__ int adb_thread_setname(const std::string& name) {
 #ifdef __APPLE__
     return pthread_setname_np(name.c_str());
diff --git a/adb/sysdeps/network.h b/adb/sysdeps/network.h
new file mode 100644
index 0000000..83ce371
--- /dev/null
+++ b/adb/sysdeps/network.h
@@ -0,0 +1,22 @@
+#pragma once
+
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+
+int network_loopback_client(int port, int type, std::string* error);
+int network_loopback_server(int port, int type, std::string* error);
diff --git a/adb/sysdeps/posix/network.cpp b/adb/sysdeps/posix/network.cpp
new file mode 100644
index 0000000..45da5af
--- /dev/null
+++ b/adb/sysdeps/posix/network.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "sysdeps/network.h"
+
+#include <errno.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+#include <string>
+
+#include "adb_unique_fd.h"
+
+static void set_error(std::string* error) {
+    if (error) {
+        *error = strerror(errno);
+    }
+}
+
+static sockaddr* loopback_addr4(sockaddr_storage* addr, socklen_t* addrlen, int port) {
+    struct sockaddr_in* addr4 = reinterpret_cast<sockaddr_in*>(addr);
+    *addrlen = sizeof(*addr4);
+
+    addr4->sin_family = AF_INET;
+    addr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+    addr4->sin_port = htons(port);
+    return reinterpret_cast<sockaddr*>(addr);
+}
+
+static sockaddr* loopback_addr6(sockaddr_storage* addr, socklen_t* addrlen, int port) {
+    struct sockaddr_in6* addr6 = reinterpret_cast<sockaddr_in6*>(addr);
+    *addrlen = sizeof(*addr6);
+
+    addr6->sin6_family = AF_INET6;
+    addr6->sin6_addr = in6addr_loopback;
+    addr6->sin6_port = htons(port);
+    return reinterpret_cast<sockaddr*>(addr);
+}
+
+static int _network_loopback_client(bool ipv6, int port, int type, std::string* error) {
+    unique_fd s(socket(ipv6 ? AF_INET6 : AF_INET, type, 0));
+    if (s == -1) {
+        set_error(error);
+        return -1;
+    }
+
+    struct sockaddr_storage addr_storage = {};
+    socklen_t addrlen = sizeof(addr_storage);
+    sockaddr* addr = (ipv6 ? loopback_addr6 : loopback_addr4)(&addr_storage, &addrlen, 0);
+
+    if (bind(s.get(), addr, addrlen) != 0) {
+        set_error(error);
+        return -1;
+    }
+
+    addr = (ipv6 ? loopback_addr6 : loopback_addr4)(&addr_storage, &addrlen, port);
+
+    if (connect(s.get(), addr, addrlen) != 0) {
+        set_error(error);
+        return -1;
+    }
+
+    return s.release();
+}
+
+int network_loopback_client(int port, int type, std::string* error) {
+    // Try IPv4 first, use IPv6 as a fallback.
+    int rc = _network_loopback_client(false, port, type, error);
+    if (rc == -1) {
+        return _network_loopback_client(true, port, type, error);
+    }
+    return rc;
+}
+
+static int _network_loopback_server(bool ipv6, int port, int type, std::string* error) {
+    unique_fd s(socket(ipv6 ? AF_INET6 : AF_INET, type, 0));
+    if (s == -1) {
+        set_error(error);
+        return -1;
+    }
+
+    int n = 1;
+    setsockopt(s.get(), SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n));
+
+    struct sockaddr_storage addr_storage = {};
+    socklen_t addrlen = sizeof(addr_storage);
+    sockaddr* addr = (ipv6 ? loopback_addr6 : loopback_addr4)(&addr_storage, &addrlen, port);
+
+    if (bind(s, addr, addrlen) != 0) {
+        set_error(error);
+        return -1;
+    }
+
+    if (type == SOCK_STREAM || type == SOCK_SEQPACKET) {
+        // Arbitrarily selected value, ported from libcutils.
+        if (listen(s, 4) != 0) {
+            set_error(error);
+            return -1;
+        }
+    }
+
+    return s.release();
+}
+
+int network_loopback_server(int port, int type, std::string* error) {
+    int rc = _network_loopback_server(false, port, type, error);
+
+    // Only attempt to listen on IPv6 if IPv4 is unavailable.
+    // We don't want to start an IPv6 server if there's already an IPv4 one running.
+    if (rc == -1 && (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT)) {
+        return _network_loopback_server(true, port, type, error);
+    }
+    return rc;
+}
diff --git a/adb/sysdeps_test.cpp b/adb/sysdeps_test.cpp
index 9007e75..edb0fb3 100644
--- a/adb/sysdeps_test.cpp
+++ b/adb/sysdeps_test.cpp
@@ -25,54 +25,6 @@
 #include "sysdeps.h"
 #include "sysdeps/chrono.h"
 
-static void increment_atomic_int(void* c) {
-    std::this_thread::sleep_for(1s);
-    reinterpret_cast<std::atomic<int>*>(c)->fetch_add(1);
-}
-
-TEST(sysdeps_thread, smoke) {
-    std::atomic<int> counter(0);
-
-    for (int i = 0; i < 100; ++i) {
-        ASSERT_TRUE(adb_thread_create(increment_atomic_int, &counter));
-    }
-
-    std::this_thread::sleep_for(2s);
-    ASSERT_EQ(100, counter.load());
-}
-
-TEST(sysdeps_thread, join) {
-    std::atomic<int> counter(0);
-    std::vector<adb_thread_t> threads(500);
-    for (size_t i = 0; i < threads.size(); ++i) {
-        ASSERT_TRUE(adb_thread_create(increment_atomic_int, &counter, &threads[i]));
-    }
-
-    int current = counter.load();
-    ASSERT_GE(current, 0);
-    // Make sure that adb_thread_create actually creates threads, and doesn't do something silly
-    // like synchronously run the function passed in. The sleep in increment_atomic_int should be
-    // enough to keep this from being flakey.
-    ASSERT_LT(current, 500);
-
-    for (const auto& thread : threads) {
-        ASSERT_TRUE(adb_thread_join(thread));
-    }
-
-    ASSERT_EQ(500, counter.load());
-}
-
-TEST(sysdeps_thread, exit) {
-    adb_thread_t thread;
-    ASSERT_TRUE(adb_thread_create(
-        [](void*) {
-            adb_thread_exit();
-            for (;;) continue;
-        },
-        nullptr, &thread));
-    ASSERT_TRUE(adb_thread_join(thread));
-}
-
 TEST(sysdeps_socketpair, smoke) {
     int fds[2];
     ASSERT_EQ(0, adb_socketpair(fds)) << strerror(errno);
@@ -254,13 +206,13 @@
     static std::mutex &m = *new std::mutex();
     m.lock();
     ASSERT_FALSE(m.try_lock());
-    adb_thread_create([](void*) {
+    std::thread thread([]() {
         ASSERT_FALSE(m.try_lock());
         m.lock();
         finished.store(true);
         std::this_thread::sleep_for(200ms);
         m.unlock();
-    }, nullptr);
+    });
 
     ASSERT_FALSE(finished.load());
     std::this_thread::sleep_for(100ms);
@@ -270,6 +222,8 @@
     m.lock();
     ASSERT_TRUE(finished.load());
     m.unlock();
+
+    thread.join();
 }
 
 TEST(sysdeps_mutex, recursive_mutex_smoke) {
@@ -279,12 +233,12 @@
     ASSERT_TRUE(m.try_lock());
     m.unlock();
 
-    adb_thread_create([](void*) {
+    std::thread thread([]() {
         ASSERT_FALSE(m.try_lock());
         m.lock();
         std::this_thread::sleep_for(500ms);
         m.unlock();
-    }, nullptr);
+    });
 
     std::this_thread::sleep_for(100ms);
     m.unlock();
@@ -292,6 +246,8 @@
     ASSERT_FALSE(m.try_lock());
     m.lock();
     m.unlock();
+
+    thread.join();
 }
 
 TEST(sysdeps_condition_variable, smoke) {
@@ -300,14 +256,16 @@
     static volatile bool flag = false;
 
     std::unique_lock<std::mutex> lock(m);
-    adb_thread_create([](void*) {
+    std::thread thread([]() {
         m.lock();
         flag = true;
         cond.notify_one();
         m.unlock();
-    }, nullptr);
+    });
 
     while (!flag) {
         cond.wait(lock);
     }
+
+    thread.join();
 }
diff --git a/adb/transport.cpp b/adb/transport.cpp
index c951f5b..4686841 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -29,6 +29,7 @@
 #include <algorithm>
 #include <list>
 #include <mutex>
+#include <thread>
 
 #include <android-base/logging.h>
 #include <android-base/parsenetaddress.h>
@@ -509,13 +510,8 @@
 
         fdevent_set(&(t->transport_fde), FDE_READ);
 
-        if (!adb_thread_create(write_transport_thread, t)) {
-            fatal_errno("cannot create write_transport thread");
-        }
-
-        if (!adb_thread_create(read_transport_thread, t)) {
-            fatal_errno("cannot create read_transport thread");
-        }
+        std::thread(write_transport_thread, t).detach();
+        std::thread(read_transport_thread, t).detach();
     }
 
     {
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 4198a52..408f51f 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -199,7 +199,7 @@
 std::mutex &retry_ports_lock = *new std::mutex;
 std::condition_variable &retry_ports_cond = *new std::condition_variable;
 
-static void client_socket_thread(void* x) {
+static void client_socket_thread(int) {
     adb_thread_setname("client_socket_thread");
     D("transport: client_socket_thread() starting");
     PollAllLocalPortsForEmulator();
@@ -244,9 +244,8 @@
 
 #else // ADB_HOST
 
-static void server_socket_thread(void* arg) {
+static void server_socket_thread(int port) {
     int serverfd, fd;
-    int port = (int) (uintptr_t) arg;
 
     adb_thread_setname("server socket");
     D("transport: server_socket_thread() starting");
@@ -325,7 +324,7 @@
  *   the transport registration is completed. That's why we need to send the
  *   'start' request after the transport is registered.
  */
-static void qemu_socket_thread(void* arg) {
+static void qemu_socket_thread(int port) {
     /* 'accept' request to the adb QEMUD service. */
     static const char _accept_req[] = "accept";
     /* 'start' request to the adb QEMUD service. */
@@ -333,7 +332,6 @@
     /* 'ok' reply from the adb QEMUD service. */
     static const char _ok_resp[] = "ok";
 
-    const int port = (int) (uintptr_t) arg;
     int fd;
     char tmp[256];
     char con_name[32];
@@ -350,7 +348,7 @@
         /* This could be an older version of the emulator, that doesn't
          * implement adb QEMUD service. Fall back to the old TCP way. */
         D("adb service is not available. Falling back to TCP socket.");
-        adb_thread_create(server_socket_thread, arg);
+        std::thread(server_socket_thread, port).detach();
         return;
     }
 
@@ -394,7 +392,7 @@
 
 void local_init(int port)
 {
-    adb_thread_func_t func;
+    void (*func)(int);
     const char* debug_name = "";
 
 #if ADB_HOST
@@ -414,9 +412,7 @@
 #endif // !ADB_HOST
 
     D("transport: local %s init", debug_name);
-    if (!adb_thread_create(func, (void *) (uintptr_t) port)) {
-        fatal_errno("cannot create local socket %s thread", debug_name);
-    }
+    std::thread(func, port).detach();
 }
 
 static void remote_kick(atransport *t)
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 78d0c07..ea9cb37 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -31,7 +31,10 @@
 #include <time.h>
 #include <unistd.h>
 
+#include <memory>
+
 #include <android-base/file.h>
+#include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/unique_fd.h>
 #include <cutils/android_reboot.h>
@@ -47,8 +50,10 @@
 #include <logwrap/logwrap.h>
 #include <private/android_logger.h>  // for __android_log_is_debuggable()
 
+#include "fs_mgr.h"
+#include "fs_mgr_avb.h"
 #include "fs_mgr_priv.h"
-#include "fs_mgr_priv_avb.h"
+#include "fs_mgr_priv_dm_ioctl.h"
 
 #define KEY_LOC_PROP   "ro.crypto.keyfile.userdata"
 #define KEY_IN_FOOTER  "footer"
@@ -819,7 +824,7 @@
                     return -1;
                 }
             }
-            if (!avb_handle->SetUpAvb(&fstab->recs[i])) {
+            if (!avb_handle->SetUpAvb(&fstab->recs[i], true /* wait_for_verity_dev */)) {
                 LERROR << "Failed to set up AVB on partition: "
                        << fstab->recs[i].mount_point << ", skipping!";
                 /* Skips mounting the device. */
@@ -1031,7 +1036,7 @@
                     return -1;
                 }
             }
-            if (!avb_handle->SetUpAvb(&fstab->recs[i])) {
+            if (!avb_handle->SetUpAvb(&fstab->recs[i], true /* wait_for_verity_dev */)) {
                 LERROR << "Failed to set up AVB on partition: "
                        << fstab->recs[i].mount_point << ", skipping!";
                 /* Skips mounting the device. */
@@ -1257,3 +1262,97 @@
 
     return 0;
 }
+
+bool fs_mgr_load_verity_state(int* mode) {
+    /* return the default mode, unless any of the verified partitions are in
+     * logging mode, in which case return that */
+    *mode = VERITY_MODE_DEFAULT;
+
+    std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
+                                                               fs_mgr_free_fstab);
+    if (!fstab) {
+        LERROR << "Failed to read default fstab";
+        return false;
+    }
+
+    for (int i = 0; i < fstab->num_entries; i++) {
+        if (fs_mgr_is_avb(&fstab->recs[i])) {
+            *mode = VERITY_MODE_RESTART;  // avb only supports restart mode.
+            break;
+        } else if (!fs_mgr_is_verified(&fstab->recs[i])) {
+            continue;
+        }
+
+        int current;
+        if (load_verity_state(&fstab->recs[i], &current) < 0) {
+            continue;
+        }
+        if (current != VERITY_MODE_DEFAULT) {
+            *mode = current;
+            break;
+        }
+    }
+
+    return true;
+}
+
+bool fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback) {
+    if (!callback) {
+        return false;
+    }
+
+    int mode;
+    if (!fs_mgr_load_verity_state(&mode)) {
+        return false;
+    }
+
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC)));
+    if (fd == -1) {
+        PERROR << "Error opening device mapper";
+        return false;
+    }
+
+    std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
+                                                               fs_mgr_free_fstab);
+    if (!fstab) {
+        LERROR << "Failed to read default fstab";
+        return false;
+    }
+
+    alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
+    struct dm_ioctl* io = (struct dm_ioctl*)buffer;
+    bool system_root = android::base::GetProperty("ro.build.system_root_image", "") == "true";
+
+    for (int i = 0; i < fstab->num_entries; i++) {
+        if (!fs_mgr_is_verified(&fstab->recs[i]) && !fs_mgr_is_avb(&fstab->recs[i])) {
+            continue;
+        }
+
+        std::string mount_point;
+        if (system_root && !strcmp(fstab->recs[i].mount_point, "/")) {
+            mount_point = "system";
+        } else {
+            mount_point = basename(fstab->recs[i].mount_point);
+        }
+
+        fs_mgr_verity_ioctl_init(io, mount_point, 0);
+
+        const char* status;
+        if (ioctl(fd, DM_TABLE_STATUS, io)) {
+            if (fstab->recs[i].fs_mgr_flags & MF_VERIFYATBOOT) {
+                status = "V";
+            } else {
+                PERROR << "Failed to query DM_TABLE_STATUS for " << mount_point.c_str();
+                continue;
+            }
+        }
+
+        status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
+
+        if (*status == 'C' || *status == 'V') {
+            callback(&fstab->recs[i], mount_point.c_str(), mode, *status);
+        }
+    }
+
+    return true;
+}
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp
index 76ec236..7c82bb1 100644
--- a/fs_mgr/fs_mgr_avb.cpp
+++ b/fs_mgr/fs_mgr_avb.cpp
@@ -38,9 +38,9 @@
 #include <utils/Compat.h>
 
 #include "fs_mgr.h"
+#include "fs_mgr_avb.h"
 #include "fs_mgr_avb_ops.h"
 #include "fs_mgr_priv.h"
-#include "fs_mgr_priv_avb.h"
 #include "fs_mgr_priv_dm_ioctl.h"
 #include "fs_mgr_priv_sha.h"
 
@@ -336,7 +336,8 @@
 
 static bool hashtree_dm_verity_setup(struct fstab_rec* fstab_entry,
                                      const AvbHashtreeDescriptor& hashtree_desc,
-                                     const std::string& salt, const std::string& root_digest) {
+                                     const std::string& salt, const std::string& root_digest,
+                                     bool wait_for_verity_dev) {
     // Gets the device mapper fd.
     android::base::unique_fd fd(open("/dev/device-mapper", O_RDWR));
     if (fd < 0) {
@@ -375,13 +376,12 @@
     // Marks the underlying block device as read-only.
     fs_mgr_set_blk_ro(fstab_entry->blk_device);
 
-    // TODO(bowgotsai): support verified all partition at boot.
     // Updates fstab_rec->blk_device to verity device name.
     free(fstab_entry->blk_device);
     fstab_entry->blk_device = strdup(verity_blk_name.c_str());
 
     // Makes sure we've set everything up properly.
-    if (fs_mgr_test_access(verity_blk_name.c_str()) < 0) {
+    if (wait_for_verity_dev && fs_mgr_test_access(verity_blk_name.c_str()) < 0) {
         return false;
     }
 
@@ -519,7 +519,7 @@
     return nullptr;
 }
 
-bool FsManagerAvbHandle::SetUpAvb(struct fstab_rec* fstab_entry) {
+bool FsManagerAvbHandle::SetUpAvb(struct fstab_rec* fstab_entry, bool wait_for_verity_dev) {
     if (!fstab_entry) return false;
     if (!avb_slot_data_ || avb_slot_data_->num_vbmeta_images < 1) {
         return false;
@@ -545,7 +545,8 @@
     }
 
     // Converts HASHTREE descriptor to verity_table_params.
-    if (!hashtree_dm_verity_setup(fstab_entry, hashtree_descriptor, salt, root_digest)) {
+    if (!hashtree_dm_verity_setup(fstab_entry, hashtree_descriptor, salt, root_digest,
+                                  wait_for_verity_dev)) {
         return false;
     }
     return true;
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index dfbde18..dc73c24 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -768,6 +768,11 @@
     return fstab->fs_mgr_flags & MF_VERIFY;
 }
 
+int fs_mgr_is_avb(const struct fstab_rec *fstab)
+{
+    return fstab->fs_mgr_flags & MF_AVB;
+}
+
 int fs_mgr_is_verifyatboot(const struct fstab_rec *fstab)
 {
     return fstab->fs_mgr_flags & MF_VERIFYATBOOT;
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index dedffd8..c985462 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -115,5 +115,6 @@
 bool fs_mgr_update_for_slotselect(struct fstab *fstab);
 bool is_dt_compatible();
 bool is_device_secure();
+int load_verity_state(struct fstab_rec* fstab, int* mode);
 
 #endif /* __CORE_FS_MGR_PRIV_H */
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 8c7a8ca..0bf173b 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -653,8 +653,7 @@
                 offset);
 }
 
-static int load_verity_state(struct fstab_rec *fstab, int *mode)
-{
+int load_verity_state(struct fstab_rec* fstab, int* mode) {
     int match = 0;
     off64_t offset = 0;
 
@@ -690,129 +689,6 @@
     return read_verity_state(fstab->verity_loc, offset, mode);
 }
 
-int fs_mgr_load_verity_state(int *mode)
-{
-    int rc = -1;
-    int i;
-    int current;
-    struct fstab *fstab = NULL;
-
-    /* return the default mode, unless any of the verified partitions are in
-     * logging mode, in which case return that */
-    *mode = VERITY_MODE_DEFAULT;
-
-    fstab = fs_mgr_read_fstab_default();
-    if (!fstab) {
-        LERROR << "Failed to read default fstab";
-        goto out;
-    }
-
-    for (i = 0; i < fstab->num_entries; i++) {
-        if (!fs_mgr_is_verified(&fstab->recs[i])) {
-            continue;
-        }
-
-        rc = load_verity_state(&fstab->recs[i], &current);
-        if (rc < 0) {
-            continue;
-        }
-
-        if (current != VERITY_MODE_DEFAULT) {
-            *mode = current;
-            break;
-        }
-    }
-
-    rc = 0;
-
-out:
-    if (fstab) {
-        fs_mgr_free_fstab(fstab);
-    }
-
-    return rc;
-}
-
-int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback)
-{
-    alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
-    bool system_root = false;
-    std::string mount_point;
-    char propbuf[PROPERTY_VALUE_MAX];
-    const char *status;
-    int fd = -1;
-    int i;
-    int mode;
-    int rc = -1;
-    struct dm_ioctl *io = (struct dm_ioctl *) buffer;
-    struct fstab *fstab = NULL;
-
-    if (!callback) {
-        return -1;
-    }
-
-    if (fs_mgr_load_verity_state(&mode) == -1) {
-        return -1;
-    }
-
-    fd = TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC));
-    if (fd == -1) {
-        PERROR << "Error opening device mapper";
-        goto out;
-    }
-
-    property_get("ro.build.system_root_image", propbuf, "");
-    system_root = !strcmp(propbuf, "true");
-    fstab = fs_mgr_read_fstab_default();
-    if (!fstab) {
-        LERROR << "Failed to read default fstab";
-        goto out;
-    }
-
-    for (i = 0; i < fstab->num_entries; i++) {
-        if (!fs_mgr_is_verified(&fstab->recs[i])) {
-            continue;
-        }
-
-        if (system_root && !strcmp(fstab->recs[i].mount_point, "/")) {
-            mount_point = "system";
-        } else {
-            mount_point = basename(fstab->recs[i].mount_point);
-        }
-
-        fs_mgr_verity_ioctl_init(io, mount_point, 0);
-
-        if (ioctl(fd, DM_TABLE_STATUS, io)) {
-            if (fstab->recs[i].fs_mgr_flags & MF_VERIFYATBOOT) {
-                status = "V";
-            } else {
-                PERROR << "Failed to query DM_TABLE_STATUS for "
-                       << mount_point.c_str();
-                continue;
-            }
-        }
-
-        status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
-
-        if (*status == 'C' || *status == 'V') {
-            callback(&fstab->recs[i], mount_point.c_str(), mode, *status);
-        }
-    }
-
-    rc = 0;
-
-out:
-    if (fstab) {
-        fs_mgr_free_fstab(fstab);
-    }
-
-    if (fd) {
-        close(fd);
-    }
-
-    return rc;
-}
-
 static void update_verity_table_blk_device(char *blk_device, char **table)
 {
     std::string result, word;
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 3c2fea4..12db672 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -113,8 +113,8 @@
 int fs_mgr_unmount_all(struct fstab *fstab);
 int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc,
                           char *real_blk_device, int size);
-int fs_mgr_load_verity_state(int *mode);
-int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback);
+bool fs_mgr_load_verity_state(int* mode);
+bool fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback);
 int fs_mgr_add_entry(struct fstab *fstab,
                      const char *mount_point, const char *fs_type,
                      const char *blk_device);
@@ -123,6 +123,7 @@
 int fs_mgr_is_nonremovable(const struct fstab_rec *fstab);
 int fs_mgr_is_verified(const struct fstab_rec *fstab);
 int fs_mgr_is_verifyatboot(const struct fstab_rec *fstab);
+int fs_mgr_is_avb(const struct fstab_rec *fstab);
 int fs_mgr_is_encryptable(const struct fstab_rec *fstab);
 int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab);
 const char* fs_mgr_get_file_encryption_mode(const struct fstab_rec *fstab);
diff --git a/fs_mgr/fs_mgr_priv_avb.h b/fs_mgr/include/fs_mgr_avb.h
similarity index 83%
rename from fs_mgr/fs_mgr_priv_avb.h
rename to fs_mgr/include/fs_mgr_avb.h
index 99a033e..526a5ce 100644
--- a/fs_mgr/fs_mgr_priv_avb.h
+++ b/fs_mgr/include/fs_mgr_avb.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef __CORE_FS_MGR_PRIV_AVB_H
-#define __CORE_FS_MGR_PRIV_AVB_H
+#ifndef __CORE_FS_MGR_AVB_H
+#define __CORE_FS_MGR_AVB_H
 
 #include <memory>
 #include <string>
@@ -63,18 +63,22 @@
     static FsManagerAvbUniquePtr Open(const std::string& device_file_by_name_prefix);
 
     // Sets up dm-verity on the given fstab entry.
+    // The 'wait_for_verity_dev' parameter makes this function wait for the
+    // verity device to get created before return.
     // Returns true if the mount point is eligible to mount, it includes:
     //   - status_ is kFsMgrAvbHandleHashtreeDisabled or
     //   - status_ is kFsMgrAvbHandleSuccess and sending ioctl DM_TABLE_LOAD
     //     to load verity table is success.
     // Otherwise, returns false.
-    bool SetUpAvb(fstab_rec* fstab_entry);
+    bool SetUpAvb(fstab_rec* fstab_entry, bool wait_for_verity_dev);
 
-    FsManagerAvbHandle(const FsManagerAvbHandle&) = delete; // no copy
-    FsManagerAvbHandle& operator=(const FsManagerAvbHandle&) = delete; // no assignment
+    bool AvbHashtreeDisabled() { return status_ == kFsManagerAvbHandleHashtreeDisabled; }
 
-    FsManagerAvbHandle(FsManagerAvbHandle&&) noexcept = delete;  // no move
-    FsManagerAvbHandle& operator=(FsManagerAvbHandle&&) noexcept = delete; // no move assignment
+    FsManagerAvbHandle(const FsManagerAvbHandle&) = delete;             // no copy
+    FsManagerAvbHandle& operator=(const FsManagerAvbHandle&) = delete;  // no assignment
+
+    FsManagerAvbHandle(FsManagerAvbHandle&&) noexcept = delete;             // no move
+    FsManagerAvbHandle& operator=(FsManagerAvbHandle&&) noexcept = delete;  // no move assignment
 
     ~FsManagerAvbHandle() {
         if (avb_slot_data_) {
@@ -90,4 +94,4 @@
     FsManagerAvbHandleStatus status_;
 };
 
-#endif /* __CORE_FS_MGR_PRIV_AVB_H */
+#endif /* __CORE_FS_MGR_AVB_H */
diff --git a/init/Android.mk b/init/Android.mk
index 7e9b613..c9bf9fc 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -111,8 +111,8 @@
     libfec_rs \
     libsquashfs_utils \
     liblogwrap \
-    libcutils \
     libext4_utils \
+    libcutils \
     libbase \
     libc \
     libselinux \
diff --git a/init/builtins.cpp b/init/builtins.cpp
index e1d9b94..2327cdf 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -677,11 +677,11 @@
 
 static int do_verity_load_state(const std::vector<std::string>& args) {
     int mode = -1;
-    int rc = fs_mgr_load_verity_state(&mode);
-    if (rc == 0 && mode != VERITY_MODE_DEFAULT) {
+    bool loaded = fs_mgr_load_verity_state(&mode);
+    if (loaded && mode != VERITY_MODE_DEFAULT) {
         ActionManager::GetInstance().QueueEventTrigger("verity-logging");
     }
-    return rc;
+    return loaded ? 0 : 1;
 }
 
 static void verity_update_property(fstab_rec *fstab, const char *mount_point,
@@ -691,7 +691,7 @@
 }
 
 static int do_verity_update_state(const std::vector<std::string>& args) {
-    return fs_mgr_update_verity_state(verity_update_property);
+    return fs_mgr_update_verity_state(verity_update_property) ? 0 : 1;
 }
 
 static int do_write(const std::vector<std::string>& args) {
diff --git a/init/init.cpp b/init/init.cpp
index 543f38e..6c09c99 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -61,6 +61,7 @@
 #include "bootchart.h"
 #include "devices.h"
 #include "fs_mgr.h"
+#include "fs_mgr_avb.h"
 #include "import_parser.h"
 #include "init_parser.h"
 #include "keychords.h"
@@ -482,42 +483,73 @@
     }
 }
 
-static constexpr char android_dt_dir[] = "/proc/device-tree/firmware/android";
-
-static bool is_dt_compatible() {
-    std::string dt_value;
-    std::string file_name = StringPrintf("%s/compatible", android_dt_dir);
-
-    if (android::base::ReadFileToString(file_name, &dt_value)) {
-        // trim the trailing '\0' out, otherwise the comparison
-        // will produce false-negatives.
-        dt_value.resize(dt_value.size() - 1);
-        if (dt_value == "android,firmware") {
+/* Reads the content of device tree file into dt_value.
+ * Returns true if the read is success, false otherwise.
+ */
+static bool read_dt_file(const std::string& file_name, std::string* dt_value) {
+    if (android::base::ReadFileToString(file_name, dt_value)) {
+        if (!dt_value->empty()) {
+            dt_value->pop_back();  // Trim the trailing '\0' out.
             return true;
         }
     }
-
     return false;
 }
 
-static bool is_dt_fstab_compatible() {
-    std::string dt_value;
-    std::string file_name = StringPrintf("%s/%s/compatible", android_dt_dir, "fstab");
+static const std::string kAndroidDtDir("/proc/device-tree/firmware/android/");
 
-    if (android::base::ReadFileToString(file_name, &dt_value)) {
-        dt_value.resize(dt_value.size() - 1);
-        if (dt_value == "android,fstab") {
+static bool is_dt_value_expected(const std::string& dt_file_suffix,
+                                 const std::string& expected_value) {
+    std::string dt_value;
+    std::string file_name = kAndroidDtDir + dt_file_suffix;
+
+    if (read_dt_file(file_name, &dt_value)) {
+        if (dt_value == expected_value) {
             return true;
         }
     }
-
     return false;
 }
 
+static inline bool is_dt_compatible() {
+    return is_dt_value_expected("compatible", "android,firmware");
+}
+
+static inline bool is_dt_fstab_compatible() {
+    return is_dt_value_expected("fstab/compatible", "android,fstab");
+}
+
+static inline bool is_dt_vbmeta_compatible() {
+    return is_dt_value_expected("vbmeta/compatible", "android,vbmeta");
+}
+
+// Gets the vbmeta config from device tree. Specifically, the 'parts' and 'by_name_prefix'.
+// /{
+//     firmware {
+//         android {
+//             vbmeta {
+//                 compatible = "android,vbmeta";
+//                 parts = "vbmeta,boot,system,vendor"
+//                 by_name_prefix="/dev/block/platform/soc.0/f9824900.sdhci/by-name/"
+//             };
+//         };
+//     };
+//  }
+static bool get_vbmeta_config_from_dt(std::string* vbmeta_partitions,
+                                      std::string* device_file_by_name_prefix) {
+    std::string file_name = kAndroidDtDir + "vbmeta/parts";
+    if (!read_dt_file(file_name, vbmeta_partitions)) return false;
+
+    file_name = kAndroidDtDir + "vbmeta/by_name_prefix";
+    if (!read_dt_file(file_name, device_file_by_name_prefix)) return false;
+
+    return true;
+}
+
 static void process_kernel_dt() {
     if (!is_dt_compatible()) return;
 
-    std::unique_ptr<DIR, int(*)(DIR*)>dir(opendir(android_dt_dir), closedir);
+    std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(kAndroidDtDir.c_str()), closedir);
     if (!dir) return;
 
     std::string dt_file;
@@ -527,7 +559,7 @@
             continue;
         }
 
-        std::string file_name = StringPrintf("%s/%s", android_dt_dir, dp->d_name);
+        std::string file_name = kAndroidDtDir + dp->d_name;
 
         android::base::ReadFileToString(file_name, &dt_file);
         std::replace(dt_file.begin(), dt_file.end(), ',', '.');
@@ -920,38 +952,100 @@
     }
 }
 
-static bool early_mount_one(struct fstab_rec* rec) {
-    if (rec && fs_mgr_is_verified(rec)) {
-        // setup verity and create the dm-XX block device
-        // needed to mount this partition
-        int ret = fs_mgr_setup_verity(rec, false);
-        if (ret == FS_MGR_SETUP_VERITY_FAIL) {
-            PLOG(ERROR) << "early_mount: Failed to setup verity for '" << rec->mount_point << "'";
+// Creates "/dev/block/dm-XX" for dm-verity by running coldboot on /sys/block/dm-XX.
+static void device_init_dm_device(const std::string& dm_device) {
+    const std::string device_name(basename(dm_device.c_str()));
+    const std::string syspath = "/sys/block/" + device_name;
+
+    device_init(syspath.c_str(), [&](uevent* uevent) -> coldboot_action_t {
+        if (uevent->device_name && device_name == uevent->device_name) {
+            LOG(VERBOSE) << "early_mount: creating dm-verity device : " << dm_device;
+            return COLDBOOT_STOP;
+        }
+        return COLDBOOT_CONTINUE;
+    });
+    device_close();
+}
+
+static bool vboot_1_0_mount_partitions(const std::vector<fstab_rec*>& fstab_recs) {
+    if (fstab_recs.empty()) return false;
+
+    for (auto rec : fstab_recs) {
+        bool need_create_dm_device = false;
+        if (fs_mgr_is_verified(rec)) {
+            // setup verity and create the dm-XX block device
+            // needed to mount this partition
+            int ret = fs_mgr_setup_verity(rec, false /* wait_for_verity_dev */);
+            if (ret == FS_MGR_SETUP_VERITY_DISABLED) {
+                LOG(INFO) << "verity disabled for '" << rec->mount_point << "'";
+            } else if (ret == FS_MGR_SETUP_VERITY_SUCCESS) {
+                need_create_dm_device = true;
+            } else {
+                PLOG(ERROR) << "early_mount: failed to setup verity for '" << rec->mount_point
+                            << "'";
+                return false;
+            }
+        }
+        if (need_create_dm_device) {
+            // The exact block device name (rec->blk_device) is changed to "/dev/block/dm-XX".
+            // Need to create it because ueventd isn't started during early mount.
+            device_init_dm_device(rec->blk_device);
+        }
+        if (fs_mgr_do_mount_one(rec)) {
+            PLOG(ERROR) << "early_mount: failed to mount '" << rec->mount_point << "'";
             return false;
         }
-
-        // The exact block device name is added as a mount source by
-        // fs_mgr_setup_verity() in ->blk_device as "/dev/block/dm-XX"
-        // We create that device by running coldboot on /sys/block/dm-XX
-        std::string dm_device(basename(rec->blk_device));
-        std::string syspath = StringPrintf("/sys/block/%s", dm_device.c_str());
-        device_init(syspath.c_str(), [&](uevent* uevent) -> coldboot_action_t {
-            if (uevent->device_name && !strcmp(dm_device.c_str(), uevent->device_name)) {
-                LOG(VERBOSE) << "early_mount: creating dm-verity device : " << dm_device;
-                return COLDBOOT_STOP;
-            }
-            return COLDBOOT_CONTINUE;
-        });
-    }
-
-    if (rec && fs_mgr_do_mount_one(rec)) {
-        PLOG(ERROR) << "early_mount: Failed to mount '" << rec->mount_point << "'";
-        return false;
     }
 
     return true;
 }
 
+static bool vboot_2_0_mount_partitions(const std::vector<fstab_rec*>& fstab_recs,
+                                       const std::string& device_file_by_name_prefix) {
+    if (fstab_recs.empty()) return false;
+
+    FsManagerAvbUniquePtr avb_handle = FsManagerAvbHandle::Open(device_file_by_name_prefix);
+    if (!avb_handle) {
+        LOG(INFO) << "Failed to Open FsManagerAvbHandle";
+        return false;
+    }
+
+    for (auto rec : fstab_recs) {
+        bool need_create_dm_device = false;
+        if (fs_mgr_is_avb(rec)) {
+            if (avb_handle->AvbHashtreeDisabled()) {
+                LOG(INFO) << "avb hashtree disabled for '" << rec->mount_point << "'";
+            } else if (avb_handle->SetUpAvb(rec, false /* wait_for_verity_dev */)) {
+                need_create_dm_device = true;
+            } else {
+                PLOG(ERROR) << "early_mount: failed to set up AVB on partition: '"
+                            << rec->mount_point << "'";
+                return false;
+            }
+        }
+        if (need_create_dm_device) {
+            // The exact block device name (rec->blk_device) is changed to "/dev/block/dm-XX".
+            // Need to create it because ueventd isn't started during early mount.
+            device_init_dm_device(rec->blk_device);
+        }
+        if (fs_mgr_do_mount_one(rec)) {
+            PLOG(ERROR) << "early_mount: failed to mount '" << rec->mount_point << "'";
+            return false;
+        }
+    }
+
+    return true;
+}
+
+static bool mount_early_partitions(const std::vector<fstab_rec*>& fstab_recs,
+                                   const std::string& device_file_by_name_prefix) {
+    if (is_dt_vbmeta_compatible()) {  // AVB (external/avb) is used to setup dm-verity.
+        return vboot_2_0_mount_partitions(fstab_recs, device_file_by_name_prefix);
+    } else {
+        return vboot_1_0_mount_partitions(fstab_recs);
+    }
+}
+
 // Creates devices with uevent->partition_name matching one in the in/out
 // partition_names. Note that the partition_names MUST have A/B suffix
 // when A/B is used. Found partitions will then be removed from the
@@ -994,12 +1088,10 @@
     });
 }
 
-static bool get_early_partitions(const std::vector<fstab_rec*>& early_fstab_recs,
-                                 std::set<std::string>* out_partitions, bool* out_need_verity) {
+static bool vboot_1_0_early_partitions(const std::vector<fstab_rec*>& early_fstab_recs,
+                                       std::set<std::string>* out_partitions,
+                                       bool* out_need_verity) {
     std::string meta_partition;
-    out_partitions->clear();
-    *out_need_verity = false;
-
     for (auto fstab_rec : early_fstab_recs) {
         // don't allow verifyatboot for early mounted partitions
         if (fs_mgr_is_verifyatboot(fstab_rec)) {
@@ -1038,6 +1130,40 @@
     return true;
 }
 
+// a.k.a. AVB (external/avb)
+static bool vboot_2_0_early_partitions(std::set<std::string>* out_partitions, bool* out_need_verity,
+                                       std::string* out_device_file_by_name_prefix) {
+    std::string vbmeta_partitions;
+    if (!get_vbmeta_config_from_dt(&vbmeta_partitions, out_device_file_by_name_prefix)) {
+        return false;
+    }
+    // libavb verifies AVB metadata on all verified partitions at once.
+    // e.g., The vbmeta_partitions will be "vbmeta,boot,system,vendor"
+    // for libavb to verify metadata, even if we only need to early mount /vendor.
+    std::vector<std::string> partitions = android::base::Split(vbmeta_partitions, ",");
+    std::string ab_suffix = fs_mgr_get_slot_suffix();
+    for (const auto& partition : partitions) {
+        out_partitions->emplace(partition + ab_suffix);
+    }
+    *out_need_verity = true;
+    return true;
+}
+
+static bool get_early_partitions(const std::vector<fstab_rec*>& early_fstab_recs,
+                                 std::set<std::string>* out_partitions, bool* out_need_verity,
+                                 std::string* out_device_file_by_name_prefix) {
+    *out_need_verity = false;
+    out_partitions->clear();
+    out_device_file_by_name_prefix->clear();
+
+    if (is_dt_vbmeta_compatible()) {  // AVB (external/avb) is used to setup dm-verity.
+        return vboot_2_0_early_partitions(out_partitions, out_need_verity,
+                                          out_device_file_by_name_prefix);
+    } else {
+        return vboot_1_0_early_partitions(early_fstab_recs, out_partitions, out_need_verity);
+    }
+}
+
 /* Early mount vendor and ODM partitions. The fstab is read from device-tree. */
 static bool early_mount() {
     // skip early mount if we're in recovery mode
@@ -1072,9 +1198,11 @@
     if (early_fstab_recs.empty()) return true;
 
     bool need_verity;
+    std::string device_file_by_name_prefix;
     std::set<std::string> partition_names;
     // partition_names MUST have A/B suffix when A/B is used
-    if (!get_early_partitions(early_fstab_recs, &partition_names, &need_verity)) {
+    if (!get_early_partitions(early_fstab_recs, &partition_names, &need_verity,
+                              &device_file_by_name_prefix)) {
         return false;
     }
 
@@ -1097,10 +1225,9 @@
                     [&](uevent* uevent) -> coldboot_action_t { return COLDBOOT_STOP; });
     }
 
-    for (auto fstab_rec : early_fstab_recs) {
-        if (!early_mount_one(fstab_rec)) goto done;
+    if (mount_early_partitions(early_fstab_recs, device_file_by_name_prefix)) {
+        success = true;
     }
-    success = true;
 
 done:
     device_close();
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 8de3c78..d9ebd91 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -46,6 +46,7 @@
 #include <cutils/android_reboot.h>
 #include <fs_mgr.h>
 #include <logwrap/logwrap.h>
+#include <private/android_filesystem_config.h>
 
 #include "property_service.h"
 #include "service.h"
@@ -305,7 +306,8 @@
     Timer t;
     LOG(INFO) << "Reboot start, reason: " << reason << ", rebootTarget: " << rebootTarget;
 
-    android::base::WriteStringToFile(StringPrintf("%s\n", reason.c_str()), LAST_REBOOT_REASON_FILE);
+    android::base::WriteStringToFile(StringPrintf("%s\n", reason.c_str()), LAST_REBOOT_REASON_FILE,
+                                     S_IRUSR | S_IWUSR, AID_SYSTEM, AID_SYSTEM);
 
     if (cmd == ANDROID_RB_THERMOFF) {  // do not wait if it is thermal
         DoThermalOff();
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index f668f18..bb82f4d 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -24,7 +24,6 @@
     "socket_inaddr_any_server_unix.c",
     "socket_local_client_unix.c",
     "socket_local_server_unix.c",
-    "socket_loopback_server_unix.c",
     "socket_network_client_unix.c",
     "sockets_unix.cpp",
     "str_parms.c",
diff --git a/libcutils/include/cutils/sockets.h b/libcutils/include/cutils/sockets.h
index d724dd6..b24468b 100644
--- a/libcutils/include/cutils/sockets.h
+++ b/libcutils/include/cutils/sockets.h
@@ -88,8 +88,6 @@
 cutils_socket_t socket_network_client(const char* host, int port, int type);
 int socket_network_client_timeout(const char* host, int port, int type,
                                   int timeout, int* getaddrinfo_error);
-int socket_loopback_server(int port, int type);
-int socket_loopback_server6(int port, int type);
 int socket_local_server(const char* name, int namespaceId, int type);
 int socket_local_server_bind(int s, const char* name, int namespaceId);
 int socket_local_client_connect(int fd, const char *name, int namespaceId,
diff --git a/libcutils/socket_loopback_server_unix.c b/libcutils/socket_loopback_server_unix.c
deleted file mode 100644
index 7b92fd6..0000000
--- a/libcutils/socket_loopback_server_unix.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-** Copyright 2006, 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 <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#define LISTEN_BACKLOG 4
-
-#if !defined(_WIN32)
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#endif
-
-#include <cutils/sockets.h>
-
-static int _socket_loopback_server(int family, int type, struct sockaddr * addr, size_t size)
-{
-    int s, n;
-
-    s = socket(family, type, 0);
-    if(s < 0)
-        return -1;
-
-    n = 1;
-    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &n, sizeof(n));
-
-    if(bind(s, addr, size) < 0) {
-        close(s);
-        return -1;
-    }
-
-    if (type == SOCK_STREAM) {
-        int ret;
-
-        ret = listen(s, LISTEN_BACKLOG);
-
-        if (ret < 0) {
-            close(s);
-            return -1;
-        }
-    }
-
-    return s;
-}
-
-/* open listen() port on loopback IPv6 interface */
-int socket_loopback_server6(int port, int type)
-{
-    struct sockaddr_in6 addr;
-
-    memset(&addr, 0, sizeof(addr));
-    addr.sin6_family = AF_INET6;
-    addr.sin6_port = htons(port);
-    addr.sin6_addr = in6addr_loopback;
-
-    return _socket_loopback_server(AF_INET6, type, (struct sockaddr *) &addr, sizeof(addr));
-}
-
-/* open listen() port on loopback interface */
-int socket_loopback_server(int port, int type)
-{
-    struct sockaddr_in addr;
-
-    memset(&addr, 0, sizeof(addr));
-    addr.sin_family = AF_INET;
-    addr.sin_port = htons(port);
-    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
-    return _socket_loopback_server(AF_INET, type, (struct sockaddr *) &addr, sizeof(addr));
-}
diff --git a/liblog/include/log/log_event_list.h b/liblog/include/log/log_event_list.h
index 55953fc..057be5d 100644
--- a/liblog/include/log/log_event_list.h
+++ b/liblog/include/log/log_event_list.h
@@ -17,6 +17,7 @@
 #ifndef _LIBS_LOG_EVENT_LIST_H
 #define _LIBS_LOG_EVENT_LIST_H
 
+#include <errno.h>
 #include <stdint.h>
 
 #if (defined(__cplusplus) && defined(_USING_LIBCXX))
@@ -148,6 +149,7 @@
     return ctx;
   }
 
+  /* return errors or transmit status */
   int status() const {
     return ret;
   }
@@ -209,14 +211,16 @@
   }
 
   int write(log_id_t id = LOG_ID_EVENTS) {
+    /* facilitate -EBUSY retry */
+    if ((ret == -EBUSY) || (ret > 0)) ret = 0;
     int retval = android_log_write_list(ctx, id);
-    if (retval < 0) ret = retval;
+    /* existing errors trump transmission errors */
+    if (!ret) ret = retval;
     return ret;
   }
 
   int operator<<(log_id_t id) {
-    int retval = android_log_write_list(ctx, id);
-    if (retval < 0) ret = retval;
+    write(id);
     android_log_destroy(&ctx);
     return ret;
   }
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 17dade4..a43b0e1 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -406,7 +406,7 @@
     mkdir /data/misc/boottrace 0771 system shell
     mkdir /data/misc/update_engine 0700 root root
     mkdir /data/misc/trace 0700 root root
-    mkdir /data/misc/reboot 0700 root root
+    mkdir /data/misc/reboot 0700 system system
     # profile file layout
     mkdir /data/misc/profiles 0771 system system
     mkdir /data/misc/profiles/cur 0771 system system