Snap for 5949240 from ecc9b1bd7f9a650f3b2b9c3b7ff3135409788301 to sdk-release

Change-Id: I34aca2afd9a7be781b3b269252e31544f2944e91
diff --git a/adb/Android.bp b/adb/Android.bp
index 2f9c8fc..170053b 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -422,14 +422,6 @@
         "liblog",
     ],
 
-    product_variables: {
-        debuggable: {
-            required: [
-                "remount",
-            ],
-        },
-    },
-
     target: {
         android: {
             srcs: [
@@ -437,7 +429,6 @@
                 "daemon/framebuffer_service.cpp",
                 "daemon/mdns.cpp",
                 "daemon/reboot_service.cpp",
-                "daemon/remount_service.cpp",
                 "daemon/restart_service.cpp",
                 "daemon/set_verity_enable_state_service.cpp",
             ],
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index e5a4917..9ebab74 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -248,6 +248,12 @@
         prop_port = android::base::GetProperty("persist.adb.tcp.port", "");
     }
 
+#if !defined(__ANDROID__)
+    if (prop_port.empty() && getenv("ADBD_PORT")) {
+        prop_port = getenv("ADBD_PORT");
+    }
+#endif
+
     int port;
     if (sscanf(prop_port.c_str(), "%d", &port) == 1 && port > 0) {
         D("using port=%d", port);
diff --git a/adb/daemon/remount_service.cpp b/adb/daemon/remount_service.cpp
deleted file mode 100644
index 6bd7855..0000000
--- a/adb/daemon/remount_service.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2008 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 <fcntl.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <string>
-
-#include "adb.h"
-#include "adb_io.h"
-#include "adb_unique_fd.h"
-
-static constexpr char kRemountCmd[] = "/system/bin/remount";
-
-static bool do_remount(int fd, const std::string& cmd) {
-    if (getuid() != 0) {
-        WriteFdExactly(fd, "Not running as root. Try \"adb root\" first.\n");
-        return false;
-    }
-
-    auto pid = fork();
-    if (pid < 0) {
-        WriteFdFmt(fd, "Failed to fork to %s: %s\n", kRemountCmd, strerror(errno));
-        return false;
-    }
-
-    if (pid == 0) {
-        // child side of the fork
-        dup2(fd, STDIN_FILENO);
-        dup2(fd, STDOUT_FILENO);
-        dup2(fd, STDERR_FILENO);
-
-        execl(kRemountCmd, kRemountCmd, cmd.empty() ? nullptr : cmd.c_str(), nullptr);
-        const char* msg = "failed to exec remount\n";
-        write(STDERR_FILENO, msg, strlen(msg));
-        _exit(errno);
-    }
-
-    int wstatus = 0;
-    auto ret = waitpid(pid, &wstatus, 0);
-
-    if (ret == -1) {
-        WriteFdFmt(fd, "Failed to wait for %s: %s\n", kRemountCmd, strerror(errno));
-        return false;
-    } else if (ret != pid) {
-        WriteFdFmt(fd, "pid %d and waitpid return %d do not match for %s\n",
-                   static_cast<int>(pid), static_cast<int>(ret), kRemountCmd);
-        return false;
-    }
-
-    if (WIFSIGNALED(wstatus)) {
-        WriteFdFmt(fd, "%s terminated with signal %s\n", kRemountCmd,
-                   strsignal(WTERMSIG(wstatus)));
-        return false;
-    }
-
-    if (!WIFEXITED(wstatus)) {
-        WriteFdFmt(fd, "%s stopped with status 0x%x\n", kRemountCmd, wstatus);
-        return false;
-    }
-
-    if (WEXITSTATUS(wstatus)) {
-        WriteFdFmt(fd, "%s exited with status %d\n", kRemountCmd, WEXITSTATUS(wstatus));
-        return false;
-    }
-
-    return true;
-}
-
-void remount_service(unique_fd fd, const std::string& cmd) {
-    do_remount(fd.get(), cmd);
-    // The remount command will print success or failure for us.
-}
diff --git a/adb/daemon/remount_service.h b/adb/daemon/remount_service.h
deleted file mode 100644
index 522a5da..0000000
--- a/adb/daemon/remount_service.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <string>
-
-#include "adb_unique_fd.h"
-
-#if defined(__ANDROID__)
-void remount_service(unique_fd, const std::string&);
-#endif
diff --git a/adb/daemon/services.cpp b/adb/daemon/services.cpp
index e6f4499..181a8c5 100644
--- a/adb/daemon/services.cpp
+++ b/adb/daemon/services.cpp
@@ -54,7 +54,6 @@
 #include "daemon/file_sync_service.h"
 #include "daemon/framebuffer_service.h"
 #include "daemon/reboot_service.h"
-#include "daemon/remount_service.h"
 #include "daemon/restart_service.h"
 #include "daemon/set_verity_enable_state_service.h"
 #include "daemon/shell_service.h"
@@ -251,9 +250,9 @@
     if (name.starts_with("framebuffer:")) {
         return create_service_thread("fb", framebuffer_service);
     } else if (android::base::ConsumePrefix(&name, "remount:")) {
-        std::string arg(name);
-        return create_service_thread("remount",
-                                     std::bind(remount_service, std::placeholders::_1, arg));
+        std::string cmd = "/system/bin/remount ";
+        cmd += name;
+        return StartSubprocess(cmd, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
     } else if (android::base::ConsumePrefix(&name, "reboot:")) {
         std::string arg(name);
         return create_service_thread("reboot",
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index 1a5b435..7e35a2f 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -195,7 +195,10 @@
     return false;
   }
 
-  InterceptRequest req = {.pid = pid, .dump_type = dump_type};
+  InterceptRequest req = {
+      .dump_type = dump_type,
+      .pid = pid,
+  };
   if (!set_timeout(sockfd)) {
     PLOG(ERROR) << "libdebugger_client: failed to set timeout";
     return false;
diff --git a/debuggerd/client/debuggerd_client_test.cpp b/debuggerd/client/debuggerd_client_test.cpp
index 9c2f0d6..2545cd6 100644
--- a/debuggerd/client/debuggerd_client_test.cpp
+++ b/debuggerd/client/debuggerd_client_test.cpp
@@ -73,15 +73,15 @@
   unique_fd pipe_read, pipe_write;
   ASSERT_TRUE(Pipe(&pipe_read, &pipe_write));
 
-  // 64 kB should be enough for everyone.
+  // 64 MiB should be enough for everyone.
   constexpr int PIPE_SIZE = 64 * 1024 * 1024;
   ASSERT_EQ(PIPE_SIZE, fcntl(pipe_read.get(), F_SETPIPE_SZ, PIPE_SIZE));
 
   // Wait for a bit to let the child spawn all of its threads.
-  std::this_thread::sleep_for(250ms);
+  std::this_thread::sleep_for(1s);
 
   ASSERT_TRUE(
-      debuggerd_trigger_dump(forkpid, kDebuggerdNativeBacktrace, 10000, std::move(pipe_write)));
+      debuggerd_trigger_dump(forkpid, kDebuggerdNativeBacktrace, 60000, std::move(pipe_write)));
   // Immediately kill the forked child, to make sure that the dump didn't return early.
   ASSERT_EQ(0, kill(forkpid, SIGKILL)) << strerror(errno);
 
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index c9a193c..99729dc 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -101,7 +101,10 @@
     FAIL() << "failed to contact tombstoned: " << strerror(errno);
   }
 
-  InterceptRequest req = {.pid = target_pid, .dump_type = intercept_type};
+  InterceptRequest req = {
+      .dump_type = intercept_type,
+      .pid = target_pid,
+  };
 
   unique_fd output_pipe_write;
   if (!Pipe(output_fd, &output_pipe_write)) {
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 598ea85..b90ca80 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -525,8 +525,8 @@
   log_signal_summary(info);
 
   debugger_thread_info thread_info = {
-      .pseudothread_tid = -1,
       .crashing_tid = __gettid(),
+      .pseudothread_tid = -1,
       .siginfo = info,
       .ucontext = context,
       .abort_msg = reinterpret_cast<uintptr_t>(abort_message),
diff --git a/debuggerd/libdebuggerd/test/tombstone_test.cpp b/debuggerd/libdebuggerd/test/tombstone_test.cpp
index 88c206f..9dea7ac 100644
--- a/debuggerd/libdebuggerd/test/tombstone_test.cpp
+++ b/debuggerd/libdebuggerd/test/tombstone_test.cpp
@@ -345,9 +345,9 @@
 
 TEST_F(TombstoneTest, dump_thread_info_uid) {
   dump_thread_info(&log_, ThreadInfo{.uid = 1,
-                                     .pid = 2,
                                      .tid = 3,
                                      .thread_name = "some_thread",
+                                     .pid = 2,
                                      .process_name = "some_process"});
   std::string expected = "pid: 2, tid: 3, name: some_thread  >>> some_process <<<\nuid: 1\n";
   ASSERT_STREQ(expected.c_str(), amfd_data_.c_str());
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index c1a8dae..2ff5243 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -686,13 +686,14 @@
         if (entries.empty()) {
             FstabEntry entry = {
                     .blk_device = partition,
+                    // .logical_partition_name is required to look up AVB Hashtree descriptors.
+                    .logical_partition_name = "system",
                     .mount_point = mount_point,
                     .fs_type = "ext4",
                     .flags = MS_RDONLY,
                     .fs_options = "barrier=1",
                     .avb_keys = kGsiKeys,
-                    // .logical_partition_name is required to look up AVB Hashtree descriptors.
-                    .logical_partition_name = "system"};
+            };
             entry.fs_mgr_flags.wait = true;
             entry.fs_mgr_flags.logical = true;
             entry.fs_mgr_flags.first_stage_mount = true;
diff --git a/fs_mgr/libfs_avb/tests/avb_util_test.cpp b/fs_mgr/libfs_avb/tests/avb_util_test.cpp
index 0d342d3..784eb9c 100644
--- a/fs_mgr/libfs_avb/tests/avb_util_test.cpp
+++ b/fs_mgr/libfs_avb/tests/avb_util_test.cpp
@@ -101,10 +101,10 @@
 TEST_F(AvbUtilTest, DeriveAvbPartitionName) {
     // The fstab_entry to test.
     FstabEntry fstab_entry = {
-        .blk_device = "/dev/block/dm-1",  // a dm-linear device (logical)
-        .mount_point = "/system",
-        .fs_type = "ext4",
-        .logical_partition_name = "system",
+            .blk_device = "/dev/block/dm-1",  // a dm-linear device (logical)
+            .logical_partition_name = "system",
+            .mount_point = "/system",
+            .fs_type = "ext4",
     };
 
     // Logical partitions.
diff --git a/fs_mgr/liblp/Android.bp b/fs_mgr/liblp/Android.bp
index a7c77b8..ea0fca8 100644
--- a/fs_mgr/liblp/Android.bp
+++ b/fs_mgr/liblp/Android.bp
@@ -100,6 +100,7 @@
     test_suites: ["vts-core"],
     auto_gen_config: true,
     test_min_api_level: 29,
+    require_root: true,
 }
 
 cc_test {
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index 7405039..54350a5 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -171,7 +171,8 @@
 std::unique_ptr<MetadataBuilder> MetadataBuilder::NewForUpdate(const IPartitionOpener& opener,
                                                                const std::string& source_partition,
                                                                uint32_t source_slot_number,
-                                                               uint32_t target_slot_number) {
+                                                               uint32_t target_slot_number,
+                                                               bool always_keep_source_slot) {
     auto metadata = ReadMetadata(opener, source_partition, source_slot_number);
     if (!metadata) {
         return nullptr;
@@ -189,7 +190,8 @@
         }
     }
 
-    if (IPropertyFetcher::GetInstance()->GetBoolProperty("ro.virtual_ab.enabled", false)) {
+    if (IPropertyFetcher::GetInstance()->GetBoolProperty("ro.virtual_ab.enabled", false) &&
+        !always_keep_source_slot) {
         if (!UpdateMetadataForInPlaceSnapshot(metadata.get(), source_slot_number,
                                               target_slot_number)) {
             return nullptr;
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index b43ccf0..1e9d636 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -209,10 +209,13 @@
     // metadata may not have the target slot's devices listed yet, in which
     // case, it is automatically upgraded to include all available block
     // devices.
+    // If |always_keep_source_slot| is set, on a Virtual A/B device, source slot
+    // partitions are kept. This is useful when applying a downgrade package.
     static std::unique_ptr<MetadataBuilder> NewForUpdate(const IPartitionOpener& opener,
                                                          const std::string& source_partition,
                                                          uint32_t source_slot_number,
-                                                         uint32_t target_slot_number);
+                                                         uint32_t target_slot_number,
+                                                         bool always_keep_source_slot = false);
 
     // Import an existing table for modification. If the table is not valid, for
     // example it contains duplicate partition names, then nullptr is returned.
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index 8cf0f3b..ba43949 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -28,6 +28,7 @@
         "liblp",
     ],
     static_libs: [
+        "libcutils",
         "libdm",
         "libfs_mgr",
         "libfstab",
@@ -56,6 +57,17 @@
     },
 }
 
+cc_defaults {
+    name: "libsnapshot_hal_deps",
+    cflags: [
+        "-DLIBSNAPSHOT_USE_HAL",
+    ],
+    shared_libs: [
+        "android.hardware.boot@1.0",
+        "android.hardware.boot@1.1",
+    ],
+}
+
 filegroup {
     name: "libsnapshot_sources",
     srcs: [
@@ -75,7 +87,10 @@
 
 cc_library_static {
     name: "libsnapshot",
-    defaults: ["libsnapshot_defaults"],
+    defaults: [
+        "libsnapshot_defaults",
+        "libsnapshot_hal_deps",
+    ],
     srcs: [":libsnapshot_sources"],
     whole_static_libs: [
         "libfiemap_binder",
@@ -83,7 +98,7 @@
 }
 
 cc_library_static {
-    name: "libsnapshot_nobinder",
+    name: "libsnapshot_init",
     defaults: ["libsnapshot_defaults"],
     srcs: [":libsnapshot_sources"],
     recovery_available: true,
@@ -92,6 +107,19 @@
     ],
 }
 
+cc_library_static {
+    name: "libsnapshot_nobinder",
+    defaults: [
+        "libsnapshot_defaults",
+        "libsnapshot_hal_deps",
+    ],
+    srcs: [":libsnapshot_sources"],
+    recovery_available: true,
+    whole_static_libs: [
+        "libfiemap_passthrough",
+    ],
+}
+
 cc_test {
     name: "libsnapshot_test",
     defaults: ["libsnapshot_defaults"],
@@ -103,11 +131,13 @@
     ],
     shared_libs: [
         "libbinder",
+        "libhidlbase",
         "libprotobuf-cpp-lite",
         "libutils",
     ],
     static_libs: [
-        "libcutils",
+        "android.hardware.boot@1.0",
+        "android.hardware.boot@1.1",
         "libcrypto_static",
         "libfs_mgr",
         "libgmock",
@@ -134,10 +164,14 @@
         "libsnapshot",
     ],
     shared_libs: [
+        "android.hardware.boot@1.0",
+        "android.hardware.boot@1.1",
         "libbase",
         "libbinder",
+        "libbinderthreadstate",
         "libext4_utils",
         "libfs_mgr",
+        "libhidlbase",
         "liblog",
         "liblp",
         "libprotobuf-cpp-lite",
diff --git a/fs_mgr/libsnapshot/dm_snapshot_internals.h b/fs_mgr/libsnapshot/dm_snapshot_internals.h
new file mode 100644
index 0000000..4903de1
--- /dev/null
+++ b/fs_mgr/libsnapshot/dm_snapshot_internals.h
@@ -0,0 +1,133 @@
+// Copyright (C) 2019 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 <stdint.h>
+
+#include <vector>
+
+namespace android {
+namespace snapshot {
+
+class DmSnapCowSizeCalculator {
+  public:
+    DmSnapCowSizeCalculator(unsigned int sector_bytes, unsigned int chunk_sectors)
+        : sector_bytes_(sector_bytes),
+          chunk_sectors_(chunk_sectors),
+          exceptions_per_chunk(chunk_sectors_ * sector_bytes_ / (64 * 2 / 8)) {}
+
+    void WriteByte(uint64_t address) { WriteSector(address / sector_bytes_); }
+    void WriteSector(uint64_t sector) { WriteChunk(sector / chunk_sectors_); }
+    void WriteChunk(uint64_t chunk_id) {
+        if (modified_chunks_.size() <= chunk_id) {
+            modified_chunks_.resize(chunk_id + 1, false);
+        }
+        modified_chunks_[chunk_id] = true;
+    }
+
+    uint64_t cow_size_bytes() const { return cow_size_sectors() * sector_bytes_; }
+    uint64_t cow_size_sectors() const { return cow_size_chunks() * chunk_sectors_; }
+
+    /*
+     * The COW device has a precise internal structure as follows:
+     *
+     * - header (1 chunk)
+     * - #0 map and chunks
+     *   - map (1 chunk)
+     *   - chunks addressable by previous map (exceptions_per_chunk)
+     * - #1 map and chunks
+     *   - map (1 chunk)
+     *   - chunks addressable by previous map (exceptions_per_chunk)
+     * ...
+     * - #n: map and chunks
+     *   - map (1 chunk)
+     *   - chunks addressable by previous map (exceptions_per_chunk)
+     * - 1 extra chunk
+     */
+    uint64_t cow_size_chunks() const {
+        uint64_t modified_chunks_count = 0;
+        uint64_t cow_chunks = 0;
+
+        for (const auto& c : modified_chunks_) {
+            if (c) {
+                ++modified_chunks_count;
+            }
+        }
+
+        /* disk header + padding = 1 chunk */
+        cow_chunks += 1;
+
+        /* snapshot modified chunks */
+        cow_chunks += modified_chunks_count;
+
+        /* snapshot chunks index metadata */
+        cow_chunks += 1 + modified_chunks_count / exceptions_per_chunk;
+
+        return cow_chunks;
+    }
+
+  private:
+    /*
+     * Size of each sector in bytes.
+     */
+    const uint64_t sector_bytes_;
+
+    /*
+     * Size of each chunk in sectors.
+     */
+    const uint64_t chunk_sectors_;
+
+    /*
+     * The COW device stores tables to map the modified chunks. Each table
+     * has the size of exactly 1 chunk.
+     * Each row of the table (also called exception in the kernel) contains two
+     * 64 bit indices to identify the corresponding chunk, and this 128 bit row
+     * size is a constant.
+     * The number of exceptions that each table can contain determines the
+     * number of data chunks that separate two consecutive tables. This value
+     * is then fundamental to compute the space overhead introduced by the
+     * tables in COW devices.
+     */
+    const uint64_t exceptions_per_chunk;
+
+    /*
+     * |modified_chunks_| is a container that keeps trace of the modified
+     * chunks.
+     * Multiple options were considered when choosing the most appropriate data
+     * structure for this container. Here follows a summary of why vector<bool>
+     * has been chosen, taking as a reference a snapshot partition of 4 GiB and
+     * chunk size of 4 KiB.
+     * - std::set<uint64_t> is very space-efficient for a small number of
+     *   operations, but if the whole snapshot is changed, it would need to
+     *   store
+     *     4 GiB / 4 KiB * (64 bit / 8) = 8 MiB
+     *   just for the data, plus the additional data overhead for the red-black
+     *   tree used for data sorting (if each rb-tree element stores 3 address
+     *   and the word-aligne color, the total size grows to 32 MiB).
+     * - std::bitset<N> is not a good fit because requires a priori knowledge,
+     *   at compile time, of the bitset size.
+     * - std::vector<bool> is a special case of vector, which uses a data
+     *   compression that allows reducing the space utilization of each element
+     *   to 1 bit. In detail, this data structure is composed of a resizable
+     *   array of words, each of them representing a bitmap. On a 64 bit
+     *   device, modifying the whole 4 GiB snapshot grows this container up to
+     *     4 * GiB / 4 KiB / 64 = 64 KiB
+     *   that, even if is the same space requirement to change a single byte at
+     *   the highest address of the snapshot, is a very affordable space
+     *   requirement.
+     */
+    std::vector<bool> modified_chunks_;
+};
+
+}  // namespace snapshot
+}  // namespace android
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 69f2895..fcaa73a 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -49,6 +49,16 @@
 class IPartitionOpener;
 }  // namespace fs_mgr
 
+// Forward declare IBootControl types since we cannot include only the headers
+// with Soong. Note: keep the enum width in sync.
+namespace hardware {
+namespace boot {
+namespace V1_1 {
+enum class MergeStatus : int32_t;
+}  // namespace V1_1
+}  // namespace boot
+}  // namespace hardware
+
 namespace snapshot {
 
 struct AutoDeleteCowImage;
@@ -94,6 +104,7 @@
     using LpMetadata = android::fs_mgr::LpMetadata;
     using MetadataBuilder = android::fs_mgr::MetadataBuilder;
     using DeltaArchiveManifest = chromeos_update_engine::DeltaArchiveManifest;
+    using MergeStatus = android::hardware::boot::V1_1::MergeStatus;
 
   public:
     // Dependency injection for testing.
@@ -107,6 +118,7 @@
         virtual std::string GetSuperDevice(uint32_t slot) const = 0;
         virtual const IPartitionOpener& GetPartitionOpener() const = 0;
         virtual bool IsOverlayfsSetup() const = 0;
+        virtual bool SetBootControlMergeStatus(MergeStatus status) = 0;
     };
 
     ~SnapshotManager();
@@ -208,6 +220,7 @@
     FRIEND_TEST(SnapshotTest, Merge);
     FRIEND_TEST(SnapshotTest, MergeCannotRemoveCow);
     FRIEND_TEST(SnapshotTest, NoMergeBeforeReboot);
+    FRIEND_TEST(SnapshotTest, UpdateBootControlHal);
     FRIEND_TEST(SnapshotUpdateTest, SnapshotStatusFileWithoutCow);
     friend class SnapshotTest;
     friend class SnapshotUpdateTest;
diff --git a/fs_mgr/libsnapshot/partition_cow_creator_test.cpp b/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
index feb3c2d..f683f5b 100644
--- a/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
+++ b/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
@@ -17,6 +17,7 @@
 #include <liblp/builder.h>
 #include <liblp/property_fetcher.h>
 
+#include "dm_snapshot_internals.h"
 #include "partition_cow_creator.h"
 #include "test_helpers.h"
 
@@ -32,17 +33,20 @@
 };
 
 TEST_F(PartitionCowCreatorTest, IntersectSelf) {
-    auto builder_a = MetadataBuilder::New(1024 * 1024, 1024, 2);
+    constexpr uint64_t initial_size = 1_MiB;
+    constexpr uint64_t final_size = 40_KiB;
+
+    auto builder_a = MetadataBuilder::New(initial_size, 1_KiB, 2);
     ASSERT_NE(builder_a, nullptr);
     auto system_a = builder_a->AddPartition("system_a", LP_PARTITION_ATTR_READONLY);
     ASSERT_NE(system_a, nullptr);
-    ASSERT_TRUE(builder_a->ResizePartition(system_a, 40 * 1024));
+    ASSERT_TRUE(builder_a->ResizePartition(system_a, final_size));
 
-    auto builder_b = MetadataBuilder::New(1024 * 1024, 1024, 2);
+    auto builder_b = MetadataBuilder::New(initial_size, 1_KiB, 2);
     ASSERT_NE(builder_b, nullptr);
     auto system_b = builder_b->AddPartition("system_b", LP_PARTITION_ATTR_READONLY);
     ASSERT_NE(system_b, nullptr);
-    ASSERT_TRUE(builder_b->ResizePartition(system_b, 40 * 1024));
+    ASSERT_TRUE(builder_b->ResizePartition(system_b, final_size));
 
     PartitionCowCreator creator{.target_metadata = builder_b.get(),
                                 .target_suffix = "_b",
@@ -51,8 +55,8 @@
                                 .current_suffix = "_a"};
     auto ret = creator.Run();
     ASSERT_TRUE(ret.has_value());
-    ASSERT_EQ(40 * 1024, ret->snapshot_status.device_size());
-    ASSERT_EQ(40 * 1024, ret->snapshot_status.snapshot_size());
+    ASSERT_EQ(final_size, ret->snapshot_status.device_size());
+    ASSERT_EQ(final_size, ret->snapshot_status.snapshot_size());
 }
 
 TEST_F(PartitionCowCreatorTest, Holes) {
@@ -64,7 +68,7 @@
 
     BlockDeviceInfo super_device("super", kSuperSize, 0, 0, 4_KiB);
     std::vector<BlockDeviceInfo> devices = {super_device};
-    auto source = MetadataBuilder::New(devices, "super", 1024, 2);
+    auto source = MetadataBuilder::New(devices, "super", 1_KiB, 2);
     auto system = source->AddPartition("system_a", 0);
     ASSERT_NE(nullptr, system);
     ASSERT_TRUE(source->ResizePartition(system, big_size));
@@ -96,5 +100,31 @@
     ASSERT_TRUE(ret.has_value());
 }
 
+TEST(DmSnapshotInternals, CowSizeCalculator) {
+    DmSnapCowSizeCalculator cc(512, 8);
+    unsigned long int b;
+
+    // Empty COW
+    ASSERT_EQ(cc.cow_size_sectors(), 16);
+
+    // First chunk written
+    for (b = 0; b < 4_KiB; ++b) {
+        cc.WriteByte(b);
+        ASSERT_EQ(cc.cow_size_sectors(), 24);
+    }
+
+    // Second chunk written
+    for (b = 4_KiB; b < 8_KiB; ++b) {
+        cc.WriteByte(b);
+        ASSERT_EQ(cc.cow_size_sectors(), 32);
+    }
+
+    // Leave a hole and write 5th chunk
+    for (b = 16_KiB; b < 20_KiB; ++b) {
+        cc.WriteByte(b);
+        ASSERT_EQ(cc.cow_size_sectors(), 40);
+    }
+}
+
 }  // namespace snapshot
 }  // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 5b758c9..48a94e4 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -29,6 +29,9 @@
 #include <android-base/parseint.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
+#ifdef LIBSNAPSHOT_USE_HAL
+#include <android/hardware/boot/1.1/IBootControl.h>
+#endif
 #include <ext4_utils/ext4_utils.h>
 #include <fs_mgr.h>
 #include <fs_mgr_dm_linear.h>
@@ -63,6 +66,7 @@
 using android::fs_mgr::LpMetadata;
 using android::fs_mgr::MetadataBuilder;
 using android::fs_mgr::SlotNumberForSlotSuffix;
+using android::hardware::boot::V1_1::MergeStatus;
 using chromeos_update_engine::DeltaArchiveManifest;
 using chromeos_update_engine::InstallOperation;
 template <typename T>
@@ -71,8 +75,6 @@
 using namespace std::chrono_literals;
 using namespace std::string_literals;
 
-// Unit is sectors, this is a 4K chunk.
-static constexpr uint32_t kSnapshotChunkSize = 8;
 static constexpr char kBootIndicatorPath[] = "/metadata/ota/snapshot-boot";
 
 class DeviceInfo final : public SnapshotManager::IDeviceInfo {
@@ -86,11 +88,39 @@
         return fs_mgr_get_super_partition_name(slot);
     }
     bool IsOverlayfsSetup() const override { return fs_mgr_overlayfs_is_setup(); }
+    bool SetBootControlMergeStatus(MergeStatus status) override;
 
   private:
     android::fs_mgr::PartitionOpener opener_;
+#ifdef LIBSNAPSHOT_USE_HAL
+    android::sp<android::hardware::boot::V1_1::IBootControl> boot_control_;
+#endif
 };
 
+bool DeviceInfo::SetBootControlMergeStatus([[maybe_unused]] MergeStatus status) {
+#ifdef LIBSNAPSHOT_USE_HAL
+    if (!boot_control_) {
+        auto hal = android::hardware::boot::V1_0::IBootControl::getService();
+        if (!hal) {
+            LOG(ERROR) << "Could not find IBootControl HAL";
+            return false;
+        }
+        boot_control_ = android::hardware::boot::V1_1::IBootControl::castFrom(hal);
+        if (!boot_control_) {
+            LOG(ERROR) << "Could not find IBootControl 1.1 HAL";
+            return false;
+        }
+    }
+    if (!boot_control_->setSnapshotMergeStatus(status)) {
+        LOG(ERROR) << "Unable to set the snapshot merge status";
+        return false;
+    }
+    return true;
+#else
+    return false;
+#endif
+}
+
 // Note: IImageManager is an incomplete type in the header, so the default
 // destructor doesn't work.
 SnapshotManager::~SnapshotManager() {}
@@ -1592,6 +1622,35 @@
         PLOG(ERROR) << "Could not write to state file";
         return false;
     }
+
+#ifdef LIBSNAPSHOT_USE_HAL
+    auto merge_status = MergeStatus::UNKNOWN;
+    switch (state) {
+        // The needs-reboot and completed cases imply that /data and /metadata
+        // can be safely wiped, so we don't report a merge status.
+        case UpdateState::None:
+        case UpdateState::MergeNeedsReboot:
+        case UpdateState::MergeCompleted:
+            merge_status = MergeStatus::NONE;
+            break;
+        case UpdateState::Initiated:
+        case UpdateState::Unverified:
+            merge_status = MergeStatus::SNAPSHOTTED;
+            break;
+        case UpdateState::Merging:
+        case UpdateState::MergeFailed:
+            merge_status = MergeStatus::MERGING;
+            break;
+        default:
+            // Note that Cancelled flows to here - it is never written, since
+            // it only communicates a transient state to the caller.
+            LOG(ERROR) << "Unexpected update status: " << state;
+            break;
+    }
+    if (!device_->SetBootControlMergeStatus(merge_status)) {
+        return false;
+    }
+#endif
     return true;
 }
 
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index fd7754e..a008294 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -203,9 +203,9 @@
                     .block_device = fake_super,
                     .metadata = metadata.get(),
                     .partition = &partition,
-                    .device_name = GetPartitionName(partition) + "-base",
                     .force_writable = true,
                     .timeout_ms = 10s,
+                    .device_name = GetPartitionName(partition) + "-base",
             };
             std::string ignore_path;
             if (!CreateLogicalPartition(params, &ignore_path)) {
@@ -617,6 +617,31 @@
     ASSERT_EQ(sm->GetUpdateState(), UpdateState::None);
 }
 
+TEST_F(SnapshotTest, UpdateBootControlHal) {
+    ASSERT_TRUE(AcquireLock());
+
+    ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::None));
+    ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
+
+    ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Initiated));
+    ASSERT_EQ(test_device->merge_status(), MergeStatus::SNAPSHOTTED);
+
+    ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Unverified));
+    ASSERT_EQ(test_device->merge_status(), MergeStatus::SNAPSHOTTED);
+
+    ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Merging));
+    ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
+
+    ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeNeedsReboot));
+    ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
+
+    ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeCompleted));
+    ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
+
+    ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeFailed));
+    ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
+}
+
 class SnapshotUpdateTest : public SnapshotTest {
   public:
     void SetUp() override {
diff --git a/fs_mgr/libsnapshot/test_helpers.cpp b/fs_mgr/libsnapshot/test_helpers.cpp
index 1a6a593..539c5c5 100644
--- a/fs_mgr/libsnapshot/test_helpers.cpp
+++ b/fs_mgr/libsnapshot/test_helpers.cpp
@@ -92,21 +92,14 @@
 }
 
 std::optional<std::string> GetHash(const std::string& path) {
-    unique_fd fd(open(path.c_str(), O_RDONLY));
-    char buf[4096];
+    std::string content;
+    if (!android::base::ReadFileToString(path, &content, true)) {
+        PLOG(ERROR) << "Cannot access " << path;
+        return std::nullopt;
+    }
     SHA256_CTX ctx;
     SHA256_Init(&ctx);
-    while (true) {
-        ssize_t n = TEMP_FAILURE_RETRY(read(fd.get(), buf, sizeof(buf)));
-        if (n < 0) {
-            PLOG(ERROR) << "Cannot read " << path;
-            return std::nullopt;
-        }
-        if (n == 0) {
-            break;
-        }
-        SHA256_Update(&ctx, buf, n);
-    }
+    SHA256_Update(&ctx, content.c_str(), content.size());
     uint8_t out[32];
     SHA256_Final(out, &ctx);
     return ToHexString(out, sizeof(out));
diff --git a/fs_mgr/libsnapshot/test_helpers.h b/fs_mgr/libsnapshot/test_helpers.h
index 769d21e..ea2c5b6 100644
--- a/fs_mgr/libsnapshot/test_helpers.h
+++ b/fs_mgr/libsnapshot/test_helpers.h
@@ -17,6 +17,7 @@
 #include <optional>
 #include <string>
 
+#include <android/hardware/boot/1.1/IBootControl.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <libfiemap/image_manager.h>
@@ -32,6 +33,7 @@
 using android::fs_mgr::IPropertyFetcher;
 using android::fs_mgr::MetadataBuilder;
 using android::fs_mgr::testing::MockPropertyFetcher;
+using android::hardware::boot::V1_1::MergeStatus;
 using chromeos_update_engine::DeltaArchiveManifest;
 using chromeos_update_engine::PartitionUpdate;
 using testing::_;
@@ -81,16 +83,22 @@
     const android::fs_mgr::IPartitionOpener& GetPartitionOpener() const override {
         return *opener_.get();
     }
+    bool SetBootControlMergeStatus(MergeStatus status) override {
+        merge_status_ = status;
+        return true;
+    }
     bool IsOverlayfsSetup() const override { return false; }
 
     void set_slot_suffix(const std::string& suffix) { slot_suffix_ = suffix; }
     void set_fake_super(const std::string& path) {
         opener_ = std::make_unique<TestPartitionOpener>(path);
     }
+    MergeStatus merge_status() const { return merge_status_; }
 
   private:
     std::string slot_suffix_ = "_a";
     std::unique_ptr<TestPartitionOpener> opener_;
+    MergeStatus merge_status_;
 };
 
 class SnapshotTestPropertyFetcher : public android::fs_mgr::testing::MockPropertyFetcher {
diff --git a/fs_mgr/libsnapshot/utility.h b/fs_mgr/libsnapshot/utility.h
index 75c694c..3051184 100644
--- a/fs_mgr/libsnapshot/utility.h
+++ b/fs_mgr/libsnapshot/utility.h
@@ -27,6 +27,9 @@
 namespace android {
 namespace snapshot {
 
+// Unit is sectors, this is a 4K chunk.
+static constexpr uint32_t kSnapshotChunkSize = 8;
+
 struct AutoDevice {
     virtual ~AutoDevice(){};
     void Release();
diff --git a/init/Android.bp b/init/Android.bp
index 9b2ddc0..ce5b12a 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -69,7 +69,7 @@
         "libprotobuf-cpp-lite",
         "libpropertyinfoserializer",
         "libpropertyinfoparser",
-        "libsnapshot_nobinder",
+        "libsnapshot_init",
     ],
     shared_libs: [
         "libbacktrace",
diff --git a/init/Android.mk b/init/Android.mk
index 8fc44da..4e4c002 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -114,7 +114,7 @@
     libmodprobe \
     libext2_uuid \
     libprotobuf-cpp-lite \
-    libsnapshot_nobinder \
+    libsnapshot_init \
 
 LOCAL_SANITIZE := signed-integer-overflow
 # First stage init is weird: it may start without stdout/stderr, and no /proc.
diff --git a/init/action_parser.cpp b/init/action_parser.cpp
index 9736824..a8e1e09 100644
--- a/init/action_parser.cpp
+++ b/init/action_parser.cpp
@@ -16,11 +16,14 @@
 
 #include "action_parser.h"
 
+#include <ctype.h>
+
 #include <android-base/properties.h>
 #include <android-base/strings.h>
 
 #if defined(__ANDROID__)
 #include "property_service.h"
+#include "selinux.h"
 #else
 #include "host_init_stubs.h"
 #endif
@@ -77,6 +80,17 @@
     return {};
 }
 
+Result<void> ValidateEventTrigger(const std::string& event_trigger) {
+    if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_R__) {
+        for (const char& c : event_trigger) {
+            if (c != '_' && c != '-' && !std::isalnum(c)) {
+                return Error() << "Illegal character '" << c << "' in '" << event_trigger << "'";
+            }
+        }
+    }
+    return {};
+}
+
 Result<void> ParseTriggers(const std::vector<std::string>& args, Subcontext* subcontext,
                            std::string* event_trigger,
                            std::map<std::string, std::string>* property_triggers) {
@@ -103,6 +117,9 @@
             if (!event_trigger->empty()) {
                 return Error() << "multiple event triggers are not allowed";
             }
+            if (auto result = ValidateEventTrigger(args[i]); !result) {
+                return result;
+            }
 
             *event_trigger = args[i];
         }
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 42211b2..2f2ead0 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -138,7 +138,14 @@
     if (!write_bootloader_message(options, &err)) {
         return Error() << "Failed to set bootloader message: " << err;
     }
-    property_set("sys.powerctl", "reboot,recovery");
+    // This function should only be reached from init and not from vendor_init, and we want to
+    // immediately trigger reboot instead of relaying through property_service.  Older devices may
+    // still have paths that reach here from vendor_init, so we keep the property_set as a fallback.
+    if (getpid() == 1) {
+        TriggerShutdown("reboot,recovery");
+    } else {
+        property_set("sys.powerctl", "reboot,recovery");
+    }
     return {};
 }
 
diff --git a/init/host_init_stubs.h b/init/host_init_stubs.h
index 71f78a5..5dd5cf1 100644
--- a/init/host_init_stubs.h
+++ b/init/host_init_stubs.h
@@ -35,7 +35,7 @@
 namespace init {
 
 // init.h
-inline void EnterShutdown(const std::string&) {
+inline void TriggerShutdown(const std::string&) {
     abort();
 }
 
diff --git a/init/init.cpp b/init/init.cpp
index ab6dbcf..f775d8f 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -179,7 +179,7 @@
     waiting_for_prop.reset();
 }
 
-void EnterShutdown(const std::string& command) {
+void TriggerShutdown(const std::string& command) {
     // We can't call HandlePowerctlMessage() directly in this function,
     // because it modifies the contents of the action queue, which can cause the action queue
     // to get into a bad state if this function is called from a command being executed by the
@@ -197,7 +197,7 @@
     // In non-thermal-shutdown case, 'shutdown' trigger will be fired to let device specific
     // commands to be executed.
     if (name == "sys.powerctl") {
-        EnterShutdown(value);
+        TriggerShutdown(value);
     }
 
     if (property_triggers_enabled) ActionManager::GetInstance().QueuePropertyChange(name, value);
diff --git a/init/init.h b/init/init.h
index c7918e7..d884a94 100644
--- a/init/init.h
+++ b/init/init.h
@@ -31,7 +31,7 @@
 Parser CreateParser(ActionManager& action_manager, ServiceList& service_list);
 Parser CreateServiceOnlyParser(ServiceList& service_list);
 
-void EnterShutdown(const std::string& command);
+void TriggerShutdown(const std::string& command);
 
 bool start_waiting_for_property(const char *name, const char *value);
 
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 315d584..9f63e4f 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -93,6 +93,26 @@
     EXPECT_TRUE(expect_true);
 }
 
+TEST(init, WrongEventTrigger) {
+    std::string init_script =
+            R"init(
+on boot:
+pass_test
+)init";
+
+    TemporaryFile tf;
+    ASSERT_TRUE(tf.fd != -1);
+    ASSERT_TRUE(android::base::WriteStringToFd(init_script, tf.fd));
+
+    ActionManager am;
+
+    Parser parser;
+    parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
+
+    ASSERT_TRUE(parser.ParseConfig(tf.path));
+    ASSERT_EQ(1u, parser.parse_error_count());
+}
+
 TEST(init, EventTriggerOrder) {
     std::string init_script =
         R"init(
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 4b892b7..d77b975 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -710,7 +710,7 @@
     auto guard = android::base::make_scope_guard([] {
         // Leave shutdown so that we can handle a full reboot.
         LeaveShutdown();
-        property_set("sys.powerctl", "reboot,abort-userspace-reboot");
+        TriggerShutdown("reboot,abort-userspace-reboot");
     });
     // Triggering userspace-reboot-requested will result in a bunch of set_prop
     // actions. We should make sure, that all of them are propagated before
diff --git a/init/service.cpp b/init/service.cpp
index a2db070..c8568a0 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -255,7 +255,7 @@
 
     if ((siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) && on_failure_reboot_target_) {
         LOG(ERROR) << "Service with 'reboot_on_failure' option failed, shutting down system.";
-        EnterShutdown(*on_failure_reboot_target_);
+        TriggerShutdown(*on_failure_reboot_target_);
     }
 
     if (flags_ & SVC_EXEC) UnSetExec();
@@ -335,7 +335,7 @@
 Result<void> Service::ExecStart() {
     auto reboot_on_failure = make_scope_guard([this] {
         if (on_failure_reboot_target_) {
-            EnterShutdown(*on_failure_reboot_target_);
+            TriggerShutdown(*on_failure_reboot_target_);
         }
     });
 
@@ -366,7 +366,7 @@
 Result<void> Service::Start() {
     auto reboot_on_failure = make_scope_guard([this] {
         if (on_failure_reboot_target_) {
-            EnterShutdown(*on_failure_reboot_target_);
+            TriggerShutdown(*on_failure_reboot_target_);
         }
     });
 
diff --git a/libcutils/sched_policy_test.cpp b/libcutils/sched_policy_test.cpp
index a321c90..b9e2832 100644
--- a/libcutils/sched_policy_test.cpp
+++ b/libcutils/sched_policy_test.cpp
@@ -107,6 +107,18 @@
 
 TEST(SchedPolicy, get_sched_policy_name) {
     EXPECT_STREQ("bg", get_sched_policy_name(SP_BACKGROUND));
-    EXPECT_STREQ("error", get_sched_policy_name(SchedPolicy(-2)));
-    EXPECT_STREQ("error", get_sched_policy_name(SP_CNT));
+    EXPECT_EQ(nullptr, get_sched_policy_name(SchedPolicy(-2)));
+    EXPECT_EQ(nullptr, get_sched_policy_name(SP_CNT));
+}
+
+TEST(SchedPolicy, get_cpuset_policy_profile_name) {
+    EXPECT_STREQ("CPUSET_SP_BACKGROUND", get_cpuset_policy_profile_name(SP_BACKGROUND));
+    EXPECT_EQ(nullptr, get_cpuset_policy_profile_name(SchedPolicy(-2)));
+    EXPECT_EQ(nullptr, get_cpuset_policy_profile_name(SP_CNT));
+}
+
+TEST(SchedPolicy, get_sched_policy_profile_name) {
+    EXPECT_STREQ("SCHED_SP_BACKGROUND", get_sched_policy_profile_name(SP_BACKGROUND));
+    EXPECT_EQ(nullptr, get_sched_policy_profile_name(SchedPolicy(-2)));
+    EXPECT_EQ(nullptr, get_sched_policy_profile_name(SP_CNT));
 }
diff --git a/liblog/include/android/log.h b/liblog/include/android/log.h
index 935590d..2e6210e 100644
--- a/liblog/include/android/log.h
+++ b/liblog/include/android/log.h
@@ -96,20 +96,14 @@
  * [printf(3)](http://man7.org/linux/man-pages/man3/printf.3.html).
  */
 int __android_log_print(int prio, const char* tag, const char* fmt, ...)
-#if defined(__GNUC__)
-    __attribute__((__format__(printf, 3, 4)))
-#endif
-    ;
+    __attribute__((__format__(printf, 3, 4)));
 
 /**
  * Equivalent to `__android_log_print`, but taking a `va_list`.
  * (If `__android_log_print` is like `printf`, this is like `vprintf`.)
  */
 int __android_log_vprint(int prio, const char* tag, const char* fmt, va_list ap)
-#if defined(__GNUC__)
-    __attribute__((__format__(printf, 3, 0)))
-#endif
-    ;
+    __attribute__((__format__(printf, 3, 0)));
 
 /**
  * Writes an assertion failure to the log (as `ANDROID_LOG_FATAL`) and to
@@ -127,13 +121,8 @@
  * including the source filename and line number more conveniently than this
  * function.
  */
-void __android_log_assert(const char* cond, const char* tag, const char* fmt,
-                          ...)
-#if defined(__GNUC__)
-    __attribute__((__noreturn__))
-    __attribute__((__format__(printf, 3, 4)))
-#endif
-    ;
+void __android_log_assert(const char* cond, const char* tag, const char* fmt, ...)
+    __attribute__((__noreturn__)) __attribute__((__format__(printf, 3, 4)));
 
 #ifndef log_id_t_defined
 #define log_id_t_defined
@@ -171,8 +160,7 @@
  *
  * Apps should use __android_log_write() instead.
  */
-int __android_log_buf_write(int bufID, int prio, const char* tag,
-                            const char* text);
+int __android_log_buf_write(int bufID, int prio, const char* tag, const char* text);
 
 /**
  * Writes a formatted string to log buffer `id`,
@@ -182,12 +170,8 @@
  *
  * Apps should use __android_log_print() instead.
  */
-int __android_log_buf_print(int bufID, int prio, const char* tag,
-                            const char* fmt, ...)
-#if defined(__GNUC__)
-    __attribute__((__format__(printf, 4, 5)))
-#endif
-    ;
+int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt, ...)
+    __attribute__((__format__(printf, 4, 5)));
 
 #ifdef __cplusplus
 }
diff --git a/liblog/include/log/event_tag_map.h b/liblog/include/log/event_tag_map.h
index 2687b3a..f7ec208 100644
--- a/liblog/include/log/event_tag_map.h
+++ b/liblog/include/log/event_tag_map.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include <stddef.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/liblog/include/log/log.h b/liblog/include/log/log.h
index 5928649..90d1e76 100644
--- a/liblog/include/log/log.h
+++ b/liblog/include/log/log.h
@@ -22,7 +22,6 @@
 #endif
 #include <stdint.h> /* uint16_t, int32_t */
 #include <stdio.h>
-#include <sys/types.h>
 #include <time.h>
 #include <unistd.h>
 
@@ -65,21 +64,6 @@
 #endif
 #endif
 
-/* --------------------------------------------------------------------- */
-
-/*
- * This file uses ", ## __VA_ARGS__" zero-argument token pasting to
- * work around issues with debug-only syntax errors in assertions
- * that are missing format strings.  See commit
- * 19299904343daf191267564fe32e6cd5c165cd42
- */
-#if defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
-#endif
-
-/* --------------------------------------------------------------------- */
-
 /*
  * Event logging.
  */
@@ -164,10 +148,6 @@
  */
 void __android_log_close(void);
 
-#if defined(__clang__)
-#pragma clang diagnostic pop
-#endif
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/liblog/include/log/log_event_list.h b/liblog/include/log/log_event_list.h
index 636d417..deadf20 100644
--- a/liblog/include/log/log_event_list.h
+++ b/liblog/include/log/log_event_list.h
@@ -36,16 +36,11 @@
 /*
  * The opaque context used to manipulate lists of events.
  */
-#ifndef __android_log_context_defined
-#define __android_log_context_defined
 typedef struct android_log_context_internal* android_log_context;
-#endif
 
 /*
  * Elements returned when reading a list of events.
  */
-#ifndef __android_log_list_element_defined
-#define __android_log_list_element_defined
 typedef struct {
   AndroidEventLogType type;
   uint16_t complete;
@@ -57,7 +52,6 @@
     float float32;
   } data;
 } android_log_list_element;
-#endif
 
 /*
  * Creates a context associated with an event tag to write elements to
@@ -104,8 +98,6 @@
 int android_log_destroy(android_log_context* ctx);
 
 #ifdef __cplusplus
-#ifndef __class_android_log_event_list_defined
-#define __class_android_log_event_list_defined
 /* android_log_list C++ helpers */
 extern "C++" {
 class android_log_event_list {
@@ -280,7 +272,6 @@
 };
 }
 #endif
-#endif
 
 #ifdef __cplusplus
 }
diff --git a/liblog/include/log/log_id.h b/liblog/include/log/log_id.h
index c052a50..4c6d809 100644
--- a/liblog/include/log/log_id.h
+++ b/liblog/include/log/log_id.h
@@ -45,12 +45,8 @@
  */
 int __android_log_buf_write(int bufID, int prio, const char* tag,
                             const char* text);
-int __android_log_buf_print(int bufID, int prio, const char* tag,
-                            const char* fmt, ...)
-#if defined(__GNUC__)
-    __attribute__((__format__(printf, 4, 5)))
-#endif
-    ;
+int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt, ...)
+    __attribute__((__format__(printf, 4, 5)));
 
 /*
  * log_id_t helpers
diff --git a/liblog/include/log/log_read.h b/liblog/include/log/log_read.h
index fdef306..2079e7a 100644
--- a/liblog/include/log/log_read.h
+++ b/liblog/include/log/log_read.h
@@ -53,8 +53,6 @@
 /*
  * The userspace structure for version 1 of the logger_entry ABI.
  */
-#ifndef __struct_logger_entry_defined
-#define __struct_logger_entry_defined
 struct logger_entry {
   uint16_t len;   /* length of the payload */
   uint16_t __pad; /* no matter what, we get 2 bytes of padding */
@@ -64,13 +62,10 @@
   int32_t nsec;   /* nanoseconds */
   char msg[0]; /* the entry's payload */
 };
-#endif
 
 /*
  * The userspace structure for version 2 of the logger_entry ABI.
  */
-#ifndef __struct_logger_entry_v2_defined
-#define __struct_logger_entry_v2_defined
 struct logger_entry_v2 {
   uint16_t len;      /* length of the payload */
   uint16_t hdr_size; /* sizeof(struct logger_entry_v2) */
@@ -81,13 +76,10 @@
   uint32_t euid;     /* effective UID of logger */
   char msg[0]; /* the entry's payload */
 } __attribute__((__packed__));
-#endif
 
 /*
  * The userspace structure for version 3 of the logger_entry ABI.
  */
-#ifndef __struct_logger_entry_v3_defined
-#define __struct_logger_entry_v3_defined
 struct logger_entry_v3 {
   uint16_t len;      /* length of the payload */
   uint16_t hdr_size; /* sizeof(struct logger_entry_v3) */
@@ -98,13 +90,10 @@
   uint32_t lid;      /* log id of the payload */
   char msg[0]; /* the entry's payload */
 } __attribute__((__packed__));
-#endif
 
 /*
  * The userspace structure for version 4 of the logger_entry ABI.
  */
-#ifndef __struct_logger_entry_v4_defined
-#define __struct_logger_entry_v4_defined
 struct logger_entry_v4 {
   uint16_t len;      /* length of the payload */
   uint16_t hdr_size; /* sizeof(struct logger_entry_v4) */
@@ -116,7 +105,6 @@
   uint32_t uid;      /* generating process's uid */
   char msg[0]; /* the entry's payload */
 };
-#endif
 #pragma clang diagnostic pop
 
 /*
@@ -133,8 +121,6 @@
  */
 #define LOGGER_ENTRY_MAX_LEN (5 * 1024)
 
-#ifndef __struct_log_msg_defined
-#define __struct_log_msg_defined
 struct log_msg {
   union {
     unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1];
@@ -191,7 +177,6 @@
   }
 #endif
 };
-#endif
 
 struct logger;
 
diff --git a/liblog/include/log/log_time.h b/liblog/include/log/log_time.h
index 09c9910..6b4458c 100644
--- a/liblog/include/log/log_time.h
+++ b/liblog/include/log/log_time.h
@@ -24,9 +24,6 @@
 #define US_PER_SEC 1000000ULL
 #define MS_PER_SEC 1000ULL
 
-#ifndef __struct_log_time_defined
-#define __struct_log_time_defined
-
 #define LOG_TIME_SEC(t) ((t)->tv_sec)
 /* next power of two after NS_PER_SEC */
 #define LOG_TIME_NSEC(t) ((t)->tv_nsec & (UINT32_MAX >> 2))
@@ -35,11 +32,6 @@
 
 extern "C" {
 
-/*
- * NB: we did NOT define a copy constructor. This will result in structure
- * no longer being compatible with pass-by-value which is desired
- * efficient behavior. Also, pass-by-reference breaks C/C++ ABI.
- */
 struct log_time {
  public:
   uint32_t tv_sec = 0; /* good to Feb 5 2106 */
@@ -169,5 +161,3 @@
 } __attribute__((__packed__)) log_time;
 
 #endif /* __cplusplus */
-
-#endif /* __struct_log_time_defined */
diff --git a/liblog/include/log/logprint.h b/liblog/include/log/logprint.h
index 8f4b187..7dfd914 100644
--- a/liblog/include/log/logprint.h
+++ b/liblog/include/log/logprint.h
@@ -16,7 +16,8 @@
 
 #pragma once
 
-#include <pthread.h>
+#include <stdint.h>
+#include <sys/types.h>
 
 #include <android/log.h>
 #include <log/event_tag_map.h>
diff --git a/liblog/pmsg_reader.cpp b/liblog/pmsg_reader.cpp
index 9c5bc95..ce923f3 100644
--- a/liblog/pmsg_reader.cpp
+++ b/liblog/pmsg_reader.cpp
@@ -62,58 +62,9 @@
   return -EBADF;
 }
 
-/* Determine the credentials of the caller */
-static bool uid_has_log_permission(uid_t uid) {
-  return (uid == AID_SYSTEM) || (uid == AID_LOG) || (uid == AID_ROOT) || (uid == AID_LOGD);
-}
-
-static uid_t get_best_effective_uid() {
-  uid_t euid;
-  uid_t uid;
-  gid_t gid;
-  ssize_t i;
-  static uid_t last_uid = (uid_t)-1;
-
-  if (last_uid != (uid_t)-1) {
-    return last_uid;
-  }
-  uid = __android_log_uid();
-  if (uid_has_log_permission(uid)) {
-    return last_uid = uid;
-  }
-  euid = geteuid();
-  if (uid_has_log_permission(euid)) {
-    return last_uid = euid;
-  }
-  gid = getgid();
-  if (uid_has_log_permission(gid)) {
-    return last_uid = gid;
-  }
-  gid = getegid();
-  if (uid_has_log_permission(gid)) {
-    return last_uid = gid;
-  }
-  i = getgroups((size_t)0, NULL);
-  if (i > 0) {
-    gid_t list[i];
-
-    getgroups(i, list);
-    while (--i >= 0) {
-      if (uid_has_log_permission(list[i])) {
-        return last_uid = list[i];
-      }
-    }
-  }
-  return last_uid = uid;
-}
-
 static int pmsgClear(struct android_log_logger* logger __unused,
                      struct android_log_transport_context* transp __unused) {
-  if (uid_has_log_permission(get_best_effective_uid())) {
-    return unlink("/sys/fs/pstore/pmsg-ramoops-0");
-  }
-  errno = EPERM;
-  return -1;
+  return unlink("/sys/fs/pstore/pmsg-ramoops-0");
 }
 
 /*
@@ -128,14 +79,12 @@
                     struct android_log_transport_context* transp, struct log_msg* log_msg) {
   ssize_t ret;
   off_t current, next;
-  uid_t uid;
   struct __attribute__((__packed__)) {
     android_pmsg_log_header_t p;
     android_log_header_t l;
     uint8_t prio;
   } buf;
   static uint8_t preread_count;
-  bool is_system;
 
   memset(log_msg, 0, sizeof(*log_msg));
 
@@ -195,37 +144,30 @@
           ((logger_list->start.tv_sec != buf.l.realtime.tv_sec) ||
            (logger_list->start.tv_nsec <= buf.l.realtime.tv_nsec)))) &&
         (!logger_list->pid || (logger_list->pid == buf.p.pid))) {
-      uid = get_best_effective_uid();
-      is_system = uid_has_log_permission(uid);
-      if (is_system || (uid == buf.p.uid)) {
-        char* msg = is_system ? log_msg->entry_v4.msg : log_msg->entry_v3.msg;
-        *msg = buf.prio;
-        fd = atomic_load(&transp->context.fd);
-        if (fd <= 0) {
-          return -EBADF;
-        }
-        ret = TEMP_FAILURE_RETRY(read(fd, msg + sizeof(buf.prio), buf.p.len - sizeof(buf)));
-        if (ret < 0) {
-          return -errno;
-        }
-        if (ret != (ssize_t)(buf.p.len - sizeof(buf))) {
-          return -EIO;
-        }
-
-        log_msg->entry_v4.len = buf.p.len - sizeof(buf) + sizeof(buf.prio);
-        log_msg->entry_v4.hdr_size =
-            is_system ? sizeof(log_msg->entry_v4) : sizeof(log_msg->entry_v3);
-        log_msg->entry_v4.pid = buf.p.pid;
-        log_msg->entry_v4.tid = buf.l.tid;
-        log_msg->entry_v4.sec = buf.l.realtime.tv_sec;
-        log_msg->entry_v4.nsec = buf.l.realtime.tv_nsec;
-        log_msg->entry_v4.lid = buf.l.id;
-        if (is_system) {
-          log_msg->entry_v4.uid = buf.p.uid;
-        }
-
-        return ret + sizeof(buf.prio) + log_msg->entry_v4.hdr_size;
+      char* msg = log_msg->entry_v4.msg;
+      *msg = buf.prio;
+      fd = atomic_load(&transp->context.fd);
+      if (fd <= 0) {
+        return -EBADF;
       }
+      ret = TEMP_FAILURE_RETRY(read(fd, msg + sizeof(buf.prio), buf.p.len - sizeof(buf)));
+      if (ret < 0) {
+        return -errno;
+      }
+      if (ret != (ssize_t)(buf.p.len - sizeof(buf))) {
+        return -EIO;
+      }
+
+      log_msg->entry_v4.len = buf.p.len - sizeof(buf) + sizeof(buf.prio);
+      log_msg->entry_v4.hdr_size = sizeof(log_msg->entry_v4);
+      log_msg->entry_v4.pid = buf.p.pid;
+      log_msg->entry_v4.tid = buf.l.tid;
+      log_msg->entry_v4.sec = buf.l.realtime.tv_sec;
+      log_msg->entry_v4.nsec = buf.l.realtime.tv_nsec;
+      log_msg->entry_v4.lid = buf.l.id;
+      log_msg->entry_v4.uid = buf.p.uid;
+
+      return ret + sizeof(buf.prio) + log_msg->entry_v4.hdr_size;
     }
 
     fd = atomic_load(&transp->context.fd);
@@ -273,13 +215,7 @@
   struct android_log_transport_context transp;
   struct content {
     struct listnode node;
-    union {
-      struct logger_entry_v4 entry;
-      struct logger_entry_v4 entry_v4;
-      struct logger_entry_v3 entry_v3;
-      struct logger_entry_v2 entry_v2;
-      struct logger_entry entry_v1;
-    };
+    struct logger_entry_v4 entry;
   } * content;
   struct names {
     struct listnode node;
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index 4642b9b..56892a2 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -17,6 +17,7 @@
 #include <fcntl.h>
 #include <inttypes.h>
 #include <poll.h>
+#include <sched.h>
 #include <sys/socket.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index cfcfd99..94c4fbb 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -27,10 +27,12 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <memory>
 #include <string>
 
 #include <android-base/file.h>
 #include <android-base/macros.h>
+#include <android-base/scopeguard.h>
 #include <android-base/stringprintf.h>
 #ifdef __ANDROID__  // includes sys/properties.h which does not exist outside
 #include <cutils/properties.h>
@@ -42,6 +44,8 @@
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
 
+using android::base::make_scope_guard;
+
 // #define ENABLE_FLAKY_TESTS
 
 // enhanced version of LOG_FAILURE_RETRY to add support for EAGAIN and
@@ -58,6 +62,80 @@
     _rc;                                                                 \
   })
 
+// std::unique_ptr doesn't let you provide a pointer to a deleter (android_logger_list_close()) if
+// the type (struct logger_list) is an incomplete type, so we create ListCloser instead.
+struct ListCloser {
+  void operator()(struct logger_list* list) { android_logger_list_close(list); }
+};
+
+// This function is meant to be used for most log tests, it does the following:
+// 1) Open the log_buffer with a blocking reader
+// 2) Write the messages via write_messages
+// 3) Set an alarm for 2 seconds as a timeout
+// 4) Read until check_message returns true, which should be used to indicate the target message
+//    is found
+// 5) Open log_buffer with a non_blocking reader and dump all messages
+// 6) Count the number of times check_messages returns true for these messages and assert it's
+//    only 1.
+template <typename FWrite, typename FCheck>
+static void RunLogTests(log_id_t log_buffer, FWrite write_messages, FCheck check_message) {
+  pid_t pid = getpid();
+
+  auto logger_list = std::unique_ptr<struct logger_list, ListCloser>{
+      android_logger_list_open(log_buffer, ANDROID_LOG_RDONLY, 1000, pid)};
+  ASSERT_TRUE(logger_list);
+
+  write_messages();
+
+  alarm(2);
+  auto alarm_guard = android::base::make_scope_guard([] { alarm(0); });
+  bool found = false;
+  while (!found) {
+    log_msg log_msg;
+    ASSERT_GT(android_logger_list_read(logger_list.get(), &log_msg), 0);
+
+    ASSERT_EQ(log_buffer, log_msg.id());
+    ASSERT_EQ(pid, log_msg.entry.pid);
+
+    // TODO: Should this be an assert?
+    if (log_msg.msg() == nullptr) {
+      continue;
+    }
+
+    check_message(log_msg, &found);
+  }
+
+  auto logger_list_non_block = std::unique_ptr<struct logger_list, ListCloser>{
+      android_logger_list_open(log_buffer, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)};
+  ASSERT_TRUE(logger_list_non_block);
+
+  size_t count = 0;
+  while (true) {
+    log_msg log_msg;
+    auto ret = android_logger_list_read(logger_list_non_block.get(), &log_msg);
+    if (ret == -EAGAIN) {
+      break;
+    }
+    ASSERT_GT(ret, 0);
+
+    ASSERT_EQ(log_buffer, log_msg.id());
+    ASSERT_EQ(pid, log_msg.entry.pid);
+
+    // TODO: Should this be an assert?
+    if (log_msg.msg() == nullptr) {
+      continue;
+    }
+
+    found = false;
+    check_message(log_msg, &found);
+    if (found) {
+      ++count;
+    }
+  }
+
+  EXPECT_EQ(1U, count);
+}
+
 TEST(liblog, __android_log_btwrite) {
   int intBuf = 0xDEADBEEF;
   EXPECT_LT(0,
@@ -65,14 +143,11 @@
   long long longBuf = 0xDEADBEEFA55A5AA5;
   EXPECT_LT(
       0, __android_log_btwrite(0, EVENT_TYPE_LONG, &longBuf, sizeof(longBuf)));
-  usleep(1000);
   char Buf[] = "\20\0\0\0DeAdBeEfA55a5aA5";
   EXPECT_LT(0,
             __android_log_btwrite(0, EVENT_TYPE_STRING, Buf, sizeof(Buf) - 1));
-  usleep(1000);
 }
 
-#ifdef ENABLE_FLAKY_TESTS
 #if defined(__ANDROID__)
 static std::string popenToString(const std::string& command) {
   std::string ret;
@@ -141,81 +216,63 @@
 
 static bool tested__android_log_close;
 #endif
-#endif  // ENABLE_FLAKY_TESTS
 
 TEST(liblog, __android_log_btwrite__android_logger_list_read) {
 #ifdef __ANDROID__
-  struct logger_list* logger_list;
-
-  pid_t pid = getpid();
-
-  ASSERT_TRUE(NULL !=
-              (logger_list = android_logger_list_open(
-                   LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-                   1000, pid)));
-
   log_time ts(CLOCK_MONOTONIC);
-  EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
-#ifdef ENABLE_FLAKY_TESTS
-  // Check that we can close and reopen the logger
-  bool logdwActiveAfter__android_log_btwrite;
-  if (getuid() == AID_ROOT) {
-    tested__android_log_close = true;
-#ifndef NO_PSTORE
-    bool pmsgActiveAfter__android_log_btwrite = isPmsgActive();
-    EXPECT_TRUE(pmsgActiveAfter__android_log_btwrite);
-#endif /* NO_PSTORE */
-    logdwActiveAfter__android_log_btwrite = isLogdwActive();
-    EXPECT_TRUE(logdwActiveAfter__android_log_btwrite);
-  } else if (!tested__android_log_close) {
-    fprintf(stderr, "WARNING: can not test __android_log_close()\n");
-  }
-  __android_log_close();
-  if (getuid() == AID_ROOT) {
-#ifndef NO_PSTORE
-    bool pmsgActiveAfter__android_log_close = isPmsgActive();
-    EXPECT_FALSE(pmsgActiveAfter__android_log_close);
-#endif /* NO_PSTORE */
-    bool logdwActiveAfter__android_log_close = isLogdwActive();
-    EXPECT_FALSE(logdwActiveAfter__android_log_close);
-  }
-#endif  // ENABLE_FLAKY_TESTS
+  log_time ts1(ts);
 
