Merge "Refine the exported DSU status"
diff --git a/adb/Android.bp b/adb/Android.bp
index fea8c78..a26017f 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -375,6 +375,7 @@
     srcs: libadb_srcs + libadb_linux_srcs + libadb_posix_srcs + [
         "daemon/auth.cpp",
         "daemon/jdwp_service.cpp",
+        "daemon/logging.cpp",
         "daemon/adb_wifi.cpp",
     ],
 
@@ -418,6 +419,12 @@
             srcs: [
                 "daemon/usb_dummy.cpp",
             ]
+        },
+        recovery: {
+            exclude_shared_libs: [
+                "libadb_pairing_auth",
+                "libadb_pairing_connection",
+            ],
         }
     },
 }
@@ -477,6 +484,10 @@
             exclude_srcs: [
                 "daemon/abb_service.cpp",
             ],
+            exclude_shared_libs: [
+                "libadb_pairing_auth",
+                "libadb_pairing_connection",
+            ],
         },
     },
 }
@@ -512,6 +523,15 @@
         "libselinux",
     ],
 
+    target: {
+        recovery: {
+            exclude_shared_libs: [
+                "libadb_pairing_auth",
+                "libadb_pairing_connection",
+            ],
+        }
+    },
+
     static_libs: [
         "libadbd_services",
         "libcutils_sockets",
@@ -544,6 +564,8 @@
     },
 
     static_libs: [
+        "libadb_crypto",
+        "libadb_tls_connection",
         "libadbconnection_server",
         "libadbd",
         "libadbd_services",
@@ -561,15 +583,22 @@
     ],
 
     shared_libs: [
-        "libadb_crypto",
         "libadb_pairing_connection",
         "libadb_protos",
-        "libadb_tls_connection",
         "libadbd_auth",
         "libadbd_fs",
         "libcrypto",
     ],
 
