Merge "host_init_verifier: use libhidlmetadata"
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/adb/fastdeploy/Android.bp b/adb/fastdeploy/Android.bp
index 245d52a..f5893aa 100644
--- a/adb/fastdeploy/Android.bp
+++ b/adb/fastdeploy/Android.bp
@@ -27,6 +27,7 @@
 
 java_binary {
     name: "deployagent",
+    sdk_version: "24",
     static_libs: [
         "deployagent_lib",
     ],
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/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp
index 3ce909e..8a924d5 100644
--- a/fs_mgr/libdm/Android.bp
+++ b/fs_mgr/libdm/Android.bp
@@ -81,7 +81,7 @@
 }
 
 cc_fuzz {
-  name: "dm_table_fuzzer",
+  name: "dm_linear_table_fuzzer",
   defaults: ["fs_mgr_defaults"],
   srcs: [
     "dm_linear_fuzzer.cpp",
diff --git a/fs_mgr/libdm/dm_linear_fuzzer.cpp b/fs_mgr/libdm/dm_linear_fuzzer.cpp
index b119635..8462901 100644
--- a/fs_mgr/libdm/dm_linear_fuzzer.cpp
+++ b/fs_mgr/libdm/dm_linear_fuzzer.cpp
@@ -76,7 +76,7 @@
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
     uint64_t val[6];
 
-    if (size != sizeof(*val)) {
+    if (size != sizeof(val)) {
         return 0;
     }
 
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..9256a16 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,12 +131,14 @@
     ],
     shared_libs: [
         "libbinder",
+        "libcrypto",
+        "libhidlbase",
         "libprotobuf-cpp-lite",
         "libutils",
     ],
     static_libs: [
-        "libcutils",
-        "libcrypto_static",
+        "android.hardware.boot@1.0",
+        "android.hardware.boot@1.1",
         "libfs_mgr",
         "libgmock",
         "liblp",
@@ -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 cf2d745..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"
 
@@ -99,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 395fb40..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>
@@ -84,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() {}
@@ -1590,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 aea12be..a008294 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -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/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 06c8176..57ed362 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -200,9 +200,7 @@
     return value;
 }
 
-bool BatteryMonitor::update(void) {
-    bool logthis;
-
+void BatteryMonitor::updateValues(void) {
     initBatteryProperties(&props);
 
     if (!mHealthdConfig->batteryPresentPath.isEmpty())
@@ -289,50 +287,44 @@
             }
         }
     }
+}
 
-    logthis = !healthd_board_battery_update(&props);
+void BatteryMonitor::logValues(void) {
+    char dmesgline[256];
+    size_t len;
+    if (props.batteryPresent) {
+        snprintf(dmesgline, sizeof(dmesgline), "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
+                 props.batteryLevel, props.batteryVoltage, props.batteryTemperature < 0 ? "-" : "",
+                 abs(props.batteryTemperature / 10), abs(props.batteryTemperature % 10),
+                 props.batteryHealth, props.batteryStatus);
 
-    if (logthis) {
-        char dmesgline[256];
-        size_t len;
-        if (props.batteryPresent) {
-            snprintf(dmesgline, sizeof(dmesgline),
-                 "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
-                 props.batteryLevel, props.batteryVoltage,
-                 props.batteryTemperature < 0 ? "-" : "",
-                 abs(props.batteryTemperature / 10),
-                 abs(props.batteryTemperature % 10), props.batteryHealth,
-                 props.batteryStatus);
-
-            len = strlen(dmesgline);
-            if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
-                len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
-                                " c=%d", props.batteryCurrent);
-            }
-
-            if (!mHealthdConfig->batteryFullChargePath.isEmpty()) {
-                len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
-                                " fc=%d", props.batteryFullCharge);
-            }
-
-            if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) {
-                len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
-                                " cc=%d", props.batteryCycleCount);
-            }
-        } else {
-            len = snprintf(dmesgline, sizeof(dmesgline),
-                 "battery none");
+        len = strlen(dmesgline);
+        if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
+            len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " c=%d",
+                            props.batteryCurrent);
         }
 
-        snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s",
-                 props.chargerAcOnline ? "a" : "",
-                 props.chargerUsbOnline ? "u" : "",
-                 props.chargerWirelessOnline ? "w" : "");
+        if (!mHealthdConfig->batteryFullChargePath.isEmpty()) {
+            len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " fc=%d",
+                            props.batteryFullCharge);
+        }
 