-  log_time ts1(CLOCK_MONOTONIC);
-  EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1)));
-#ifdef ENABLE_FLAKY_TESTS
-  if (getuid() == AID_ROOT) {
+  auto write_function = [&] {
+    EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
+    // Check that we can close and reopen the logger
+    bool logdwActiveAfter__android_log_btwrite;
+    if (getuid() == AID_ROOT) {
+      tested__android_log_close = true;
 #ifndef NO_PSTORE
-    bool pmsgActiveAfter__android_log_btwrite = isPmsgActive();
-    EXPECT_TRUE(pmsgActiveAfter__android_log_btwrite);
+      bool pmsgActiveAfter__android_log_btwrite = isPmsgActive();
+      EXPECT_TRUE(pmsgActiveAfter__android_log_btwrite);
 #endif /* NO_PSTORE */
-    logdwActiveAfter__android_log_btwrite = isLogdwActive();
-    EXPECT_TRUE(logdwActiveAfter__android_log_btwrite);
-  }
-#endif  // ENABLE_FLAKY_TESTS
-  usleep(1000000);
+      logdwActiveAfter__android_log_btwrite = isLogdwActive();
+      EXPECT_TRUE(logdwActiveAfter__android_log_btwrite);
+    } else if (!tested__android_log_close) {
+      fprintf(stderr, "WARNING: can not test __android_log_close()\n");
+    }
+    __android_log_close();
+    if (getuid() == AID_ROOT) {
+#ifndef NO_PSTORE
+      bool pmsgActiveAfter__android_log_close = isPmsgActive();
+      EXPECT_FALSE(pmsgActiveAfter__android_log_close);
+#endif /* NO_PSTORE */
+      bool logdwActiveAfter__android_log_close = isLogdwActive();
+      EXPECT_FALSE(logdwActiveAfter__android_log_close);
+    }
+
+    ts1 = log_time(CLOCK_MONOTONIC);
+    EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1)));
+    if (getuid() == AID_ROOT) {
+#ifndef NO_PSTORE
+      bool pmsgActiveAfter__android_log_btwrite = isPmsgActive();
+      EXPECT_TRUE(pmsgActiveAfter__android_log_btwrite);
+#endif /* NO_PSTORE */
+      logdwActiveAfter__android_log_btwrite = isLogdwActive();
+      EXPECT_TRUE(logdwActiveAfter__android_log_btwrite);
+    }
+  };
 
   int count = 0;
   int second_count = 0;
 
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
-    }
-
-    EXPECT_EQ(log_msg.entry.pid, pid);
-
+  auto check_function = [&](log_msg log_msg, bool* found) {
     if ((log_msg.entry.len != sizeof(android_log_event_long_t)) ||
         (log_msg.id() != LOG_ID_EVENTS)) {
-      continue;
+      return;
     }
 
     android_log_event_long_t* eventData;
     eventData = reinterpret_cast<android_log_event_long_t*>(log_msg.msg());
 
     if (!eventData || (eventData->payload.type != EVENT_TYPE_LONG)) {
-      continue;
+      return;
     }
 
     log_time tx(reinterpret_cast<char*>(&eventData->payload.data));
@@ -224,12 +281,50 @@
     } else if (ts1 == tx) {
       ++second_count;
     }