+    target: {
+        recovery: {
+            exclude_shared_libs: [
+                "libadb_pairing_auth",
+                "libadb_pairing_connection",
+            ],
+        }
+    },
+
     required: [
         "libadbd_auth",
         "libadbd_fs",
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 554a754..98db191 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -34,6 +34,7 @@
 #include <condition_variable>
 #include <mutex>
 #include <string>
+#include <string_view>
 #include <thread>
 #include <vector>
 
@@ -61,6 +62,8 @@
 #include <sys/mount.h>
 #include <android-base/properties.h>
 using namespace std::chrono_literals;
+
+#include "daemon/logging.h"
 #endif
 
 std::string adb_version() {
@@ -312,6 +315,9 @@
 #if ADB_HOST
     handle_online(t);
 #else
+    ADB_LOG(Connection) << "received CNXN: version=" << p->msg.arg0 << ", maxdata = " << p->msg.arg1
+                        << ", banner = '" << banner << "'";
+
     if (t->use_tls) {
         // We still handshake in TLS mode. If auth_required is disabled,
         // we'll just not verify the client's certificate. This should be the
diff --git a/adb/apex/Android.bp b/adb/apex/Android.bp
index 0189455..4346f67 100644
--- a/adb/apex/Android.bp
+++ b/adb/apex/Android.bp
@@ -1,5 +1,6 @@
 apex_defaults {
     name: "com.android.adbd-defaults",
+    updatable: true,
 
     binaries: ["adbd"],
     compile_multilib: "both",
diff --git a/adb/crypto/Android.bp b/adb/crypto/Android.bp
index b7f75ed..ce1de4a 100644
--- a/adb/crypto/Android.bp
+++ b/adb/crypto/Android.bp
@@ -45,8 +45,6 @@
     host_supported: true,
     recovery_available: true,
 
-    stl: "libc++_static",
-
     shared_libs: [
         "libadb_protos",
         "libbase",
diff --git a/adb/daemon/logging.cpp b/adb/daemon/logging.cpp
new file mode 100644
index 0000000..203c6c7
--- /dev/null
+++ b/adb/daemon/logging.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "daemon/logging.h"
+
+#include <mutex>
+#include <optional>
+#include <string_view>
+
+#include <android-base/no_destructor.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <android-base/thread_annotations.h>
+
+#if defined(__ANDROID__)
+struct LogStatus {
+    bool enabled[static_cast<size_t>(adb::LogType::COUNT)];
+
+    bool& operator[](adb::LogType type) { return enabled[static_cast<size_t>(type)]; }
+};
+
+using android::base::CachedProperty;
+using android::base::NoDestructor;
+
+static NoDestructor<std::mutex> log_mutex;
+static NoDestructor<CachedProperty> log_property GUARDED_BY(log_mutex)("debug.adbd.logging");
+static std::optional<LogStatus> cached_log_status GUARDED_BY(log_mutex);
+
+static NoDestructor<CachedProperty> persist_log_property
+        GUARDED_BY(log_mutex)("persist.debug.adbd.logging");
+static std::optional<LogStatus> cached_persist_log_status GUARDED_BY(log_mutex);
+
+static LogStatus ParseLogStatus(std::string_view str) {
+    LogStatus result = {};
+    for (const auto& part : android::base::Split(std::string(str), ",")) {
+        if (part == "cnxn") {
+            result[adb::LogType::Connection] = true;
+        } else if (part == "service") {
+            result[adb::LogType::Service] = true;
+        } else if (part == "shell") {
+            result[adb::LogType::Shell] = true;
+        } else if (part == "all") {
+            result[adb::LogType::Connection] = true;
+            result[adb::LogType::Service] = true;
+            result[adb::LogType::Shell] = true;
+        }
+    }
+    return result;
+}
+
+static LogStatus GetLogStatus(android::base::CachedProperty* property,
+                              std::optional<LogStatus>* cached_status) REQUIRES(log_mutex) {
+    bool changed;
+    const char* value = property->Get(&changed);
+    if (changed || !*cached_status) {
+        **cached_status = ParseLogStatus(value);
+    }
+    return **cached_status;
+}
+
+namespace adb {
+bool is_logging_enabled(LogType type) {
+    std::lock_guard<std::mutex> lock(*log_mutex);
+    return GetLogStatus(log_property.get(), &cached_log_status)[type] ||
+           GetLogStatus(persist_log_property.get(), &cached_persist_log_status)[type];
+}
+}  // namespace adb
+
+#else
+
+namespace adb {
+bool is_logging_enabled(LogType type) {
+    return false;
+}
+}  // namespace adb
+#endif
diff --git a/adb/daemon/logging.h b/adb/daemon/logging.h
new file mode 100644
index 0000000..3e28bef
--- /dev/null
+++ b/adb/daemon/logging.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/logging.h>
+
+namespace adb {
+enum class LogType {
+    Connection,
+    Service,
+    Shell,
+    COUNT,
+};
+
+bool is_logging_enabled(LogType type);
+
+#define ADB_LOG(type) ::adb::is_logging_enabled(::adb::LogType::type) && LOG(INFO)
+
+}  // namespace adb
diff --git a/adb/daemon/services.cpp b/adb/daemon/services.cpp
index 4ec90d2..6bbf66e 100644
--- a/adb/daemon/services.cpp
+++ b/adb/daemon/services.cpp
@@ -54,10 +54,10 @@
 
 #include "daemon/file_sync_service.h"
 #include "daemon/framebuffer_service.h"
+#include "daemon/logging.h"
 #include "daemon/restart_service.h"
 #include "daemon/shell_service.h"
 
-
 void reconnect_service(unique_fd fd, atransport* t) {
     WriteFdExactly(fd.get(), "done");
     kick_transport(t);
@@ -259,6 +259,8 @@
 }
 
 unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) {
+    ADB_LOG(Service) << "transport " << transport->serial_name() << " opening service " << name;
+
 #if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
     if (name.starts_with("abb:") || name.starts_with("abb_exec:")) {
         return execute_abb_command(name);
diff --git a/adb/daemon/shell_service.cpp b/adb/daemon/shell_service.cpp
index f62032d..fbfae1e 100644
--- a/adb/daemon/shell_service.cpp
+++ b/adb/daemon/shell_service.cpp
@@ -107,6 +107,7 @@
 #include "adb_trace.h"
 #include "adb_unique_fd.h"
 #include "adb_utils.h"
+#include "daemon/logging.h"
 #include "security_log_tags.h"
 #include "shell_protocol.h"
 
@@ -760,14 +761,14 @@
             D("post waitpid (pid=%d) status=%04x", pid_, status);
             if (WIFSIGNALED(status)) {
                 exit_code = 0x80 | WTERMSIG(status);
-                D("subprocess killed by signal %d", WTERMSIG(status));
+                ADB_LOG(Shell) << "subprocess " << pid_ << " killed by signal " << WTERMSIG(status);
                 break;
             } else if (!WIFEXITED(status)) {
                 D("subprocess didn't exit");
                 break;
             } else if (WEXITSTATUS(status) >= 0) {
                 exit_code = WEXITSTATUS(status);
-                D("subprocess exit code = %d", WEXITSTATUS(status));
+                ADB_LOG(Shell) << "subprocess " << pid_ << " exited with status " << exit_code;
                 break;
             }
         }
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index 0928198..87937fb 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -282,6 +282,7 @@
 
         monitor_thread_ = std::thread([this]() {
             adb_thread_setname("UsbFfs-monitor");
+            LOG(INFO) << "UsbFfs-monitor thread spawned";
 
             bool bound = false;
             bool enabled = false;
@@ -427,6 +428,8 @@
         worker_started_ = true;
         worker_thread_ = std::thread([this]() {
             adb_thread_setname("UsbFfs-worker");
+            LOG(INFO) << "UsbFfs-worker thread spawned";
+
             for (size_t i = 0; i < kUsbReadQueueDepth; ++i) {
                 read_requests_[i] = CreateReadBlock(next_read_id_++);
                 if (!SubmitRead(&read_requests_[i])) {
@@ -525,14 +528,16 @@
             }
 
             if (id.direction == TransferDirection::READ) {
-                HandleRead(id, event.res);
+                if (!HandleRead(id, event.res)) {
+                    return;
+                }
             } else {
                 HandleWrite(id);
             }
         }
     }
 
-    void HandleRead(TransferId id, int64_t size) {
+    bool HandleRead(TransferId id, int64_t size) {
         uint64_t read_idx = id.id % kUsbReadQueueDepth;
         IoReadBlock* block = &read_requests_[read_idx];
         block->pending = false;
@@ -542,7 +547,7 @@
         if (block->id().id != needed_read_id_) {
             LOG(VERBOSE) << "read " << block->id().id << " completed while waiting for "
                          << needed_read_id_;
-            return;
+            return true;
         }
 
         for (uint64_t id = needed_read_id_;; ++id) {
@@ -551,15 +556,22 @@
             if (current_block->pending) {
                 break;
             }
-            ProcessRead(current_block);
+            if (!ProcessRead(current_block)) {
+                return false;
+            }
             ++needed_read_id_;
         }
+
+        return true;
     }
 
-    void ProcessRead(IoReadBlock* block) {
+    bool ProcessRead(IoReadBlock* block) {
         if (!block->payload.empty()) {
             if (!incoming_header_.has_value()) {
-                CHECK_EQ(sizeof(amessage), block->payload.size());
+                if (block->payload.size() != sizeof(amessage)) {
+                    HandleError("received packet of unexpected length while reading header");
+                    return false;
+                }
                 amessage& msg = incoming_header_.emplace();
                 memcpy(&msg, block->payload.data(), sizeof(msg));
                 LOG(DEBUG) << "USB read:" << dump_header(&msg);
@@ -567,7 +579,10 @@
             } else {
                 size_t bytes_left = incoming_header_->data_length - incoming_payload_.size();
                 Block payload = std::move(block->payload);
-                CHECK_LE(payload.size(), bytes_left);
+                if (block->payload.size() > bytes_left) {
+                    HandleError("received too many bytes while waiting for payload");
+                    return false;
+                }
                 incoming_payload_.append(std::move(payload));
             }
 
@@ -590,6 +605,7 @@
 
         PrepareReadBlock(block, block->id().id + kUsbReadQueueDepth);
         SubmitRead(block);
+        return true;
     }
 
     bool SubmitRead(IoReadBlock* block) {
diff --git a/adb/daemon/usb_ffs.cpp b/adb/daemon/usb_ffs.cpp
index b19fa5d..cb7e2fb 100644
--- a/adb/daemon/usb_ffs.cpp
+++ b/adb/daemon/usb_ffs.cpp
@@ -299,6 +299,7 @@
         }
         // Signal only when writing the descriptors to ffs
         android::base::SetProperty("sys.usb.ffs.ready", "1");
+        *out_control = std::move(control);
     }
 
     bulk_out.reset(adb_open(USB_FFS_ADB_OUT, O_RDONLY));
@@ -313,7 +314,6 @@
         return false;
     }
 
-    *out_control = std::move(control);
     *out_bulk_in = std::move(bulk_in);
     *out_bulk_out = std::move(bulk_out);
     return true;
diff --git a/adb/pairing_auth/Android.bp b/adb/pairing_auth/Android.bp
index 0850047..a43f4d0 100644
--- a/adb/pairing_auth/Android.bp
+++ b/adb/pairing_auth/Android.bp
@@ -47,7 +47,7 @@
     use_version_lib: false,
 
     host_supported: true,
-    recovery_available: true,
+    recovery_available: false,
 
     stl: "libc++_static",
 
diff --git a/adb/pairing_connection/Android.bp b/adb/pairing_connection/Android.bp
index c053854..bcde7b1 100644
--- a/adb/pairing_connection/Android.bp
+++ b/adb/pairing_connection/Android.bp
@@ -52,7 +52,7 @@
     stl: "libc++_static",
 
     host_supported: true,
-    recovery_available: true,
+    recovery_available: false,
 
     static_libs: [
         "libbase",
@@ -131,7 +131,7 @@
     ],
 
     host_supported: true,
-    recovery_available: true,
+    recovery_available: false,
 
     stl: "libc++_static",
 
diff --git a/adb/pairing_connection/tests/pairing_connection_test.cpp b/adb/pairing_connection/tests/pairing_connection_test.cpp
index b6e09f1..86b66aa 100644
--- a/adb/pairing_connection/tests/pairing_connection_test.cpp
+++ b/adb/pairing_connection/tests/pairing_connection_test.cpp
@@ -440,7 +440,7 @@
     EXPECT_FALSE(*(server_waiter.is_valid_));
 }
 
-TEST_F(AdbPairingConnectionTest, MultipleClientsOnePass) {
+TEST_F(AdbPairingConnectionTest, DISABLED_MultipleClientsOnePass) {
     // Send multiple clients with bad passwords, but send the last one with the
     // correct password.
     std::vector<uint8_t> pswd{0x01, 0x03, 0x05, 0x07};
diff --git a/adb/test_adb.py b/adb/test_adb.py
index 3d6de26..c872fb0 100755
--- a/adb/test_adb.py
+++ b/adb/test_adb.py
@@ -33,6 +33,11 @@
 import unittest
 import warnings
 
+def find_open_port():
+    # Find an open port.
+    with socket.socket() as s:
+        s.bind(("localhost", 0))
+        return s.getsockname()[1]
 
 @contextlib.contextmanager
 def fake_adbd(protocol=socket.AF_INET, port=0):
@@ -126,10 +131,7 @@
     This creates an ADB server and returns the port it's listening on.
     """
 
-    port = 5038
-    # Kill any existing server on this non-default port.
-    subprocess.check_output(["adb", "-P", str(port), "kill-server"],
-                            stderr=subprocess.STDOUT)
+    port = find_open_port()
     read_pipe, write_pipe = os.pipe()
 
     if sys.platform == "win32":
@@ -224,10 +226,7 @@
         # adb server, this also tests whether multiple instances of the adb
         # server conflict on adb.log.
 
-        port = 5038
-        # Kill any existing server on this non-default port.
-        subprocess.check_output(["adb", "-P", str(port), "kill-server"],
-                                stderr=subprocess.STDOUT)
+        port = find_open_port()
 
         try:
             # We get warnings for unclosed files for the subprocess's pipes,
@@ -289,12 +288,8 @@
         """
         Tests that the server can start up on ::1 and that it's accessible
         """
-        server_port = 5037
-        # Kill any existing server on this non-default port.
-        subprocess.check_output(
-            ["adb", "-P", str(server_port), "kill-server"],
-            stderr=subprocess.STDOUT,
-        )
+
+        server_port = find_open_port()
         try:
             subprocess.check_output(
                 ["adb", "-L", "tcp:[::1]:{}".format(server_port), "server"],
diff --git a/adb/tls/Android.bp b/adb/tls/Android.bp
index 49833ff..f2837e1 100644
--- a/adb/tls/Android.bp
+++ b/adb/tls/Android.bp
@@ -42,12 +42,8 @@
         "//system/core/adb:__subpackages__",
     ],
 
-    stl: "libc++_static",
-
-    static_libs: [
-        "libbase",
-    ],
     shared_libs: [
+        "libbase",
         "libcrypto",
         "liblog",
         "libssl",
diff --git a/base/include/android-base/properties.h b/base/include/android-base/properties.h
index 31823df..49f1f31 100644
--- a/base/include/android-base/properties.h
+++ b/base/include/android-base/properties.h
@@ -20,8 +20,11 @@
 
 #include <chrono>
 #include <limits>
+#include <optional>
 #include <string>
 
+struct prop_info;
+
 namespace android {
 namespace base {
 
@@ -67,5 +70,32 @@
                                                          std::chrono::milliseconds::max());
 #endif
 
+#if defined(__BIONIC__) && __cplusplus >= 201703L
+// Cached system property lookup. For code that needs to read the same property multiple times,
+// this class helps optimize those lookups.
+class CachedProperty {
+ public:
+  explicit CachedProperty(const char* property_name);
+
+  // Returns the current value of the underlying system property as cheaply as possible.
+  // The returned pointer is valid until the next call to Get. Because most callers are going
+  // to want to parse the string returned here and cached that as well, this function performs
+  // no locking, and is completely thread unsafe. It is the caller's responsibility to provide a
+  // lock for thread-safety.
+  //
+  // Note: *changed can be set to true even if the contents of the property remain the same.
+  const char* Get(bool* changed = nullptr);
+
+ private:
+  std::string property_name_;
+  const prop_info* prop_info_;
+  std::optional<uint32_t> cached_area_serial_;
+  std::optional<uint32_t> cached_property_serial_;
+  char cached_value_[92];
+  bool is_read_only_;
+  const char* read_only_property_;
+};
+#endif
+
 } // namespace base
 } // namespace android
diff --git a/base/properties.cpp b/base/properties.cpp
index 4731bf2..35e41a8 100644
--- a/base/properties.cpp
+++ b/base/properties.cpp
@@ -30,6 +30,7 @@
 
 #include <android-base/parsebool.h>
 #include <android-base/parseint.h>
+#include <android-base/strings.h>
 
 namespace android {
 namespace base {
@@ -195,6 +196,62 @@
   return (WaitForPropertyCreation(key, relative_timeout, start_time) != nullptr);
 }
 
+CachedProperty::CachedProperty(const char* property_name)
+    : property_name_(property_name),
+      prop_info_(nullptr),
+      cached_area_serial_(0),
+      cached_property_serial_(0),
+      is_read_only_(android::base::StartsWith(property_name, "ro.")),
+      read_only_property_(nullptr) {
+  static_assert(sizeof(cached_value_) == PROP_VALUE_MAX);
+}
+
+const char* CachedProperty::Get(bool* changed) {
+  std::optional<uint32_t> initial_property_serial_ = cached_property_serial_;
+
+  // Do we have a `struct prop_info` yet?
+  if (prop_info_ == nullptr) {
+    // `__system_property_find` is expensive, so only retry if a property
+    // has been created since last time we checked.
+    uint32_t property_area_serial = __system_property_area_serial();
+    if (property_area_serial != cached_area_serial_) {
+      prop_info_ = __system_property_find(property_name_.c_str());
+      cached_area_serial_ = property_area_serial;
+    }
+  }
+
+  if (prop_info_ != nullptr) {
+    // Only bother re-reading the property if it's actually changed since last time.
+    uint32_t property_serial = __system_property_serial(prop_info_);
+    if (property_serial != cached_property_serial_) {
+      __system_property_read_callback(
+          prop_info_,
+          [](void* data, const char*, const char* value, uint32_t serial) {
+            CachedProperty* instance = reinterpret_cast<CachedProperty*>(data);
+            instance->cached_property_serial_ = serial;
+            // Read only properties can be larger than PROP_VALUE_MAX, but also never change value
+            // or location, thus we return the pointer from the shared memory directly.
+            if (instance->is_read_only_) {
+              instance->read_only_property_ = value;
+            } else {
+              strlcpy(instance->cached_value_, value, PROP_VALUE_MAX);
+            }
+          },
+          this);
+    }
+  }
+
+  if (changed) {
+    *changed = cached_property_serial_ != initial_property_serial_;
+  }
+
+  if (is_read_only_) {
+    return read_only_property_;
+  } else {
+    return cached_value_;
+  }
+}
+
 #endif
 
 }  // namespace base
diff --git a/base/properties_test.cpp b/base/properties_test.cpp
index e7d4880..c30c41e 100644
--- a/base/properties_test.cpp
+++ b/base/properties_test.cpp
@@ -230,3 +230,28 @@
   GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
 #endif
 }
+
+TEST(properties, CachedProperty) {
+#if defined(__BIONIC__)
+  android::base::CachedProperty cached_property("debug.libbase.CachedProperty_test");
+  bool changed;
+  cached_property.Get(&changed);
+
+  android::base::SetProperty("debug.libbase.CachedProperty_test", "foo");
+  ASSERT_STREQ("foo", cached_property.Get(&changed));
+  ASSERT_TRUE(changed);
+
+  ASSERT_STREQ("foo", cached_property.Get(&changed));
+  ASSERT_FALSE(changed);
+
+  android::base::SetProperty("debug.libbase.CachedProperty_test", "bar");
+  ASSERT_STREQ("bar", cached_property.Get(&changed));
+  ASSERT_TRUE(changed);
+
+  ASSERT_STREQ("bar", cached_property.Get(&changed));
+  ASSERT_FALSE(changed);
+
+#else
+  GTEST_LOG_(INFO) << "This test does nothing on the host.\n";
+#endif
+}
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index 2c9dec9..ca120c6 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -261,7 +261,7 @@
     }
 
     // If the slot is not changing, do nothing.
-    if (slot == boot_control_hal->getCurrentSlot()) {
+    if (args[1] == device->GetCurrentSlot()) {
         return device->WriteOkay("");
     }
 
diff --git a/fs_mgr/TEST_MAPPING b/fs_mgr/TEST_MAPPING
index 705d4e3..676f446 100644
--- a/fs_mgr/TEST_MAPPING
+++ b/fs_mgr/TEST_MAPPING
@@ -13,7 +13,7 @@
       "name": "fiemap_writer_test"
     },
     {
-      "name": "vts_libsnapshot_test_presubmit"
+      "name": "vts_libsnapshot_test"
     }
   ]
 }
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 5223087..49ca5db 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -97,6 +97,7 @@
 using android::base::Basename;
 using android::base::GetBoolProperty;
 using android::base::Realpath;
+using android::base::SetProperty;
 using android::base::StartsWith;
 using android::base::Timer;
 using android::base::unique_fd;
@@ -178,6 +179,7 @@
         return;
     }
 
+    Timer t;
     /* Check for the types of filesystems we know how to check */
     if (is_extfs(fs_type)) {
         /*
@@ -253,15 +255,19 @@
             }
         }
     } else if (is_f2fs(fs_type)) {
-        const char* f2fs_fsck_argv[] = {F2FS_FSCK_BIN, "-a", blk_device.c_str()};
-        const char* f2fs_fsck_forced_argv[] = {F2FS_FSCK_BIN, "-f", blk_device.c_str()};
+        const char* f2fs_fsck_argv[] = {F2FS_FSCK_BIN,     "-a", "-c", "10000", "--debug-cache",
+                                        blk_device.c_str()};
+        const char* f2fs_fsck_forced_argv[] = {
+                F2FS_FSCK_BIN, "-f", "-c", "10000", "--debug-cache", blk_device.c_str()};
 
         if (should_force_check(*fs_stat)) {
-            LINFO << "Running " << F2FS_FSCK_BIN << " -f " << realpath(blk_device);
+            LINFO << "Running " << F2FS_FSCK_BIN << " -f -c 10000 --debug-cache"
+                  << realpath(blk_device);
             ret = logwrap_fork_execvp(ARRAY_SIZE(f2fs_fsck_forced_argv), f2fs_fsck_forced_argv,
                                       &status, false, LOG_KLOG | LOG_FILE, false, FSCK_LOG_FILE);
         } else {
-            LINFO << "Running " << F2FS_FSCK_BIN << " -a " << realpath(blk_device);
+            LINFO << "Running " << F2FS_FSCK_BIN << " -a -c 10000 --debug-cache"
+                  << realpath(blk_device);
             ret = logwrap_fork_execvp(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv, &status, false,
                                       LOG_KLOG | LOG_FILE, false, FSCK_LOG_FILE);
         }
@@ -270,7 +276,8 @@
             LERROR << "Failed trying to run " << F2FS_FSCK_BIN;
         }
     }
-
+    android::base::SetProperty("ro.boottime.init.fsck." + Basename(target),
+                               std::to_string(t.duration().count()));
     return;
 }
 
diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp
index 6461788..29b1032 100644
--- a/fs_mgr/libdm/dm_target.cpp
+++ b/fs_mgr/libdm/dm_target.cpp
@@ -243,12 +243,10 @@
     return android::base::Join(argv, " ");
 }
 
-const std::string DmTargetDefaultKey::name_ = "default-key";
-
 bool DmTargetDefaultKey::IsLegacy(bool* result) {
     DeviceMapper& dm = DeviceMapper::Instance();
     DmTargetTypeInfo info;
-    if (!dm.GetTargetByName(name_, &info)) return false;
+    if (!dm.GetTargetByName(kName, &info)) return false;
     // dm-default-key was modified to be like dm-crypt with version 2
     *result = !info.IsAtLeast(2, 0, 0);
     return true;
diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h
index d2e50d3..050d0b6 100644
--- a/fs_mgr/libdm/include/libdm/dm_target.h
+++ b/fs_mgr/libdm/include/libdm/dm_target.h
@@ -287,7 +287,7 @@
           blockdev_(blockdev),
           start_sector_(start_sector) {}
 
-    std::string name() const override { return name_; }
+    std::string name() const override { return kName; }
     bool Valid() const override;
     std::string GetParameterString() const override;
     static bool IsLegacy(bool* result);
@@ -296,7 +296,8 @@
     void SetWrappedKeyV0() { is_hw_wrapped_ = true; }
 
   private:
-    static const std::string name_;
+    inline static const std::string kName = "default-key";
+
     std::string cipher_;
     std::string key_;
     std::string blockdev_;
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index d274ba4..6c739fc 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -208,21 +208,12 @@
     defaults: ["libsnapshot_test_defaults"],
 }
 
-cc_test {
-    name: "vts_libsnapshot_test_presubmit",
-    defaults: ["libsnapshot_test_defaults"],
-    cppflags: [
-        "-DSKIP_TEST_IN_PRESUBMIT",
-    ],
-}
-
 cc_binary {
     name: "snapshotctl",
     srcs: [
         "snapshotctl.cpp",
     ],
     static_libs: [
-        "libdm",
         "libfstab",
         "libsnapshot",
     ],
@@ -238,6 +229,7 @@
         "liblog",
         "liblp",
         "libprotobuf-cpp-lite",
+        "libstatslog",
         "libutils",
 
         // TODO(b/148818798): remove when parent bug is fixed.
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 5d2840f..0ffaa71 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -506,9 +506,6 @@
 }
 
 TEST_F(SnapshotTest, FirstStageMountAndMerge) {
-#ifdef SKIP_TEST_IN_PRESUBMIT
-    GTEST_SKIP() << "WIP failure b/148889015";
-#endif
     ASSERT_TRUE(AcquireLock());
 
     static const uint64_t kDeviceSize = 1024 * 1024;
@@ -565,9 +562,6 @@
 }
 
 TEST_F(SnapshotTest, FlashSuperDuringMerge) {
-#ifdef SKIP_TEST_IN_PRESUBMIT
-    GTEST_SKIP() << "WIP failure b/148889015";
-#endif
     ASSERT_TRUE(AcquireLock());
 
     static const uint64_t kDeviceSize = 1024 * 1024;
@@ -979,9 +973,6 @@
 // Also test UnmapUpdateSnapshot unmaps everything.
 // Also test first stage mount and merge after this.
 TEST_F(SnapshotUpdateTest, FullUpdateFlow) {
-#ifdef SKIP_TEST_IN_PRESUBMIT
-    GTEST_SKIP() << "WIP failure b/148889015";
-#endif
     // OTA client blindly unmaps all partitions that are possibly mapped.
     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
         ASSERT_TRUE(sm->UnmapUpdateSnapshot(name));
@@ -1129,9 +1120,6 @@
 
 // Test that the old partitions are not modified.
 TEST_F(SnapshotUpdateTest, TestRollback) {
-#ifdef SKIP_TEST_IN_PRESUBMIT
-    GTEST_SKIP() << "WIP failure b/148889015";
-#endif
     // Execute the update.
     ASSERT_TRUE(sm->BeginUpdate());
     ASSERT_TRUE(sm->UnmapUpdateSnapshot("sys_b"));
@@ -1309,9 +1297,6 @@
 }
 
 TEST_F(SnapshotUpdateTest, MergeCannotRemoveCow) {
-#ifdef SKIP_TEST_IN_PRESUBMIT
-    GTEST_SKIP() << "WIP failure b/148889015";
-#endif
     // Make source partitions as big as possible to force COW image to be created.
     SetSize(sys_, 5_MiB);
     SetSize(vnd_, 5_MiB);
@@ -1586,9 +1571,6 @@
 }
 
 TEST_F(SnapshotUpdateTest, WaitForMerge) {
-#ifdef SKIP_TEST_IN_PRESUBMIT
-    GTEST_SKIP() << "WIP failure b/148889015";
-#endif
     AddOperationForPartitions();
 
     // Execute the update.
diff --git a/fs_mgr/libsnapshot/snapshotctl.cpp b/fs_mgr/libsnapshot/snapshotctl.cpp
index e35ad4b..34d3d69 100644
--- a/fs_mgr/libsnapshot/snapshotctl.cpp
+++ b/fs_mgr/libsnapshot/snapshotctl.cpp
@@ -24,9 +24,11 @@
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
+#include <android/snapshot/snapshot.pb.h>
 #include <libsnapshot/snapshot.h>
-#include "utility.h"
+#include <statslog.h>
 
+#include "snapshot_stats.h"
 #include "utility.h"
 
 using namespace std::string_literals;
@@ -37,17 +39,29 @@
                  "Actions:\n"
                  "  dump\n"
                  "    Print snapshot states.\n"
-                 "  merge [--logcat] [--log-to-file]\n"
+                 "  merge [--logcat] [--log-to-file] [--report] [--dry-run]\n"
                  "    Initialize merge and wait for it to be completed.\n"
                  "    If --logcat is specified, log to logcat.\n"
                  "    If --log-to-file is specified, log to /data/misc/snapshotctl_log/.\n"
-                 "    If both specified, log to both. If none specified, log to stdout.\n";
+                 "    If both specified, log to both. If none specified, log to stdout.\n"
+                 "    If --report is specified, send merge statistics to statsd.\n"
+                 "    If --dry-run flag, no real merge operation is is triggered, and\n"
+                 "      sample statistics are sent to statsd for testing purpose.\n";
     return EX_USAGE;
 }
 
 namespace android {
 namespace snapshot {
 
+static SnapshotMergeReport GetDummySnapshotMergeReport() {
+    SnapshotMergeReport fake_report;
+
+    fake_report.set_state(UpdateState::MergeCompleted);
+    fake_report.set_resume_count(56);
+
+    return fake_report;
+}
+
 bool DumpCmdHandler(int /*argc*/, char** argv) {
     android::base::InitLogging(argv, &android::base::StderrLogger);
     return SnapshotManager::New()->Dump(std::cout);
@@ -113,24 +127,53 @@
 };
 
 bool MergeCmdHandler(int argc, char** argv) {
-    auto begin = std::chrono::steady_clock::now();
+    std::chrono::milliseconds passed_ms;
+
+    bool report_to_statsd = false;
+    bool dry_run = false;
+    for (int i = 2; i < argc; ++i) {
+        if (argv[i] == "--report"s) {
+            report_to_statsd = true;
+        } else if (argv[i] == "--dry-run"s) {
+            dry_run = true;
+        }
+    }
 
     // 'snapshotctl merge' is stripped away from arguments to
     // Logger.
     android::base::InitLogging(argv);
     android::base::SetLogger(MergeCmdLogger(argc - 2, argv + 2));
 
-    auto state = SnapshotManager::New()->InitiateMergeAndWait();
+    UpdateState state;
+    SnapshotMergeReport merge_report;
+    if (dry_run) {
+        merge_report = GetDummySnapshotMergeReport();
+        state = merge_report.state();
+        passed_ms = std::chrono::milliseconds(1234);
+    } else {
+        auto begin = std::chrono::steady_clock::now();
 
-    // We could wind up in the Unverified state if the device rolled back or
-    // hasn't fully rebooted. Ignore this.
-    if (state == UpdateState::None || state == UpdateState::Unverified) {
-        return true;
-    }
-    if (state == UpdateState::MergeCompleted) {
+        state = SnapshotManager::New()->InitiateMergeAndWait(&merge_report);
+
+        // We could wind up in the Unverified state if the device rolled back or
+        // hasn't fully rebooted. Ignore this.
+        if (state == UpdateState::None || state == UpdateState::Unverified) {
+            return true;
+        }
+
         auto end = std::chrono::steady_clock::now();
-        auto passed = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count();
-        LOG(INFO) << "Snapshot merged in " << passed << " ms.";
+        passed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin);
+    }
+
+    if (report_to_statsd) {
+        android::util::stats_write(android::util::SNAPSHOT_MERGE_REPORTED,
+                                   static_cast<int32_t>(merge_report.state()),
+                                   static_cast<int64_t>(passed_ms.count()),
+                                   static_cast<int32_t>(merge_report.resume_count()));
+    }
+
+    if (state == UpdateState::MergeCompleted) {
+        LOG(INFO) << "Snapshot merged in " << passed_ms.count() << " ms.";
         return true;
     }
 
diff --git a/fs_mgr/libsnapshot/snapshotctl.rc b/fs_mgr/libsnapshot/snapshotctl.rc
index 5dbe352..ccb2c41 100644
--- a/fs_mgr/libsnapshot/snapshotctl.rc
+++ b/fs_mgr/libsnapshot/snapshotctl.rc
@@ -1,2 +1,2 @@
 on property:sys.boot_completed=1
-    exec_background - root root -- /system/bin/snapshotctl merge --logcat --log-to-file
+    exec_background - root root -- /system/bin/snapshotctl merge --logcat --log-to-file --report
diff --git a/init/init.cpp b/init/init.cpp
index b0f929c..63aefc1 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -120,7 +120,7 @@
         }
     };
 
-    if (auto result = epoll->RegisterHandler(epoll_fd, drain_socket); !result) {
+    if (auto result = epoll->RegisterHandler(epoll_fd, drain_socket); !result.ok()) {
         LOG(FATAL) << result.error();
     }
 }
diff --git a/init/mount_namespace.cpp b/init/mount_namespace.cpp
index aa36849..2175075 100644
--- a/init/mount_namespace.cpp
+++ b/init/mount_namespace.cpp
@@ -323,10 +323,20 @@
     }
     if (bootstrap_ns_id != GetMountNamespaceId() && bootstrap_ns_fd.get() != -1 &&
         IsApexUpdatable()) {
+        // The property service thread and its descendent threads must be in the correct mount
+        // namespace to call Service::Start(), however setns() only operates on a single thread and
+        // fails when secondary threads attempt to join the same mount namespace.  Therefore, we
+        // must join the property service thread and its descendents before the setns() call.  Those
+        // threads are then started again after the setns() call, and they'll be in the proper
+        // namespace.
+        PausePropertyService();
+
         if (setns(bootstrap_ns_fd.get(), CLONE_NEWNS) == -1) {
             PLOG(ERROR) << "Failed to switch to bootstrap mount namespace.";
             return false;
         }
+
+        ResumePropertyService();
     }
     return true;
 }
diff --git a/init/reboot.cpp b/init/reboot.cpp
index f7cc36e..cad192d 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -96,8 +96,10 @@
     return ret;
 }
 
-static void PersistRebootReason(const char* reason) {
-    SetProperty(LAST_REBOOT_REASON_PROPERTY, reason);
+static void PersistRebootReason(const char* reason, bool write_to_property) {
+    if (write_to_property) {
+        SetProperty(LAST_REBOOT_REASON_PROPERTY, reason);
+    }
     WriteStringToFile(reason, LAST_REBOOT_REASON_FILE);
 }
 
@@ -535,14 +537,6 @@
     Timer t;
     LOG(INFO) << "Reboot start, reason: " << reason << ", reboot_target: " << reboot_target;
 
-    // If /data isn't mounted then we can skip the extra reboot steps below, since we don't need to
-    // worry about unmounting it.
-    if (!IsDataMounted()) {
-        sync();
-        RebootSystem(cmd, reboot_target);
-        abort();
-    }
-
     // Ensure last reboot reason is reduced to canonical
     // alias reported in bootloader or system boot reason.
     size_t skip = 0;
@@ -552,9 +546,17 @@
          reasons[1] == "hard" || reasons[1] == "warm")) {
         skip = strlen("reboot,");
     }
-    PersistRebootReason(reason.c_str() + skip);
+    PersistRebootReason(reason.c_str() + skip, true);
     sync();
 
+    // If /data isn't mounted then we can skip the extra reboot steps below, since we don't need to
+    // worry about unmounting it.
+    if (!IsDataMounted()) {
+        sync();
+        RebootSystem(cmd, reboot_target);
+        abort();
+    }
+
     bool is_thermal_shutdown = cmd == ANDROID_RB_THERMOFF;
 
     auto shutdown_timeout = 0ms;
@@ -818,6 +820,7 @@
         LOG(INFO) << "Re-enabling service '" << s->name() << "'";
         s->Enable();
     }
+    ServiceList::GetInstance().ResetState();
     LeaveShutdown();
     ActionManager::GetInstance().QueueEventTrigger("userspace-reboot-resume");
     guard.Disable();  // Go on with userspace reboot.
@@ -836,7 +839,8 @@
     if (!WaitForProperty("sys.boot_completed", "1", timeout)) {
         LOG(ERROR) << "Failed to boot in " << timeout.count() << "ms. Switching to full reboot";
         // In this case device is in a boot loop. Only way to recover is to do dirty reboot.
-        PersistRebootReason("userspace_failed,watchdog_triggered");
+        // Since init might be wedged, don't try to write reboot reason into a persistent property.
+        PersistRebootReason("userspace_failed,watchdog_triggered", false);
         RebootSystem(ANDROID_RB_RESTART2, "userspace_failed,watchdog_triggered");
     }
     LOG(INFO) << "Device booted, stopping userspace reboot watchdog";
diff --git a/init/service_list.h b/init/service_list.h
index 8cbc878..280a228 100644
--- a/init/service_list.h
+++ b/init/service_list.h
@@ -81,6 +81,11 @@
     bool IsServicesUpdated() const { return services_update_finished_; }
     void DelayService(const Service& service) REQUIRES(service_lock);
 
+    void ResetState() {
+        post_data_ = false;
+        services_update_finished_ = false;
+    }
+
   private:
     std::vector<std::unique_ptr<Service>> services_;
 
diff --git a/libcutils/include/cutils/trace.h b/libcutils/include/cutils/trace.h
index e12c32c..c74ee3e 100644
--- a/libcutils/include/cutils/trace.h
+++ b/libcutils/include/cutils/trace.h
@@ -88,12 +88,6 @@
 #error ATRACE_TAG must be defined to be one of the tags defined in cutils/trace.h
 #endif
 
-// Set this to 0 to revert to the old Binder-based atrace implementation.
-// This is only here in case rollbacks do not apply cleanly.
-// TODO(fmayer): Remove this once we are confident this won't need to be
-// rolled back, no later than 2020-03-01.
-#define ATRACE_SHMEM 1
-
 /**
  * Opens the trace file for writing and reads the property for initial tags.
  * The atrace.tags.enableflags property sets the tags to trace.
@@ -121,15 +115,11 @@
  * prevent tracing within the Zygote process.
  */
 void atrace_set_tracing_enabled(bool enabled);
+
 /**
- * If !ATRACE_SHMEM:
- *   Flag indicating whether setup has been completed, initialized to 0.
- *   Nonzero indicates setup has completed.
- *   Note: This does NOT indicate whether or not setup was successful.
- * If ATRACE_SHMEM:
- *   This is always set to false. This forces code that uses an old version
- *   of this header to always call into atrace_setup, in which we call
- *   atrace_init unconditionally.
+ * This is always set to false. This forces code that uses an old version
+ * of this header to always call into atrace_setup, in which we call
+ * atrace_init unconditionally.
  */
 extern atomic_bool atrace_is_ready;
 
@@ -154,28 +144,8 @@
 #define ATRACE_INIT() atrace_init()
 #define ATRACE_GET_ENABLED_TAGS() atrace_get_enabled_tags()
 
-#if ATRACE_SHMEM
 void atrace_init();
 uint64_t atrace_get_enabled_tags();
-#else
-static inline void atrace_init()
-{
-    if (CC_UNLIKELY(!atomic_load_explicit(&atrace_is_ready, memory_order_acquire))) {
-        atrace_setup();
-    }
-}
-
-/**
- * Get the mask of all tags currently enabled.
- * It can be used as a guard condition around more expensive trace calculations.
- * Every trace function calls this, which ensures atrace_init is run.
- */
-static inline uint64_t atrace_get_enabled_tags()
-{
-    atrace_init();
-    return atrace_enabled_tags;
-}
-#endif
 
 /**
  * Test if a given tag is currently enabled.
diff --git a/libcutils/trace-dev.cpp b/libcutils/trace-dev.cpp
index 9ca1729..5a09a2d 100644
--- a/libcutils/trace-dev.cpp
+++ b/libcutils/trace-dev.cpp
@@ -41,9 +41,6 @@
     } else {
       atrace_enabled_tags = atrace_get_property();
     }
-#if !ATRACE_SHMEM
-    atomic_store_explicit(&atrace_is_ready, true, memory_order_release);
-#endif
 }
 
 static void atrace_seq_number_changed(uint32_t prev_seq_no, uint32_t seq_no) {
@@ -69,11 +66,7 @@
 
 void atrace_setup()
 {
-#if ATRACE_SHMEM
     atrace_init();
-#else
-    pthread_once(&atrace_once_control, atrace_init_once);
-#endif
 }
 
 void atrace_begin_body(const char* name)
diff --git a/libcutils/trace-dev.inc b/libcutils/trace-dev.inc
index a57a4c5..3ec98b3 100644
--- a/libcutils/trace-dev.inc
+++ b/libcutils/trace-dev.inc
@@ -71,8 +71,6 @@
 static const prop_info* atrace_property_info = reinterpret_cast<const prop_info*>(empty_pi);
 #endif
 
-#if ATRACE_SHMEM
-
 /**
  * This is called when the sequence number of debug.atrace.tags.enableflags
  * changes and we need to reload the enabled tags.
@@ -96,7 +94,6 @@
     atrace_init();
     return atrace_enabled_tags;
 }
-#endif
 
 // Set whether this process is debuggable, which determines whether
 // application-level tracing is allowed when the ro.debuggable system property
@@ -186,19 +183,17 @@
 void atrace_update_tags()
 {
     uint64_t tags;
-    if (ATRACE_SHMEM || CC_UNLIKELY(atomic_load_explicit(&atrace_is_ready, memory_order_acquire))) {
-        if (atomic_load_explicit(&atrace_is_enabled, memory_order_acquire)) {
-            tags = atrace_get_property();
-            pthread_mutex_lock(&atrace_tags_mutex);
-            atrace_enabled_tags = tags;
-            pthread_mutex_unlock(&atrace_tags_mutex);
-        } else {
-            // Tracing is disabled for this process, so we simply don't
-            // initialize the tags.
-            pthread_mutex_lock(&atrace_tags_mutex);
-            atrace_enabled_tags = ATRACE_TAG_NOT_READY;
-            pthread_mutex_unlock(&atrace_tags_mutex);
-        }
+    if (atomic_load_explicit(&atrace_is_enabled, memory_order_acquire)) {
+        tags = atrace_get_property();
+        pthread_mutex_lock(&atrace_tags_mutex);
+        atrace_enabled_tags = tags;
+        pthread_mutex_unlock(&atrace_tags_mutex);
+    } else {
+        // Tracing is disabled for this process, so we simply don't
+        // initialize the tags.
+        pthread_mutex_lock(&atrace_tags_mutex);
+        atrace_enabled_tags = ATRACE_TAG_NOT_READY;
+        pthread_mutex_unlock(&atrace_tags_mutex);
     }
 }
 
diff --git a/libcutils/trace-host.cpp b/libcutils/trace-host.cpp
index c21d0ee..9781ad3 100644
--- a/libcutils/trace-host.cpp
+++ b/libcutils/trace-host.cpp
@@ -30,10 +30,8 @@
 void atrace_async_end_body(const char* /*name*/, int32_t /*cookie*/) {}
 void atrace_int_body(const char* /*name*/, int32_t /*value*/) {}
 void atrace_int64_body(const char* /*name*/, int64_t /*value*/) {}
-#if ATRACE_SHMEM
 void atrace_init() {}
 uint64_t atrace_get_enabled_tags()
 {
     return ATRACE_TAG_NOT_READY;
 }
-#endif
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 7f183c2..f1e5118 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -101,11 +101,6 @@
         versions: ["29", "30"],
     },
 
-    // TODO(tomcherry): Renable this before release branch is cut
-    header_abi_checker: {
-        enabled: false,
-    },
-
     cflags: [
         "-Wall",
         "-Werror",
diff --git a/libsync/OWNERS b/libsync/OWNERS
index dc61733..e75b15b 100644
--- a/libsync/OWNERS
+++ b/libsync/OWNERS
@@ -1,3 +1,3 @@
-ghackmann@google.com
+chrisforbes@google.com
+hridya@google.com
 jessehall@google.com
-marissaw@google.com
diff --git a/libsystem/OWNERS b/libsystem/OWNERS
index fdea804..4f800d4 100644
--- a/libsystem/OWNERS
+++ b/libsystem/OWNERS
@@ -1,7 +1,6 @@
 # graphics/composer
 adyabr@google.com
 lpy@google.com
-marissaw@google.com
 stoza@google.com
 vhau@google.com
 
diff --git a/libutils/include/utils/String16.h b/libutils/include/utils/String16.h
index 013705b..1a4b47e 100644
--- a/libutils/include/utils/String16.h
+++ b/libutils/include/utils/String16.h
@@ -187,7 +187,7 @@
 ANDROID_TRIVIAL_MOVE_TRAIT(String16)
 
 static inline std::ostream& operator<<(std::ostream& os, const String16& str) {
-    os << String8(str).c_str();
+    os << String8(str);
     return os;
 }
 
diff --git a/libutils/include/utils/String8.h b/libutils/include/utils/String8.h
index d0ad314..0bcb716 100644
--- a/libutils/include/utils/String8.h
+++ b/libutils/include/utils/String8.h
@@ -17,7 +17,8 @@
 #ifndef ANDROID_STRING8_H
 #define ANDROID_STRING8_H
 
-#include <string> // for std::string
+#include <iostream>
+#include <string>
 
 #include <utils/Errors.h>
 #include <utils/Unicode.h>
@@ -232,6 +233,11 @@
 // require any change to the underlying SharedBuffer contents or reference count.
 ANDROID_TRIVIAL_MOVE_TRAIT(String8)
 
+static inline std::ostream& operator<<(std::ostream& os, const String8& str) {
+    os << str.c_str();
+    return os;
+}
+
 // ---------------------------------------------------------------------------
 // No user servicable parts below.
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 91dd7a5..276cc1e 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -733,7 +733,7 @@
     mkdir /data/incremental 0771 system system encryption=Require
 
     # Wait for apexd to finish activating APEXes before starting more processes.
-    wait_for_prop apexd.status ready
+    wait_for_prop apexd.status activated
     perform_apex_config
 
     # Special-case /data/media/obb per b/64566063
@@ -748,7 +748,7 @@
     # Allow apexd to snapshot and restore device encrypted apex data in the case
     # of a rollback. This should be done immediately after DE_user data keys
     # are loaded. APEXes should not access this data until this has been
-    # completed.
+    # completed and apexd.status becomes "ready".
     exec_start apexd-snapshotde
 
     # Set SELinux security contexts on upgrade or policy update.