-        KLOG_WARNING(LOG_TAG, "%s\n", dmesgline);
+        if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) {
+            len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " cc=%d",
+                            props.batteryCycleCount);
+        }
+    } else {
+        len = snprintf(dmesgline, sizeof(dmesgline), "battery none");
     }
 
-    healthd_mode_ops->battery_update(&props);
+    snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s",
+             props.chargerAcOnline ? "a" : "", props.chargerUsbOnline ? "u" : "",
+             props.chargerWirelessOnline ? "w" : "");
+
+    KLOG_WARNING(LOG_TAG, "%s\n", dmesgline);
+}
+
+bool BatteryMonitor::isChargerOnline() {
     return props.chargerAcOnline | props.chargerUsbOnline |
             props.chargerWirelessOnline;
 }
diff --git a/healthd/include/healthd/BatteryMonitor.h b/healthd/include/healthd/BatteryMonitor.h
index 4d1d53f..0fd3824 100644
--- a/healthd/include/healthd/BatteryMonitor.h
+++ b/healthd/include/healthd/BatteryMonitor.h
@@ -38,12 +38,15 @@
 
     BatteryMonitor();
     void init(struct healthd_config *hc);
-    bool update(void);
     int getChargeStatus();
     status_t getProperty(int id, struct BatteryProperty *val);
     void dumpState(int fd);
     friend struct BatteryProperties getBatteryProperties(BatteryMonitor* batteryMonitor);
 
+    void updateValues(void);
+    void logValues(void);
+    bool isChargerOnline();
+
   private:
     struct healthd_config *mHealthdConfig;
     Vector<String8> mChargerNames;
diff --git a/init/Android.bp b/init/Android.bp
index 6b0557c..bd2d38c 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/property_service.cpp b/init/property_service.cpp
index c6bbc14..3baaf7c 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -404,7 +404,7 @@
     // We must release the fd before sending it to init, otherwise there will be a race with init.
     // If init calls close() before Release(), then fdsan will see the wrong tag and abort().
     int fd = -1;
-    if (socket != nullptr) {
+    if (socket != nullptr && SelinuxGetVendorAndroidVersion() > __ANDROID_API_Q__) {
         fd = socket->Release();
         control_message->set_fd(fd);
     }
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..7290789 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,16 +121,9 @@
  * 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
 /**
  * Identifies a specific log buffer for __android_log_buf_write()
  * and __android_log_buf_print().
@@ -163,7 +150,6 @@
 
   LOG_ID_MAX
 } log_id_t;
-#endif
 
 /**
  * Writes the constant string `text` to the log buffer `id`,
@@ -171,8 +157,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 +167,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..c8fafe7 100644
--- a/liblog/include/log/log_id.h
+++ b/liblog/include/log/log_id.h
@@ -16,41 +16,19 @@
 
 #pragma once
 
+#include <android/log.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#ifndef log_id_t_defined
-#define log_id_t_defined
-typedef enum log_id {
-  LOG_ID_MIN = 0,
-
-  LOG_ID_MAIN = 0,
-  LOG_ID_RADIO = 1,
-  LOG_ID_EVENTS = 2,
-  LOG_ID_SYSTEM = 3,
-  LOG_ID_CRASH = 4,
-  LOG_ID_STATS = 5,
-  LOG_ID_SECURITY = 6,
-  LOG_ID_KERNEL = 7, /* place last, third-parties can not use it */
-
-  LOG_ID_MAX
-} log_id_t;
-#endif
-#define sizeof_log_id_t sizeof(typeof_log_id_t)
-#define typeof_log_id_t unsigned char
-
 /*
  * Send a simple string to the log.
  */
 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 1b33331..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))
@@ -164,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/include/private/android_logger.h b/liblog/include/private/android_logger.h
index d3cb571..d3b72bc 100644
--- a/liblog/include/private/android_logger.h
+++ b/liblog/include/private/android_logger.h
@@ -47,7 +47,7 @@
 
 /* Header Structure to logd, and second header for pstore */
 typedef struct __attribute__((__packed__)) {
-  typeof_log_id_t id;
+  uint8_t id;
   uint16_t tid;
   log_time realtime;
 } android_log_header_t;
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 063c132..94c4fbb 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -62,6 +62,12 @@
     _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