-  }
 
-  EXPECT_EQ(1, count);
-  EXPECT_EQ(1, second_count);
+    if (count == 1 && second_count == 1) {
+      count = 0;
+      second_count = 0;
+      *found = true;
+    }
+  };
 
-  android_logger_list_close(logger_list);
+  RunLogTests(LOG_ID_EVENTS, write_function, check_function);
+
+#else
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+}
+
+TEST(liblog, __android_log_write__android_logger_list_read) {
+#ifdef __ANDROID__
+  pid_t pid = getpid();
+
+  struct timespec ts;
+  clock_gettime(CLOCK_MONOTONIC, &ts);
+  std::string buf = android::base::StringPrintf("pid=%u ts=%ld.%09ld", pid, ts.tv_sec, ts.tv_nsec);
+  static const char tag[] = "liblog.__android_log_write__android_logger_list_read";
+  static const char prio = ANDROID_LOG_DEBUG;
+
+  std::string expected_message =
+      std::string(&prio, sizeof(prio)) + tag + std::string("", 1) + buf + std::string("", 1);
+
+  auto write_function = [&] { ASSERT_LT(0, __android_log_write(prio, tag, buf.c_str())); };
+
+  auto check_function = [&](log_msg log_msg, bool* found) {
+    if (log_msg.entry.len != expected_message.length()) {
+      return;
+    }
+
+    if (expected_message != std::string(log_msg.msg(), log_msg.entry.len)) {
+      return;
+    }
+
+    *found = true;
+  };
+
+  RunLogTests(LOG_ID_MAIN, write_function, check_function);
+
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
@@ -237,18 +332,10 @@
 
 static void bswrite_test(const char* message) {
 #ifdef __ANDROID__
-  struct logger_list* logger_list;
-
   pid_t pid = getpid();
 
-  ASSERT_TRUE(NULL !=
-              (logger_list = android_logger_list_open(
-                   LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-                   1000, pid)));
-
   log_time ts(android_log_clockid());
 
-  EXPECT_LT(0, __android_log_bswrite(0, message));
   size_t num_lines = 1, size = 0, length = 0, total = 0;
   const char* cp = message;
   while (*cp) {
@@ -270,36 +357,25 @@
     ++cp;
     ++total;
   }
-  usleep(1000000);
 
-  int count = 0;
+  auto write_function = [&] { EXPECT_LT(0, __android_log_bswrite(0, message)); };
 
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
-    }
-
-    EXPECT_EQ(log_msg.entry.pid, pid);
-
-    if ((log_msg.entry.sec < (ts.tv_sec - 1)) ||
-        ((ts.tv_sec + 1) < log_msg.entry.sec) ||
-        ((size_t)log_msg.entry.len !=
-         (sizeof(android_log_event_string_t) + length)) ||
-        (log_msg.id() != LOG_ID_EVENTS)) {
-      continue;
+  auto check_function = [&](log_msg log_msg, bool* found) {
+    if ((size_t)log_msg.entry.len != (sizeof(android_log_event_string_t) + length) ||
+        log_msg.id() != LOG_ID_EVENTS) {
+      return;
     }
 
     android_log_event_string_t* eventData;
     eventData = reinterpret_cast<android_log_event_string_t*>(log_msg.msg());
 
     if (!eventData || (eventData->type != EVENT_TYPE_STRING)) {
-      continue;
+      return;
     }
 
     size_t len = eventData->length;
     if (len == total) {
-      ++count;
+      *found = true;
 
       AndroidLogFormat* logformat = android_log_format_new();
       EXPECT_TRUE(NULL != logformat);
@@ -326,11 +402,10 @@
       }
       android_log_format_free(logformat);
     }
-  }
+  };
 