@@ -75,11 +81,6 @@
 static void RunLogTests(log_id_t log_buffer, FWrite write_messages, FCheck check_message) {
   pid_t pid = getpid();
 
-  // 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); }
-  };
   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);
@@ -946,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";
@@ -995,7 +995,6 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif  // ENABLE_FLAKY_TESTS
 
 TEST(liblog, __android_log_buf_print__maxtag) {
 #ifdef __ANDROID__
@@ -1089,11 +1088,20 @@
 #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";
@@ -1102,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;
@@ -1135,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) &&
@@ -1230,7 +1247,6 @@
 
   android_log_format_free(p_format);
 }
-#endif  // ENABLE_FLAKY_TESTS
 
 #ifdef ENABLE_FLAKY_TESTS
 TEST(liblog, is_loggable) {
@@ -2609,7 +2625,6 @@
 #endif
 }
 
-#ifdef ENABLE_FLAKY_TESTS
 TEST(liblog, create_android_logger_overflow) {
   android_log_context ctx;
 
@@ -2636,7 +2651,6 @@
   EXPECT_LE(0, android_log_destroy(&ctx));
   ASSERT_TRUE(NULL == ctx);
 }
-#endif  // ENABLE_FLAKY_TESTS
 
 #ifdef ENABLE_FLAKY_TESTS
 #ifdef __ANDROID__
@@ -2777,7 +2791,6 @@
 }
 #endif  // ENABLE_FLAKY_TESTS
 
-#ifdef ENABLE_FLAKY_TESTS
 TEST(liblog, android_lookupEventTagNum) {
 #ifdef __ANDROID__
   EventTagMap* map = android_openEventTagMap(NULL);
@@ -2794,4 +2807,3 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif  // ENABLE_FLAKY_TESTS
diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c
index a098d59..6af49bb 100644
--- a/libnetutils/ifc_utils.c
+++ b/libnetutils/ifc_utils.c
@@ -362,10 +362,12 @@
     return err->error;
 }
 
+// Returns zero on success and negative errno on failure.
 int ifc_add_address(const char *name, const char *address, int prefixlen) {
     return ifc_act_on_address(RTM_NEWADDR, name, address, prefixlen);
 }
 
+// Returns zero on success and negative errno on failure.
 int ifc_del_address(const char *name, const char * address, int prefixlen) {
     return ifc_act_on_address(RTM_DELADDR, name, address, prefixlen);
 }
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/Android.bp b/libunwindstack/Android.bp
index b0f3786..2573b1c 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -239,6 +239,7 @@
         "tests/files/offline/bad_eh_frame_hdr_arm64/*",
         "tests/files/offline/debug_frame_first_x86/*",
         "tests/files/offline/debug_frame_load_bias_arm/*",
+        "tests/files/offline/eh_frame_bias_x86/*",
         "tests/files/offline/eh_frame_hdr_begin_x86_64/*",
         "tests/files/offline/invalid_elf_offset_arm/*",
         "tests/files/offline/jit_debug_arm/*",
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/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index e34273c..e863f22 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -228,7 +228,7 @@
     case PT_GNU_EH_FRAME:
       // This is really the pointer to the .eh_frame_hdr section.
       eh_frame_hdr_offset_ = phdr.p_offset;
-      eh_frame_hdr_section_bias_ = static_cast<uint64_t>(phdr.p_paddr) - phdr.p_offset;
+      eh_frame_hdr_section_bias_ = static_cast<uint64_t>(phdr.p_vaddr) - phdr.p_offset;
       eh_frame_hdr_size_ = phdr.p_memsz;
       break;
 
diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp
index b048b17..ea27e3e 100644
--- a/libunwindstack/tests/ElfInterfaceTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceTest.cpp
@@ -1310,7 +1310,7 @@
 
   memset(&phdr, 0, sizeof(phdr));
   phdr.p_type = PT_GNU_EH_FRAME;
-  phdr.p_paddr = addr;
+  phdr.p_vaddr = addr;
   phdr.p_offset = offset;
   memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr));
 
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index 72eef3e..0d58c09 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -1583,4 +1583,50 @@
   EXPECT_EQ(0x7fdd4a4170ULL, unwinder.frames()[11].sp);
 }
 
+TEST_F(UnwindOfflineTest, eh_frame_bias_x86) {
+  ASSERT_NO_FATAL_FAILURE(Init("eh_frame_bias_x86/", ARCH_X86));
+
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
+  unwinder.Unwind();
+
+  std::string frame_info(DumpFrames(unwinder));
+  ASSERT_EQ(11U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc ffffe430  vdso.so (__kernel_vsyscall+16)\n"
+      "  #01 pc 00082a4b  libc.so (__epoll_pwait+43)\n"
+      "  #02 pc 000303a3  libc.so (epoll_pwait+115)\n"
+      "  #03 pc 000303ed  libc.so (epoll_wait+45)\n"
+      "  #04 pc 00010ea2  tombstoned (epoll_dispatch+226)\n"
+      "  #05 pc 0000c5e7  tombstoned (event_base_loop+1095)\n"
+      "  #06 pc 0000c193  tombstoned (event_base_dispatch+35)\n"
+      "  #07 pc 00005c77  tombstoned (main+884)\n"
+      "  #08 pc 00015f66  libc.so (__libc_init+102)\n"
+      "  #09 pc 0000360e  tombstoned (_start+98)\n"
+      "  #10 pc 00000001  <unknown>\n",
+      frame_info);
+
+  EXPECT_EQ(0xffffe430ULL, unwinder.frames()[0].pc);
+  EXPECT_EQ(0xfffe1a30ULL, unwinder.frames()[0].sp);
+  EXPECT_EQ(0xeb585a4bULL, unwinder.frames()[1].pc);
+  EXPECT_EQ(0xfffe1a40ULL, unwinder.frames()[1].sp);
+  EXPECT_EQ(0xeb5333a3ULL, unwinder.frames()[2].pc);
+  EXPECT_EQ(0xfffe1a60ULL, unwinder.frames()[2].sp);
+  EXPECT_EQ(0xeb5333edULL, unwinder.frames()[3].pc);
+  EXPECT_EQ(0xfffe1ab0ULL, unwinder.frames()[3].sp);
+  EXPECT_EQ(0xeb841ea2ULL, unwinder.frames()[4].pc);
+  EXPECT_EQ(0xfffe1ae0ULL, unwinder.frames()[4].sp);
+  EXPECT_EQ(0xeb83d5e7ULL, unwinder.frames()[5].pc);
+  EXPECT_EQ(0xfffe1b30ULL, unwinder.frames()[5].sp);
+  EXPECT_EQ(0xeb83d193ULL, unwinder.frames()[6].pc);
+  EXPECT_EQ(0xfffe1bd0ULL, unwinder.frames()[6].sp);
+  EXPECT_EQ(0xeb836c77ULL, unwinder.frames()[7].pc);
+  EXPECT_EQ(0xfffe1c00ULL, unwinder.frames()[7].sp);
+  EXPECT_EQ(0xeb518f66ULL, unwinder.frames()[8].pc);
+  EXPECT_EQ(0xfffe1d00ULL, unwinder.frames()[8].sp);
+  EXPECT_EQ(0xeb83460eULL, unwinder.frames()[9].pc);
+  EXPECT_EQ(0xfffe1d40ULL, unwinder.frames()[9].sp);
+  EXPECT_EQ(0x00000001ULL, unwinder.frames()[10].pc);
+  EXPECT_EQ(0xfffe1d74ULL, unwinder.frames()[10].sp);
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so b/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so
new file mode 100644
index 0000000..f3eb615
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/maps.txt b/libunwindstack/tests/files/offline/eh_frame_bias_x86/maps.txt
new file mode 100644
index 0000000..7d52483
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/maps.txt
@@ -0,0 +1,3 @@
+eb503000-eb5e8000 r-xp 0 00:00 0   libc.so
+eb831000-eb852000 r-xp 0 00:00 0   tombstoned
+ffffe000-fffff000 r-xp 0 00:00 0   vdso.so
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/regs.txt b/libunwindstack/tests/files/offline/eh_frame_bias_x86/regs.txt
new file mode 100644
index 0000000..821928e
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/regs.txt
@@ -0,0 +1,9 @@
+eax: fffffffc
+ebx: 4
+ecx: eb290180
+edx: 20
+ebp: 8
+edi: 0
+esi: ffffffff
+esp: fffe1a30
+eip: ffffe430
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data b/libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data
new file mode 100644
index 0000000..b95bfac
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned b/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned
new file mode 100644
index 0000000..aefdb6b
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so b/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so
new file mode 100644
index 0000000..c71dcfb
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so
Binary files differ
diff --git a/libunwindstack/tools/unwind_for_offline.cpp b/libunwindstack/tools/unwind_for_offline.cpp
index 4f67d67..64b58a8 100644
--- a/libunwindstack/tools/unwind_for_offline.cpp
+++ b/libunwindstack/tools/unwind_for_offline.cpp
@@ -275,6 +275,9 @@
 
     if (maps_by_start.count(frame.map_start) == 0) {
       map_info = maps->Find(frame.map_start);
+      if (map_info == nullptr) {
+        continue;
+      }
 
       auto info = FillInAndGetMapInfo(maps_by_start, map_info);
       bool file_copied = false;
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index 0253f2f..2251479 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -184,3 +184,10 @@
     ],
     recovery_available: true,
 }