-  EXPECT_EQ(1, count);
+  RunLogTests(LOG_ID_EVENTS, write_function, check_function);
 
-  android_logger_list_close(logger_list);
 #else
   message = NULL;
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -359,20 +434,14 @@
 
 static void buf_write_test(const char* message) {
 #ifdef __ANDROID__
-  struct logger_list* logger_list;
-
   pid_t pid = getpid();
 
-  ASSERT_TRUE(
-      NULL !=
-      (logger_list = android_logger_list_open(
-           LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
   static const char tag[] = "TEST__android_log_buf_write";
   log_time ts(android_log_clockid());
 
-  EXPECT_LT(
-      0, __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO, tag, message));
+  auto write_function = [&] {
+    EXPECT_LT(0, __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO, tag, message));
+  };
   size_t num_lines = 1, size = 0, length = 0;
   const char* cp = message;
   while (*cp) {
@@ -389,26 +458,13 @@
     }
     ++cp;
   }
-  usleep(1000000);
 
-  int count = 0;
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
+  auto check_function = [&](log_msg log_msg, bool* found) {
+    if ((size_t)log_msg.entry.len != (sizeof(tag) + length + 2) || log_msg.id() != LOG_ID_MAIN) {
+      return;
     }
 
-    ASSERT_EQ(log_msg.entry.pid, pid);
-
-    if ((log_msg.entry.sec < (ts.tv_sec - 1)) ||
-        ((ts.tv_sec + 1) < log_msg.entry.sec) ||
-        ((size_t)log_msg.entry.len != (sizeof(tag) + length + 2)) ||
-        (log_msg.id() != LOG_ID_MAIN)) {
-      continue;
-    }
-
-    ++count;
+    *found = true;
 
     AndroidLogFormat* logformat = android_log_format_new();
     EXPECT_TRUE(NULL != logformat);
@@ -425,11 +481,10 @@
                 android_log_printLogLine(logformat, fileno(stderr), &entry));
     }
     android_log_format_free(logformat);