+
+cc_fuzz {
+    name: "libziparchive_fuzzer",
+    srcs: ["libziparchive_fuzzer.cpp"],
+    static_libs: ["libziparchive", "libbase", "libz", "liblog"],
+    host_supported: true,
+}
diff --git a/libziparchive/include/ziparchive/zip_archive.h b/libziparchive/include/ziparchive/zip_archive.h
index e3ac114..391cff9 100644
--- a/libziparchive/include/ziparchive/zip_archive.h
+++ b/libziparchive/include/ziparchive/zip_archive.h
@@ -114,7 +114,7 @@
 int32_t OpenArchiveFd(const int fd, const char* debugFileName, ZipArchiveHandle* handle,
                       bool assume_ownership = true);
 
-int32_t OpenArchiveFromMemory(void* address, size_t length, const char* debugFileName,
+int32_t OpenArchiveFromMemory(const void* address, size_t length, const char* debugFileName,
                               ZipArchiveHandle* handle);
 /*
  * Close archive, releasing resources associated with it. This will
diff --git a/libziparchive/libziparchive_fuzzer.cpp b/libziparchive/libziparchive_fuzzer.cpp
new file mode 100644
index 0000000..75e7939
--- /dev/null
+++ b/libziparchive/libziparchive_fuzzer.cpp
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: Apache-2.0
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <ziparchive/zip_archive.h>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  ZipArchiveHandle handle = nullptr;
+  OpenArchiveFromMemory(data, size, "fuzz", &handle);
+  CloseArchive(handle);
+  return 0;
+}
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index c95b035..3a552d8 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -178,7 +178,7 @@
 #endif
 }
 
-ZipArchive::ZipArchive(void* address, size_t length)
+ZipArchive::ZipArchive(const void* address, size_t length)
     : mapped_zip(address, length),
       close_file(false),
       directory_offset(0),
@@ -471,7 +471,7 @@
   return OpenArchiveInternal(archive, fileName);
 }
 
-int32_t OpenArchiveFromMemory(void* address, size_t length, const char* debug_file_name,
+int32_t OpenArchiveFromMemory(const void* address, size_t length, const char* debug_file_name,
                               ZipArchiveHandle* handle) {
   ZipArchive* archive = new ZipArchive(address, length);
   *handle = archive;
@@ -1152,7 +1152,7 @@
   return fd_;
 }
 
-void* MappedZipFile::GetBasePtr() const {
+const void* MappedZipFile::GetBasePtr() const {
   if (has_fd_) {
     ALOGW("Zip: MappedZipFile doesn't have a base pointer.");
     return nullptr;
@@ -1188,13 +1188,14 @@
       ALOGE("Zip: invalid offset: %" PRId64 ", data length: %" PRId64 "\n", off, data_length_);
       return false;
     }
-    memcpy(buf, static_cast<uint8_t*>(base_ptr_) + off, len);
+    memcpy(buf, static_cast<const uint8_t*>(base_ptr_) + off, len);
   }
   return true;
 }
 
-void CentralDirectory::Initialize(void* map_base_ptr, off64_t cd_start_offset, size_t cd_size) {
-  base_ptr_ = static_cast<uint8_t*>(map_base_ptr) + cd_start_offset;
+void CentralDirectory::Initialize(const void* map_base_ptr, off64_t cd_start_offset,
+                                  size_t cd_size) {
+  base_ptr_ = static_cast<const uint8_t*>(map_base_ptr) + cd_start_offset;
   length_ = cd_size;
 }
 
diff --git a/libziparchive/zip_archive_private.h b/libziparchive/zip_archive_private.h
index 30a1d72..60fdec0 100644
--- a/libziparchive/zip_archive_private.h
+++ b/libziparchive/zip_archive_private.h
@@ -95,14 +95,14 @@
   explicit MappedZipFile(const int fd)
       : has_fd_(true), fd_(fd), base_ptr_(nullptr), data_length_(0) {}
 
-  explicit MappedZipFile(void* address, size_t length)
+  explicit MappedZipFile(const void* address, size_t length)
       : has_fd_(false), fd_(-1), base_ptr_(address), data_length_(static_cast<off64_t>(length)) {}
 
   bool HasFd() const { return has_fd_; }
 
   int GetFileDescriptor() const;
 
-  void* GetBasePtr() const;
+  const void* GetBasePtr() const;
 
   off64_t GetFileLength() const;
 
@@ -117,7 +117,7 @@
 
   const int fd_;
 
-  void* const base_ptr_;
+  const void* const base_ptr_;
   const off64_t data_length_;
 };
 
@@ -129,7 +129,7 @@
 
   size_t GetMapLength() const { return length_; }
 
-  void Initialize(void* map_base_ptr, off64_t cd_start_offset, size_t cd_size);
+  void Initialize(const void* map_base_ptr, off64_t cd_start_offset, size_t cd_size);
 
  private:
   const uint8_t* base_ptr_;
@@ -177,7 +177,7 @@
   ZipStringOffset* hash_table;
 
   ZipArchive(const int fd, bool assume_ownership);
-  ZipArchive(void* address, size_t length);
+  ZipArchive(const void* address, size_t length);
   ~ZipArchive();
 
   bool InitializeCentralDirectory(off64_t cd_start_offset, size_t cd_size);
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/logd/LogListener.cpp b/logd/LogListener.cpp
index 443570f..ba61042 100644
--- a/logd/LogListener.cpp
+++ b/logd/LogListener.cpp
@@ -41,8 +41,7 @@
     }
 
     // + 1 to ensure null terminator if MAX_PAYLOAD buffer is received
-    char buffer[sizeof_log_id_t + sizeof(uint16_t) + sizeof(log_time) +
-                LOGGER_ENTRY_MAX_PAYLOAD + 1];
+    char buffer[sizeof(android_log_header_t) + LOGGER_ENTRY_MAX_PAYLOAD + 1];
     struct iovec iov = { buffer, sizeof(buffer) - 1 };
 
     alignas(4) char control[CMSG_SPACE(sizeof(struct ucred))];
diff --git a/logd/fuzz/Android.bp b/logd/fuzz/Android.bp
new file mode 100644
index 0000000..3215b24
--- /dev/null
+++ b/logd/fuzz/Android.bp
@@ -0,0 +1,28 @@
+// 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.
+cc_fuzz {
+    name: "log_buffer_log_fuzzer",
+    srcs: [
+        "log_buffer_log_fuzzer.cpp",
+    ],
+    static_libs: [
+        "libbase",
+        "libcutils",
+        "libselinux",
+        "liblog",
+        "liblogd",
+        "libcutils",
+    ],
+    cflags: ["-Werror"],
+}
diff --git a/logd/fuzz/log_buffer_log_fuzzer.cpp b/logd/fuzz/log_buffer_log_fuzzer.cpp
new file mode 100644
index 0000000..be4c7c3
--- /dev/null
+++ b/logd/fuzz/log_buffer_log_fuzzer.cpp
@@ -0,0 +1,98 @@
+/*
+ * 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 "../LogBuffer.h"
+#include "../LogTimes.h"
+
+namespace android {
+struct LogInput {
+  public:
+    log_id_t log_id;  // char
+    log_time realtime;
+    uid_t uid;
+    pid_t pid;
+    pid_t tid;
+};
+
+int write_log_messages(const uint8_t* data, size_t* data_left, LogBuffer* log_buffer) {
+    const LogInput* logInput = reinterpret_cast<const LogInput*>(data);
+    data += sizeof(LogInput);
+    *data_left -= sizeof(LogInput);
+
+    uint8_t tag_length = data[0] % 32;
+    uint8_t msg_length = data[1] % 32;
+    if (tag_length < 2 || msg_length < 2) {
+        // Not enough data for tag and message
+        return 0;
+    }
+
+    data += 2 * sizeof(uint8_t);
+    *data_left -= 2 * sizeof(uint8_t);
+
+    if (*data_left < tag_length + msg_length) {
+        // Not enough data for tag and message
+        return 0;
+    }
+
+    // We need nullterm'd strings
+    char* msg = new char[tag_length + msg_length + 2];
+    char* msg_only = msg + tag_length + 1;
+    memcpy(msg, data, tag_length);
+    msg[tag_length] = '\0';
+    memcpy(msg_only, data, msg_length);
+    msg_only[msg_length] = '\0';
+    data += tag_length + msg_length;
+    *data_left -= tag_length + msg_length;
+
+    // Other elements not in enum.
+    log_id_t log_id = static_cast<log_id_t>(unsigned(logInput->log_id) % (LOG_ID_MAX + 1));
+    log_buffer->log(log_id, logInput->realtime, logInput->uid, logInput->pid, logInput->tid, msg,
+                    tag_length + msg_length + 2);
+    delete[] msg;
+    return 1;
+}
+
+// Because system/core/logd/main.cpp redefines this.
+void prdebug(char const* fmt, ...) {
+    va_list ap;
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    // We want a random tag length and a random remaining message length
+    if (data == nullptr || size < sizeof(LogInput) + 2 * sizeof(uint8_t)) {
+        return 0;
+    }
+
+    LastLogTimes times;
+    LogBuffer log_buffer(&times);
+    size_t data_left = size;
+
+    log_buffer.enableStatistics();
+    // We want to get pruning code to get called.
+    log_id_for_each(i) { log_buffer.setSize(i, 10000); }
+
+    while (data_left >= sizeof(LogInput) + 2 * sizeof(uint8_t)) {
+        if (!write_log_messages(data, &data_left, &log_buffer)) {
+            return 0;
+        }
+    }
+
+    log_id_for_each(i) { log_buffer.clear(i); }
+    return 0;
+}
+}  // namespace android
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 5241730..e1bb02f 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -326,7 +326,7 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
 LOCAL_MODULE_STEM := $(call append_vndk_version,$(LOCAL_MODULE))
 include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_SAMEPROCESS_LIBRARIES := $(call module-installed-files-or-guess,$(VNDK_SAMEPROCESS_LIBRARIES),.com.android.vndk.current)
+$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_SAMEPROCESS_LIBRARIES := $(call module-installed-files-or-guess,$(VNDK_SAMEPROCESS_LIBRARIES),.vendor)
 $(LOCAL_BUILT_MODULE):
 	@echo "Generate: $@"
 	@mkdir -p $(dir $@)
@@ -342,7 +342,7 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
 LOCAL_MODULE_STEM := $(call append_vndk_version,$(LOCAL_MODULE))
 include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_CORE_LIBRARIES := $(call module-installed-files-or-guess,$(VNDK_CORE_LIBRARIES),.com.android.vndk.current)
+$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_CORE_LIBRARIES := $(call module-installed-files-or-guess,$(VNDK_CORE_LIBRARIES),.vendor)
 $(LOCAL_BUILT_MODULE):
 	@echo "Generate: $@"
 	@mkdir -p $(dir $@)
@@ -358,7 +358,7 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
 LOCAL_MODULE_STEM := $(call append_vndk_version,$(LOCAL_MODULE))
 include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_PRIVATE_LIBRARIES := $(call module-installed-files-or-guess,$(VNDK_PRIVATE_LIBRARIES),.com.android.vndk.current)
+$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_PRIVATE_LIBRARIES := $(call module-installed-files-or-guess,$(VNDK_PRIVATE_LIBRARIES),.vendor)
 $(LOCAL_BUILT_MODULE):
 	@echo "Generate: $@"
 	@mkdir -p $(dir $@)