-  }
+  };
 
-  EXPECT_EQ(1, count);
+  RunLogTests(LOG_ID_MAIN, write_function, check_function);
 
-  android_logger_list_close(logger_list);
 #else
   message = NULL;
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -892,7 +947,6 @@
 when you depart from me, sorrow abides and happiness\n\
 takes his leave.";
 
-#ifdef ENABLE_FLAKY_TESTS
 TEST(liblog, max_payload) {
 #ifdef __ANDROID__
   static const char max_payload_tag[] = "TEST_max_payload_and_longish_tag_XXXX";
@@ -903,32 +957,17 @@
   memcpy(tag, max_payload_tag, sizeof(tag));
   snprintf(tag + sizeof(tag) - 5, 5, "%04X", pid & 0xFFFF);
 
-  LOG_FAILURE_RETRY(__android_log_buf_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO,
-                                            tag, max_payload_buf));
-  sleep(2);
+  auto write_function = [&] {
+    LOG_FAILURE_RETRY(
+        __android_log_buf_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO, tag, max_payload_buf));
+  };
 
-  struct logger_list* logger_list;
-
-  ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
-                           LOG_ID_SYSTEM, ANDROID_LOG_RDONLY, 100, 0)));
-
-  bool matches = false;
   ssize_t max_len = 0;
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
-    }
-
-    if ((log_msg.entry.pid != pid) || (log_msg.id() != LOG_ID_SYSTEM)) {
-      continue;
-    }
-
+  auto check_function = [&](log_msg log_msg, bool* found) {
     char* data = log_msg.msg();
 
     if (!data || strcmp(++data, tag)) {
-      continue;
+      return;
     }
 
     data += strlen(data) + 1;
@@ -945,57 +984,31 @@
     }
 
     if (max_len > 512) {
-      matches = true;
-      break;
+      *found = true;
     }
-  }
+  };
 
-  android_logger_list_close(logger_list);
-
-  EXPECT_EQ(true, matches);
+  RunLogTests(LOG_ID_SYSTEM, write_function, check_function);
 
   EXPECT_LE(SIZEOF_MAX_PAYLOAD_BUF, static_cast<size_t>(max_len));
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif  // ENABLE_FLAKY_TESTS
 
 TEST(liblog, __android_log_buf_print__maxtag) {
 #ifdef __ANDROID__
-  struct logger_list* logger_list;
+  auto write_function = [&] {
+    EXPECT_LT(0, __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_INFO, max_payload_buf,
+                                         max_payload_buf));
+  };
 
-  pid_t pid = getpid();
-
-  ASSERT_TRUE(
-      NULL !=
-      (logger_list = android_logger_list_open(
-           LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
-  log_time ts(android_log_clockid());
-
-  EXPECT_LT(0, __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_INFO,
-                                       max_payload_buf, max_payload_buf));
-  usleep(1000000);
-
-  int count = 0;
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
+  auto check_function = [&](log_msg log_msg, bool* found) {
+    if ((size_t)log_msg.entry.len < LOGGER_ENTRY_MAX_PAYLOAD) {
+      return;
     }
 
-    ASSERT_EQ(log_msg.entry.pid, pid);
-
-    if ((log_msg.entry.sec < (ts.tv_sec - 1)) ||
-        ((ts.tv_sec + 1) < log_msg.entry.sec) ||
-        ((size_t)log_msg.entry.len < LOGGER_ENTRY_MAX_PAYLOAD) ||
-        (log_msg.id() != LOG_ID_MAIN)) {
-      continue;
-    }
-
-    ++count;
+    *found = true;
 
     AndroidLogFormat* logformat = android_log_format_new();
     EXPECT_TRUE(NULL != logformat);
@@ -1013,16 +1026,18 @@
       EXPECT_GT(LOGGER_ENTRY_MAX_PAYLOAD * 13 / 8, printLogLine);
     }
     android_log_format_free(logformat);
-  }
+  };
 
-  EXPECT_EQ(1, count);
+  RunLogTests(LOG_ID_MAIN, write_function, check_function);
 
-  android_logger_list_close(logger_list);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 
+// TODO: This test is tautological. android_logger_list_read() calls recv() with
+// LOGGER_ENTRY_MAX_PAYLOAD as its size argument, so it's not possible for this test to read a
+// payload larger than that size.
 TEST(liblog, too_big_payload) {
 #ifdef __ANDROID__
   pid_t pid = getpid();
@@ -1032,32 +1047,18 @@
   snprintf(tag + sizeof(tag) - 5, 5, "%04X", pid & 0xFFFF);
 
   std::string longString(3266519, 'x');
+  ssize_t ret;
 
-  ssize_t ret = LOG_FAILURE_RETRY(__android_log_buf_write(
-      LOG_ID_SYSTEM, ANDROID_LOG_INFO, tag, longString.c_str()));
+  auto write_function = [&] {
+    ret = LOG_FAILURE_RETRY(
+        __android_log_buf_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO, tag, longString.c_str()));
+  };
 
-  struct logger_list* logger_list;
-
-  ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
-                           LOG_ID_SYSTEM,
-                           ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 100, 0)));
-
-  ssize_t max_len = 0;
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
-    }
-
-    if ((log_msg.entry.pid != pid) || (log_msg.id() != LOG_ID_SYSTEM)) {
-      continue;
-    }
-
+  auto check_function = [&](log_msg log_msg, bool* found) {
     char* data = log_msg.msg();
 
     if (!data || strcmp(++data, tag)) {
-      continue;
+      return;
     }
 
     data += strlen(data) + 1;
@@ -1069,33 +1070,38 @@
       ++right;
     }
 
-    if (max_len <= (left - data)) {
-      max_len = left - data + 1;
+    ssize_t len = left - data + 1;
+    // Check that we don't see any entries larger than the max payload.
+    EXPECT_LE(static_cast<size_t>(len), LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag));
+
+    // Once we've found our expected entry, break.
+    if (len == LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag)) {
+      EXPECT_EQ(ret, len + static_cast<ssize_t>(sizeof(big_payload_tag)));
+      *found = true;
     }
-  }
+  };
 
-  android_logger_list_close(logger_list);
+  RunLogTests(LOG_ID_SYSTEM, write_function, check_function);
 
-  EXPECT_LE(LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag),
-            static_cast<size_t>(max_len));
-
-  // SLOP: Allow the underlying interface to optionally place a
-  // terminating nul at the LOGGER_ENTRY_MAX_PAYLOAD's last byte
-  // or not.
-  if (ret == (max_len + static_cast<ssize_t>(sizeof(big_payload_tag)) - 1)) {
-    --max_len;
-  }
-  EXPECT_EQ(ret, max_len + static_cast<ssize_t>(sizeof(big_payload_tag)));
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 
-#ifdef ENABLE_FLAKY_TESTS
 TEST(liblog, dual_reader) {
 #ifdef __ANDROID__
+  static const int expected_count1 = 25;
+  static const int expected_count2 = 25;
 
-  static const int num = 25;
+  pid_t pid = getpid();
+
+  auto logger_list1 = std::unique_ptr<struct logger_list, ListCloser>{
+      android_logger_list_open(LOG_ID_MAIN, ANDROID_LOG_RDONLY, expected_count1, pid)};
+  ASSERT_TRUE(logger_list1);
+
+  auto logger_list2 = std::unique_ptr<struct logger_list, ListCloser>{
+      android_logger_list_open(LOG_ID_MAIN, ANDROID_LOG_RDONLY, expected_count2, pid)};
+  ASSERT_TRUE(logger_list2);
 
   for (int i = 25; i > 0; --i) {
     static const char fmt[] = "dual_reader %02d";
@@ -1104,32 +1110,46 @@
     LOG_FAILURE_RETRY(__android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO,
                                               "liblog", buffer));
   }
-  usleep(1000000);
 
-  struct logger_list* logger_list1;
-  ASSERT_TRUE(NULL != (logger_list1 = android_logger_list_open(
-                           LOG_ID_MAIN,
-                           ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, num, 0)));
+  alarm(2);
+  auto alarm_guard = android::base::make_scope_guard([] { alarm(0); });
 
-  struct logger_list* logger_list2;
+  // Wait until we see all messages with the blocking reader.
+  int count1 = 0;
+  int count2 = 0;
 
-  if (NULL == (logger_list2 = android_logger_list_open(
-                   LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-                   num - 10, 0))) {
-    android_logger_list_close(logger_list1);
-    ASSERT_TRUE(NULL != logger_list2);
+  while (count1 != expected_count2 || count2 != expected_count2) {
+    log_msg log_msg;
+    if (count1 < expected_count1) {
+      ASSERT_GT(android_logger_list_read(logger_list1.get(), &log_msg), 0);
+      count1++;
+    }
+    if (count2 < expected_count2) {
+      ASSERT_GT(android_logger_list_read(logger_list2.get(), &log_msg), 0);
+      count2++;
+    }
   }
 
-  int count1 = 0;
+  // Test again with the nonblocking reader.
+  auto logger_list_non_block1 =
+      std::unique_ptr<struct logger_list, ListCloser>{android_logger_list_open(
+          LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, expected_count1, pid)};
+  ASSERT_TRUE(logger_list_non_block1);
+
+  auto logger_list_non_block2 =
+      std::unique_ptr<struct logger_list, ListCloser>{android_logger_list_open(
+          LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, expected_count2, pid)};
+  ASSERT_TRUE(logger_list_non_block2);
+  count1 = 0;
+  count2 = 0;
   bool done1 = false;
-  int count2 = 0;
   bool done2 = false;
 
-  do {
+  while (!done1 || !done2) {
     log_msg log_msg;
 
     if (!done1) {
-      if (android_logger_list_read(logger_list1, &log_msg) <= 0) {
+      if (android_logger_list_read(logger_list_non_block1.get(), &log_msg) <= 0) {
         done1 = true;
       } else {
         ++count1;
@@ -1137,26 +1157,21 @@
     }
 
     if (!done2) {
-      if (android_logger_list_read(logger_list2, &log_msg) <= 0) {
+      if (android_logger_list_read(logger_list_non_block2.get(), &log_msg) <= 0) {
         done2 = true;
       } else {
         ++count2;
       }
     }
-  } while ((!done1) || (!done2));
+  }
 
-  android_logger_list_close(logger_list1);
-  android_logger_list_close(logger_list2);
-
-  EXPECT_EQ(num, count1);
-  EXPECT_EQ(num - 10, count2);
+  EXPECT_EQ(expected_count1, count1);
+  EXPECT_EQ(expected_count2, count2);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif  // ENABLE_FLAKY_TESTS
 
-#ifdef ENABLE_FLAKY_TESTS
 static bool checkPriForTag(AndroidLogFormat* p_format, const char* tag,
                            android_LogPriority pri) {
   return android_log_shouldPrintLine(p_format, tag, pri) &&
@@ -1232,7 +1247,6 @@
 
   android_log_format_free(p_format);
 }
-#endif  // ENABLE_FLAKY_TESTS
 
 #ifdef ENABLE_FLAKY_TESTS
 TEST(liblog, is_loggable) {
@@ -1886,101 +1900,71 @@
 #endif  // ENABLE_FLAKY_TESTS
 
 #ifdef __ANDROID__
-static void android_errorWriteWithInfoLog_helper(int TAG, const char* SUBTAG,
-                                                 int UID, const char* payload,
-                                                 int DATA_LEN, int& count) {
-  struct logger_list* logger_list;
+static void android_errorWriteWithInfoLog_helper(int tag, const char* subtag, int uid,
+                                                 const char* payload, int data_len) {
+  auto write_function = [&] {
+    int ret = android_errorWriteWithInfoLog(tag, subtag, uid, payload, data_len);
+    ASSERT_LT(0, ret);
+  };
 
-  pid_t pid = getpid();
-
-  count = 0;
-
-  ASSERT_TRUE(NULL !=
-              (logger_list = android_logger_list_open(
-                   LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-                   1000, pid)));
-
-  int retval_android_errorWriteWithinInfoLog =
-      android_errorWriteWithInfoLog(TAG, SUBTAG, UID, payload, DATA_LEN);
-  if (payload) {
-    ASSERT_LT(0, retval_android_errorWriteWithinInfoLog);
-  } else {
-    ASSERT_GT(0, retval_android_errorWriteWithinInfoLog);
-  }
-
-  sleep(2);
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
-    }
-
-    char* eventData = log_msg.msg();
-    if (!eventData) {
-      continue;
-    }
-
-    char* original = eventData;
+  auto check_function = [&](log_msg log_msg, bool* found) {
+    char* event_data = log_msg.msg();
+    char* original = event_data;
 
     // Tag
-    auto* event_header = reinterpret_cast<android_event_header_t*>(eventData);
-    eventData += sizeof(android_event_header_t);
-
-    if (event_header->tag != TAG) {
-      continue;
-    }
-
-    if (!payload) {
-      // This tag should not have been written because the data was null
-      ++count;
-      break;
+    auto* event_header = reinterpret_cast<android_event_header_t*>(event_data);
+    event_data += sizeof(android_event_header_t);
+    if (event_header->tag != tag) {
+      return;
     }
 
     // List type
-    auto* event_list = reinterpret_cast<android_event_list_t*>(eventData);
+    auto* event_list = reinterpret_cast<android_event_list_t*>(event_data);
     ASSERT_EQ(EVENT_TYPE_LIST, event_list->type);
     ASSERT_EQ(3, event_list->element_count);
-    eventData += sizeof(android_event_list_t);
+    event_data += sizeof(android_event_list_t);
 
     // Element #1: string type for subtag
-    auto* event_string_subtag = reinterpret_cast<android_event_string_t*>(eventData);
+    auto* event_string_subtag = reinterpret_cast<android_event_string_t*>(event_data);
     ASSERT_EQ(EVENT_TYPE_STRING, event_string_subtag->type);
-    unsigned subtag_len = strlen(SUBTAG);
-    if (subtag_len > 32) subtag_len = 32;
-    ASSERT_EQ(static_cast<int32_t>(subtag_len), event_string_subtag->length);
-    if (memcmp(SUBTAG, &event_string_subtag->data, subtag_len)) {
-      continue;
+    int32_t subtag_len = strlen(subtag);
+    if (subtag_len > 32) {
+      subtag_len = 32;
     }
-    eventData += sizeof(android_event_string_t) + subtag_len;
+    ASSERT_EQ(subtag_len, event_string_subtag->length);
+    if (memcmp(subtag, &event_string_subtag->data, subtag_len)) {
+      return;
+    }
+    event_data += sizeof(android_event_string_t) + subtag_len;
 
     // Element #2: int type for uid
-    auto* event_int_uid = reinterpret_cast<android_event_int_t*>(eventData);
+    auto* event_int_uid = reinterpret_cast<android_event_int_t*>(event_data);
     ASSERT_EQ(EVENT_TYPE_INT, event_int_uid->type);
-    ASSERT_EQ(UID, event_int_uid->data);
-    eventData += sizeof(android_event_int_t);
+    ASSERT_EQ(uid, event_int_uid->data);
+    event_data += sizeof(android_event_int_t);
 
     // Element #3: string type for data
-    auto* event_string_data = reinterpret_cast<android_event_string_t*>(eventData);
+    auto* event_string_data = reinterpret_cast<android_event_string_t*>(event_data);
     ASSERT_EQ(EVENT_TYPE_STRING, event_string_data->type);
-    size_t dataLen = event_string_data->length;
-    if (DATA_LEN < 512) ASSERT_EQ(DATA_LEN, (int)dataLen);
-    if (memcmp(payload, &event_string_data->data, dataLen)) {
-      continue;
+    int32_t message_data_len = event_string_data->length;
+    if (data_len < 512) {
+      ASSERT_EQ(data_len, message_data_len);
     }
-    eventData += sizeof(android_event_string_t);
+    if (memcmp(payload, &event_string_data->data, message_data_len) != 0) {
+      return;
+    }
+    event_data += sizeof(android_event_string_t);
 
-    if (DATA_LEN >= 512) {
-      eventData += dataLen;
+    if (data_len >= 512) {
+      event_data += message_data_len;
       // 4 bytes for the tag, and max_payload_buf should be truncated.
-      ASSERT_LE(4 + 512, eventData - original);       // worst expectations
-      ASSERT_GT(4 + DATA_LEN, eventData - original);  // must be truncated
+      ASSERT_LE(4 + 512, event_data - original);       // worst expectations
+      ASSERT_GT(4 + data_len, event_data - original);  // must be truncated
     }
+    *found = true;
+  };
 
-    ++count;
-  }
-
-  android_logger_list_close(logger_list);
+  RunLogTests(LOG_ID_EVENTS, write_function, check_function);
 }
 #endif
 
@@ -1995,10 +1979,7 @@
 
 TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__typical) {
 #ifdef __ANDROID__
-  int count;
-  android_errorWriteWithInfoLog_helper(UNIQUE_TAG(1), "test-subtag", -1,
-                                       max_payload_buf, 200, count);
-  EXPECT_EQ(1, count);
+  android_errorWriteWithInfoLog_helper(UNIQUE_TAG(1), "test-subtag", -1, max_payload_buf, 200);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
@@ -2007,23 +1988,20 @@
 TEST(liblog,
      android_errorWriteWithInfoLog__android_logger_list_read__data_too_large) {
 #ifdef __ANDROID__
-  int count;
-  android_errorWriteWithInfoLog_helper(UNIQUE_TAG(2), "test-subtag", -1,
-                                       max_payload_buf, sizeof(max_payload_buf),
-                                       count);
-  EXPECT_EQ(1, count);
+  android_errorWriteWithInfoLog_helper(UNIQUE_TAG(2), "test-subtag", -1, max_payload_buf,
+                                       sizeof(max_payload_buf));
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 
+// TODO: Do we need to check that we didn't actually write anything if we return a failure here?
 TEST(liblog,
      android_errorWriteWithInfoLog__android_logger_list_read__null_data) {
 #ifdef __ANDROID__
-  int count;
-  android_errorWriteWithInfoLog_helper(UNIQUE_TAG(3), "test-subtag", -1, NULL,
-                                       200, count);
-  EXPECT_EQ(0, count);
+  int retval_android_errorWriteWithinInfoLog =
+      android_errorWriteWithInfoLog(UNIQUE_TAG(3), "test-subtag", -1, nullptr, 200);
+  ASSERT_GT(0, retval_android_errorWriteWithinInfoLog);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
@@ -2032,11 +2010,8 @@
 TEST(liblog,
      android_errorWriteWithInfoLog__android_logger_list_read__subtag_too_long) {
 #ifdef __ANDROID__
-  int count;
   android_errorWriteWithInfoLog_helper(
-      UNIQUE_TAG(4), "abcdefghijklmnopqrstuvwxyz now i know my abc", -1,
-      max_payload_buf, 200, count);
-  EXPECT_EQ(1, count);
+      UNIQUE_TAG(4), "abcdefghijklmnopqrstuvwxyz now i know my abc", -1, max_payload_buf, 200);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
@@ -2050,124 +2025,44 @@
   buf_write_test(max_payload_buf);
 }
 
-#ifdef __ANDROID__
-static void android_errorWriteLog_helper(int TAG, const char* SUBTAG,
-                                         int& count) {
-  struct logger_list* logger_list;
-
-  pid_t pid = getpid();
-
-  count = 0;
-
-  // Do a Before and After on the count to measure the effect. Decrement
-  // what we find in Before to set the stage.
-  ASSERT_TRUE(NULL !=
-              (logger_list = android_logger_list_open(
-                   LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-                   1000, pid)));
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) break;
-
-    char* eventData = log_msg.msg();
-    if (!eventData) continue;
-
-    // Tag
-    auto* event_header = reinterpret_cast<android_event_header_t*>(eventData);
-    eventData += sizeof(android_event_header_t);
-
-    if (event_header->tag != TAG) {
-      continue;
-    }
-
-    if (!SUBTAG) {
-      // This tag should not have been written because the data was null
-      --count;
-      break;
-    }
-
-    // List type
-    eventData++;
-    // Number of elements in list
-    eventData++;
-    // Element #1: string type for subtag
-    eventData++;
-
-    eventData += 4;
-
-    if (memcmp(SUBTAG, eventData, strlen(SUBTAG))) continue;
-    --count;
-  }
-
-  android_logger_list_close(logger_list);
-
-  // Do an After on the count to measure the effect.
-  ASSERT_TRUE(NULL !=
-              (logger_list = android_logger_list_open(
-                   LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-                   1000, pid)));
-
-  int retval_android_errorWriteLog = android_errorWriteLog(TAG, SUBTAG);
-  if (SUBTAG) {
-    ASSERT_LT(0, retval_android_errorWriteLog);
-  } else {
-    ASSERT_GT(0, retval_android_errorWriteLog);
-  }
-
-  sleep(2);
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
-    }
-
-    char* eventData = log_msg.msg();
-    if (!eventData) {
-      continue;
-    }
-
-    // Tag
-    auto* event_header = reinterpret_cast<android_event_header_t*>(eventData);
-    eventData += sizeof(android_event_header_t);
-
-    if (event_header->tag != TAG) {
-      continue;
-    }
-
-    if (!SUBTAG) {
-      // This tag should not have been written because the data was null
-      ++count;
-      break;
-    }
-
-    // List type
-    auto* event_list = reinterpret_cast<android_event_list_t*>(eventData);
-    ASSERT_EQ(EVENT_TYPE_LIST, event_list->type);
-    ASSERT_EQ(3, event_list->element_count);
-    eventData += sizeof(android_event_list_t);
-
-    // Element #1: string type for subtag
-    auto* event_string = reinterpret_cast<android_event_string_t*>(eventData);
-    ASSERT_EQ(EVENT_TYPE_STRING, event_string->type);
-    ASSERT_EQ(static_cast<int32_t>(strlen(SUBTAG)), event_string->length);
-
-    if (memcmp(SUBTAG, &event_string->data, strlen(SUBTAG))) {
-      continue;
-    }
-    ++count;
-  }
-
-  android_logger_list_close(logger_list);
-}
-#endif
-
 TEST(liblog, android_errorWriteLog__android_logger_list_read__success) {
 #ifdef __ANDROID__
-  int count;
-  android_errorWriteLog_helper(UNIQUE_TAG(5), "test-subtag", count);
-  EXPECT_EQ(1, count);
+  int kTag = UNIQUE_TAG(5);
+  const char* kSubTag = "test-subtag";
+
+  auto write_function = [&] {
+    int retval_android_errorWriteLog = android_errorWriteLog(kTag, kSubTag);
+    ASSERT_LT(0, retval_android_errorWriteLog);
+  };
+
+  auto check_function = [&](log_msg log_msg, bool* found) {
+    char* event_data = log_msg.msg();
+
+    // Tag
+    auto* event_header = reinterpret_cast<android_event_header_t*>(event_data);
+    event_data += sizeof(android_event_header_t);
+    if (event_header->tag != kTag) {
+      return;
+    }
+
+    // List type
+    auto* event_list = reinterpret_cast<android_event_list_t*>(event_data);
+    ASSERT_EQ(EVENT_TYPE_LIST, event_list->type);
+    ASSERT_EQ(3, event_list->element_count);
+    event_data += sizeof(android_event_list_t);
+
+    // Element #1: string type for subtag
+    auto* event_string_subtag = reinterpret_cast<android_event_string_t*>(event_data);
+    ASSERT_EQ(EVENT_TYPE_STRING, event_string_subtag->type);
+    int32_t subtag_len = strlen(kSubTag);
+    ASSERT_EQ(subtag_len, event_string_subtag->length);
+    if (memcmp(kSubTag, &event_string_subtag->data, subtag_len) == 0) {
+      *found = true;
+    }
+  };
+
+  RunLogTests(LOG_ID_EVENTS, write_function, check_function);
+
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
@@ -2175,9 +2070,7 @@
 
 TEST(liblog, android_errorWriteLog__android_logger_list_read__null_subtag) {
 #ifdef __ANDROID__
-  int count;
-  android_errorWriteLog_helper(UNIQUE_TAG(6), NULL, count);
-  EXPECT_EQ(0, count);
+  EXPECT_LT(android_errorWriteLog(UNIQUE_TAG(6), nullptr), 0);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
@@ -2595,52 +2488,21 @@
 
 static void create_android_logger(const char* (*fn)(uint32_t tag,
                                                     size_t& expected_len)) {
-  struct logger_list* logger_list;
+  size_t expected_len;
+  const char* expected_string;
+  auto write_function = [&] {
+    expected_string = (*fn)(1005, expected_len);
+    ASSERT_NE(nullptr, expected_string);
+  };
 
   pid_t pid = getpid();
-
-  ASSERT_TRUE(NULL !=
-              (logger_list = android_logger_list_open(
-                   LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-                   1000, pid)));
-
-#ifdef __ANDROID__
-  log_time ts(android_log_clockid());
-#else
-  log_time ts(CLOCK_REALTIME);
-#endif
-
-  size_t expected_len;
-  const char* expected_string = (*fn)(1005, expected_len);
-
-  if (!expected_string) {
-    android_logger_list_close(logger_list);
-    return;
-  }
-
-  usleep(1000000);
-
-  int count = 0;
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
-    }
-
-    ASSERT_EQ(log_msg.entry.pid, pid);
-
-    if ((log_msg.entry.sec < (ts.tv_sec - 1)) ||
-        ((ts.tv_sec + 1) < log_msg.entry.sec) ||
-        ((size_t)log_msg.entry.len != expected_len) ||
-        (log_msg.id() != LOG_ID_EVENTS)) {
-      continue;
+  auto check_function = [&](log_msg log_msg, bool* found) {
+    if (static_cast<size_t>(log_msg.entry.len) != expected_len) {
+      return;
     }
 
     char* eventData = log_msg.msg();
 
-    ++count;
-
     AndroidLogFormat* logformat = android_log_format_new();
     EXPECT_TRUE(NULL != logformat);
     AndroidLogEntry entry;
@@ -2676,11 +2538,10 @@
     }
     EXPECT_EQ(0, buffer_to_string);
     EXPECT_STREQ(expected_string, msgBuf);
-  }
+    *found = true;
+  };
 
-  EXPECT_EQ(1, count);
-
-  android_logger_list_close(logger_list);
+  RunLogTests(LOG_ID_EVENTS, write_function, check_function);
 }
 #endif
 
@@ -2764,7 +2625,6 @@
 #endif
 }
 
-#ifdef ENABLE_FLAKY_TESTS
 TEST(liblog, create_android_logger_overflow) {
   android_log_context ctx;
 
@@ -2791,7 +2651,6 @@
   EXPECT_LE(0, android_log_destroy(&ctx));
   ASSERT_TRUE(NULL == ctx);
 }
-#endif  // ENABLE_FLAKY_TESTS
 
 #ifdef ENABLE_FLAKY_TESTS
 #ifdef __ANDROID__
@@ -2932,7 +2791,6 @@
 }
 #endif  // ENABLE_FLAKY_TESTS
 
-#ifdef ENABLE_FLAKY_TESTS
 TEST(liblog, android_lookupEventTagNum) {
 #ifdef __ANDROID__
   EventTagMap* map = android_openEventTagMap(NULL);
@@ -2949,4 +2807,3 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif  // ENABLE_FLAKY_TESTS
diff --git a/liblog/tests/log_read_test.cpp b/liblog/tests/log_read_test.cpp
index 443c3ea..1be99aa 100644
--- a/liblog/tests/log_read_test.cpp
+++ b/liblog/tests/log_read_test.cpp
@@ -29,54 +29,6 @@
 // Do not use anything in log/log_time.h despite side effects of the above.
 #include <private/android_logger.h>
 
-TEST(liblog, __android_log_write__android_logger_list_read) {
-#ifdef __ANDROID__
-  pid_t pid = getpid();
-
-  struct logger_list* logger_list;
-  ASSERT_TRUE(
-      NULL !=
-      (logger_list = android_logger_list_open(
-           LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
-  struct timespec ts;
-  clock_gettime(CLOCK_MONOTONIC, &ts);
-  std::string buf = android::base::StringPrintf("pid=%u ts=%ld.%09ld", pid,
-                                                ts.tv_sec, ts.tv_nsec);
-  static const char tag[] =
-      "liblog.__android_log_write__android_logger_list_read";
-  static const char prio = ANDROID_LOG_DEBUG;
-  ASSERT_LT(0, __android_log_write(prio, tag, buf.c_str()));
-  usleep(1000000);
-
-  buf = std::string(&prio, sizeof(prio)) + tag + std::string("", 1) + buf +
-        std::string("", 1);
-
-  int count = 0;
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) break;
-
-    EXPECT_EQ(log_msg.entry.pid, pid);
-    // There may be a future where we leak "liblog" tagged LOG_ID_EVENT
-    // binary messages through so that logger losses can be correlated?
-    EXPECT_EQ(log_msg.id(), LOG_ID_MAIN);
-
-    if (log_msg.entry.len != buf.length()) continue;
-
-    if (buf != std::string(log_msg.msg(), log_msg.entry.len)) continue;
-
-    ++count;
-  }
-  android_logger_list_close(logger_list);
-
-  EXPECT_EQ(1, count);
-#else
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
-}
-
 TEST(liblog, android_logger_get_) {
 #ifdef __ANDROID__
   // This test assumes the log buffers are filled with noise from
diff --git a/libprocessgroup/include/processgroup/sched_policy.h b/libprocessgroup/include/processgroup/sched_policy.h
index 3c498da..945d90c 100644
--- a/libprocessgroup/include/processgroup/sched_policy.h
+++ b/libprocessgroup/include/processgroup/sched_policy.h
@@ -70,11 +70,22 @@
 extern int get_sched_policy(int tid, SchedPolicy* policy);
 
 /* Return a displayable string corresponding to policy.
- * Return value: non-NULL NUL-terminated name of unspecified length;
+ * Return value: NUL-terminated name of unspecified length, nullptr if invalid;
  * the caller is responsible for displaying the useful part of the string.
  */
 extern const char* get_sched_policy_name(SchedPolicy policy);
 
+/* Return the aggregated task profile name corresponding to cpuset policy.
+ * Return value: NUL-terminated name of unspecified length, nullptr if invalid;
+ * the caller could use it to call SetTaskProfiles.
+ */
+extern const char* get_cpuset_policy_profile_name(SchedPolicy policy);
+
+/* Return the aggregated task profile name corresponding to sched policy.
+ * Return value: NUL-terminated name of unspecified length, nullptr if invalid;
+ * the caller could use it to call SetTaskProfiles.
+ */
+extern const char* get_sched_policy_profile_name(SchedPolicy policy);
 #ifdef __cplusplus
 }
 #endif
diff --git a/libprocessgroup/sched_policy.cpp b/libprocessgroup/sched_policy.cpp
index 6b0ab87..16339d3 100644
--- a/libprocessgroup/sched_policy.cpp
+++ b/libprocessgroup/sched_policy.cpp
@@ -212,7 +212,45 @@
     };
     static_assert(arraysize(kSchedPolicyNames) == SP_CNT, "missing name");
     if (policy < SP_BACKGROUND || policy >= SP_CNT) {
-        return "error";
+        return nullptr;
     }
     return kSchedPolicyNames[policy];
 }
+
+const char* get_cpuset_policy_profile_name(SchedPolicy policy) {
+    /*
+     *  cpuset profile array for:
+     *  SP_DEFAULT(-1), SP_BACKGROUND(0), SP_FOREGROUND(1),
+     *  SP_SYSTEM(2), SP_AUDIO_APP(3), SP_AUDIO_SYS(4),
+     *  SP_TOP_APP(5), SP_RT_APP(6), SP_RESTRICTED(7)
+     *  index is policy + 1
+     *  this need keep in sync with SchedPolicy enum
+     */
+    static constexpr const char* kCpusetProfiles[SP_CNT + 1] = {
+            "CPUSET_SP_DEFAULT", "CPUSET_SP_BACKGROUND", "CPUSET_SP_FOREGROUND",
+            "CPUSET_SP_SYSTEM",  "CPUSET_SP_FOREGROUND", "CPUSET_SP_FOREGROUND",
+            "CPUSET_SP_TOP_APP", "CPUSET_SP_DEFAULT",    "CPUSET_SP_RESTRICTED"};
+    if (policy < SP_DEFAULT || policy >= SP_CNT) {
+        return nullptr;
+    }
+    return kCpusetProfiles[policy + 1];
+}
+
+const char* get_sched_policy_profile_name(SchedPolicy policy) {
+    /*
+     *  sched profile array for:
+     *  SP_DEFAULT(-1), SP_BACKGROUND(0), SP_FOREGROUND(1),
+     *  SP_SYSTEM(2), SP_AUDIO_APP(3), SP_AUDIO_SYS(4),
+     *  SP_TOP_APP(5), SP_RT_APP(6), SP_RESTRICTED(7)
+     *  index is policy + 1
+     *  this need keep in sync with SchedPolicy enum
+     */
+    static constexpr const char* kSchedProfiles[SP_CNT + 1] = {
+            "SCHED_SP_DEFAULT", "SCHED_SP_BACKGROUND", "SCHED_SP_FOREGROUND",
+            "SCHED_SP_DEFAULT", "SCHED_SP_FOREGROUND", "SCHED_SP_FOREGROUND",
+            "SCHED_SP_TOP_APP", "SCHED_SP_RT_APP",     "SCHED_SP_DEFAULT"};
+    if (policy < SP_DEFAULT || policy >= SP_CNT) {
+        return nullptr;
+    }
+    return kSchedProfiles[policy + 1];
+}
diff --git a/libunwindstack/AndroidVersions.md b/libunwindstack/AndroidVersions.md
new file mode 100644
index 0000000..234f639
--- /dev/null
+++ b/libunwindstack/AndroidVersions.md
@@ -0,0 +1,116 @@
+# Unwinder Support Per Android Release
+This document describes the changes in the way the libunwindstack
+unwinder works on different Android versions. It does not describe
+every change in the code made between different versions, but is
+meant to allow an app developer to know what might be supported
+on different versions. It also describes the different way an unwind
+will display on different versions of Android.
+
+## Android P
+libunwindstack was first introduced in Android P.
+
+* Supports up to and including Dwarf 4 unwinding information.
+  See http://dwarfstd.org/ for Dwarf standards.
+* Supports Arm exidx unwinding.
+* Supports the gdb JIT unwinding interface, which is how ART creates unwinding
+  information for the JIT'd Java frames.
+* Supports special frames added to represent an ART Java interpreter frame.
+  ART has marked the dex pc using cfi information that the unwinder
+  understands and handles by adding a new frame in the stacktrace.
+
+## Note
+By default, lld creates two separate maps of the elf in memory, one read-only
+and one read/executable. The libunwindstack on P and the unwinder on older
+versions of Android will not unwind properly in this case. For apps that
+target Android P or older, make sure that `-Wl,--no-rosegment` is
+included in linker arguments when using lld.
+
+## Android Q
+* Fix bug (b/109824792) that handled load bias data incorrectly when
+  FDEs use pc relative addressing in the eh\_frame\_hdr.
+  Unfortunately, this wasn't fixed correctly in Q since it assumes
+  that the bias is coming from the program header for the executable
+  load. The real fix was to use the bias from the actual section data and
+  is not completely fixed until Android R. For apps targeting Android Q,
+  if it is being compiled with the llvm linker lld, it might be necessary
+  to add the linker option `-Wl,-zseparate-code` to avoid creating an elf
+  created this way.
+* Change the way the exidx section offset is found (b/110704153). Before
+  the p\_vaddr value from the program header minus the load bias was used
+  to find the start of the exidx data. Changed to use the p\_offset since
+  it doesn't require any load bias manipulations.
+* Fix bug handling of dwarf sections without any header (b/110235461).
+  Previously, the code assumed that FDEs are non-overlapping, and the FDEs
+  are always in sorted order from low pc to high pc. Thus the code would
+  read the entire set of CIEs/FDEs and then do a binary search to find
+  the appropriate FDE for a given pc. Now the code does a sequential read
+  and stops when it finds the FDE for a pc. It also understands the
+  overlapping FDEs, so find the first FDE that matches a pc. In practice,
+  elf files with this format only ever occurs if the file was generated
+  without an eh\_frame/eh\_frame\_hdr section and only a debug\_frame. The
+  other way this has been observed is when running simpleperf to unwind since
+  sometimes there is not enough information in the eh\_frame for all points
+  in the executable. On Android P, this would result in some incorrect
+  unwinds coming from simpleperf. Nearly all crashes from Android P should
+  be correct since the eh\_frame information was enough to do the unwind
+  properly.
+* Be permissive of badly formed elf files. Previously, any detected error
+  would result in unwinds stopping even if there is enough valid information
+  to do an unwind.
+  * The code now allows program header/section header offsets to point
+    to unreadable memory. As long as the code can find the unwind tables,
+    that is good enough.
+  * The code allows program headers/section headers to be missing.
+  * Allow a symbol table section header to point to invalid symbol table
+    values.
+* Support for the linker read-only segment option (b/109657296).
+  This is a feature of lld whereby there are two sections that
+  contain elf data. The first is read-only and contains the elf header data,
+  and the second is read-execute or execute only that
+  contains the executable code from the elf. Before this, the unwinder
+  always assumed that there was only a single read-execute section that
+  contained the elf header data and the executable code.
+* Build ID information for elf objects added. This will display the
+  NT\_GNU\_BUILD\_ID note found in elf files. This information can be used
+  to identify the exact version of a shared library to help get symbol
+  information when looking at a crash.
+* Add support for displaying the soname from an apk frame. Previously,
+  a frame map name would be only the apk, but now if the shared library
+  in the apk has set a soname, the map name will be `app.apk!libexample.so`
+  instead of only `app.apk`.
+* Minimal support for Dwarf 5. This merely treats a Dwarf 5 version
+  elf file as Dwarf 4. It does not support the new dwarf ops in Dwarf 5.
+  Since the new ops are not likely to be used very often, this allows
+  continuing to unwind even when encountering Dwarf 5 elf files.
+* Fix bug in pc handling of signal frames (b/130302288). In the previous
+  version, the pc would be wrong in the signal frame. The rest of the
+  unwind was correct, only the frame in the signal handler was incorrect
+  in Android P.
+* Detect when an elf file is not readable so that a message can be
+  displayed indicating that. This can happen when an app puts the shared
+  libraries in non-standard locations that are not readable due to
+  security restrictions (selinux rules).
+
+## Android R
+* Display the offsets for Java interpreter frames. If this frame came
+  from a non-zero offset map, no offset is printed. Previously, the
+  line would look like:
+
+    #17 pc 00500d7a  GoogleCamera.apk (com.google.camera.AndroidPriorityThread.run+10)
+
+  to:
+
+    #17 pc 00500d7a  GoogleCamera.apk (offset 0x11d0000) (com.google.camera.AndroidPriorityThread.run+10)
+* Fix bug where the load bias was set from the first PT\_LOAD program
+  header that has a zero p\_offset value. Now it is set from the first
+  executable PT\_LOAD program header. This has only ever been a problem
+  for host executables compiled for the x86\_64 architecture.
+* Switched to the libc++ demangler for function names. Previously, the
+  demangler used was not complete, so some less common demangled function
+  names would not be properly demangled or the function name would not be
+  demangled at all.
+* Fix bug in load bias handling. If the unwind information in the eh\_frame
+  or eh\_frame\_hdr does not have the same bias as the executable section,
+  and uses pc relative FDEs, the unwind will be incorrect. This tends
+  to truncate unwinds since the unwinder could not find the correct unwind
+  information for a given pc.
diff --git a/libunwindstack/tests/DwarfSectionTest.cpp b/libunwindstack/tests/DwarfSectionTest.cpp
index 6df2bae..953dc75 100644
--- a/libunwindstack/tests/DwarfSectionTest.cpp
+++ b/libunwindstack/tests/DwarfSectionTest.cpp
@@ -30,23 +30,24 @@
   MockDwarfSection(Memory* memory) : DwarfSection(memory) {}
   virtual ~MockDwarfSection() = default;
 
-  MOCK_METHOD3(Init, bool(uint64_t, uint64_t, int64_t));
+  MOCK_METHOD(bool, Init, (uint64_t, uint64_t, int64_t), (override));
 
-  MOCK_METHOD5(Eval, bool(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*));
+  MOCK_METHOD(bool, Eval, (const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*),
+              (override));
 
-  MOCK_METHOD3(Log, bool(uint8_t, uint64_t, const DwarfFde*));
+  MOCK_METHOD(bool, Log, (uint8_t, uint64_t, const DwarfFde*), (override));
 
-  MOCK_METHOD1(GetFdes, void(std::vector<const DwarfFde*>*));
+  MOCK_METHOD(void, GetFdes, (std::vector<const DwarfFde*>*), (override));
 
-  MOCK_METHOD1(GetFdeFromPc, const DwarfFde*(uint64_t));
+  MOCK_METHOD(const DwarfFde*, GetFdeFromPc, (uint64_t), (override));
 
-  MOCK_METHOD3(GetCfaLocationInfo, bool(uint64_t, const DwarfFde*, dwarf_loc_regs_t*));
+  MOCK_METHOD(bool, GetCfaLocationInfo, (uint64_t, const DwarfFde*, dwarf_loc_regs_t*), (override));
 
-  MOCK_METHOD1(GetCieOffsetFromFde32, uint64_t(uint32_t));
+  MOCK_METHOD(uint64_t, GetCieOffsetFromFde32, (uint32_t), (override));
 
-  MOCK_METHOD1(GetCieOffsetFromFde64, uint64_t(uint64_t));
+  MOCK_METHOD(uint64_t, GetCieOffsetFromFde64, (uint64_t), (override));
 
-  MOCK_METHOD1(AdjustPcFromFde, uint64_t(uint64_t));
+  MOCK_METHOD(uint64_t, AdjustPcFromFde, (uint64_t), (override));
 };
 
 class DwarfSectionTest : public ::testing::Test {
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index 8c1eade..e6728a0 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -316,9 +316,9 @@
   bool GetFunctionName(uint64_t, std::string*, uint64_t*) override { return false; }
   std::string GetBuildID() override { return ""; }
 
-  MOCK_METHOD4(Step, bool(uint64_t, Regs*, Memory*, bool*));
-  MOCK_METHOD2(GetGlobalVariable, bool(const std::string&, uint64_t*));
-  MOCK_METHOD1(IsValidPc, bool(uint64_t));
+  MOCK_METHOD(bool, Step, (uint64_t, Regs*, Memory*, bool*), (override));
+  MOCK_METHOD(bool, GetGlobalVariable, (const std::string&, uint64_t*), (override));
+  MOCK_METHOD(bool, IsValidPc, (uint64_t), (override));
 
   void MockSetDynamicOffset(uint64_t offset) { dynamic_offset_ = offset; }
   void MockSetDynamicVaddr(uint64_t vaddr) { dynamic_vaddr_ = vaddr; }
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 9cbc7c4..ba05a06 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -1185,7 +1185,7 @@
         unlock();
 
         // range locking in LastLogTimes looks after us
-        curr = element->flushTo(reader, this, privileged, sameTid);
+        curr = element->flushTo(reader, this, sameTid);
 
         if (curr == element->FLUSH_ERROR) {
             return curr;
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index 82c4fb9..5c43e18 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -244,14 +244,10 @@
     return retval;
 }
 
-log_time LogBufferElement::flushTo(SocketClient* reader, LogBuffer* parent,
-                                   bool privileged, bool lastSame) {
-    struct logger_entry_v4 entry;
+log_time LogBufferElement::flushTo(SocketClient* reader, LogBuffer* parent, bool lastSame) {
+    struct logger_entry_v4 entry = {};
 
-    memset(&entry, 0, sizeof(struct logger_entry_v4));
-
-    entry.hdr_size = privileged ? sizeof(struct logger_entry_v4)
-                                : sizeof(struct logger_entry_v3);
+    entry.hdr_size = sizeof(struct logger_entry_v4);
     entry.lid = mLogId;
     entry.pid = mPid;
     entry.tid = mTid;
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index da4991b..fd790e4 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef _LOGD_LOG_BUFFER_ELEMENT_H__
-#define _LOGD_LOG_BUFFER_ELEMENT_H__
+#pragma once
 
 #include <stdatomic.h>
 #include <stdint.h>
@@ -96,8 +95,5 @@
     }
 
     static const log_time FLUSH_ERROR;
-    log_time flushTo(SocketClient* writer, LogBuffer* parent, bool privileged,
-                     bool lastSame);
+    log_time flushTo(SocketClient* writer, LogBuffer* parent, bool lastSame);
 };
-
-#endif
diff --git a/rootdir/etc/public.libraries.android.txt b/rootdir/etc/public.libraries.android.txt
index 27e855f..405f5a9 100644
--- a/rootdir/etc/public.libraries.android.txt
+++ b/rootdir/etc/public.libraries.android.txt
@@ -17,7 +17,7 @@
 libmediandk.so
 libm.so
 libnativewindow.so
-libneuralnetworks.so
+libneuralnetworks.so nopreload
 libOpenMAXAL.so
 libOpenSLES.so
 libRS.so