Use adbd_system_binaries to track adbd's dependencies.
am: 7b7ee191dc

Change-Id: Iad5c3797db17e27c311e787a8879a7ea7793f466
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/fastboot/device/commands.h b/fastboot/device/commands.h
index afd6d08..9b6e7b6 100644
--- a/fastboot/device/commands.h
+++ b/fastboot/device/commands.h
@@ -19,7 +19,7 @@
 #include <string>
 #include <vector>
 
-constexpr unsigned int kMaxDownloadSizeDefault = 0x20000000;
+constexpr unsigned int kMaxDownloadSizeDefault = 0x10000000;
 
 class FastbootDevice;
 
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/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/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 69f2895..120340c 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -19,6 +19,7 @@
 #include <chrono>
 #include <map>
 #include <memory>
+#include <optional>
 #include <ostream>
 #include <string>
 #include <string_view>
@@ -49,6 +50,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 +105,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 +119,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 +221,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;
@@ -285,7 +299,8 @@
                      std::string* dev_path);
 
     // Map a COW image that was previous created with CreateCowImage.
-    bool MapCowImage(const std::string& name, const std::chrono::milliseconds& timeout_ms);
+    std::optional<std::string> MapCowImage(const std::string& name,
+                                           const std::chrono::milliseconds& timeout_ms);
 
     // Remove the backing copy-on-write image and snapshot states for the named snapshot. The
     // caller is responsible for ensuring that the snapshot is unmapped.
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 395fb40..2c5eed1 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() {}
@@ -418,9 +450,9 @@
     return true;
 }
 
-bool SnapshotManager::MapCowImage(const std::string& name,
-                                  const std::chrono::milliseconds& timeout_ms) {
-    if (!EnsureImageManager()) return false;
+std::optional<std::string> SnapshotManager::MapCowImage(
+        const std::string& name, const std::chrono::milliseconds& timeout_ms) {
+    if (!EnsureImageManager()) return std::nullopt;
     auto cow_image_name = GetCowImageDeviceName(name);
 
     bool ok;
@@ -436,10 +468,10 @@
 
     if (ok) {
         LOG(INFO) << "Mapped " << cow_image_name << " to " << cow_dev;
-    } else {
-        LOG(ERROR) << "Could not map image device: " << cow_image_name;
+        return cow_dev;
     }
-    return ok;
+    LOG(ERROR) << "Could not map image device: " << cow_image_name;
+    return std::nullopt;
 }
 
 bool SnapshotManager::UnmapSnapshot(LockedFile* lock, const std::string& name) {
@@ -1411,7 +1443,7 @@
         auto remaining_time = GetRemainingTime(params.timeout_ms, begin);
         if (remaining_time.count() < 0) return false;
 
-        if (!MapCowImage(partition_name, remaining_time)) {
+        if (!MapCowImage(partition_name, remaining_time).has_value()) {
             LOG(ERROR) << "Could not map cow image for partition: " << partition_name;
             return false;
         }
@@ -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..f6a4722 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -254,12 +254,11 @@
 
     AssertionResult MapCowImage(const std::string& name,
                                 const std::chrono::milliseconds& timeout_ms, std::string* path) {
-        if (!sm->MapCowImage(name, timeout_ms)) {
+        auto cow_image_path = sm->MapCowImage(name, timeout_ms);
+        if (!cow_image_path.has_value()) {
             return AssertionFailure() << "Cannot map cow image " << name;
         }
-        if (!dm_.GetDmDevicePathByName(name + "-cow-img"s, path)) {
-            return AssertionFailure() << "No path for " << name << "-cow-img";
-        }
+        *path = *cow_image_path;
         return AssertionSuccess();
     }
 
@@ -617,6 +616,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.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 9b2ddc0..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",
@@ -82,7 +82,6 @@
         "libfscrypt",
         "libgsi",
         "libhidl-gen-utils",
-        "libjsoncpp",
         "libkeyutils",
         "liblog",
         "liblogwrap",
@@ -286,13 +285,11 @@
     shared_libs: [
         "libcutils",
         "libhidl-gen-utils",
+        "libhidlmetadata",
         "liblog",
         "libprocessgroup",
         "libprotobuf-cpp-lite",
     ],
-    header_libs: [
-        "libjsoncpp_headers",
-    ],
     srcs: [
         "action.cpp",
         "action_manager.cpp",
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/host_init_verifier.cpp b/init/host_init_verifier.cpp
index b2402b3..522709e 100644
--- a/init/host_init_verifier.cpp
+++ b/init/host_init_verifier.cpp
@@ -30,6 +30,7 @@
 #include <android-base/logging.h>
 #include <android-base/parseint.h>
 #include <android-base/strings.h>
+#include <hidl/metadata.h>
 
 #include "action.h"
 #include "action_manager.h"
@@ -142,28 +143,46 @@
 #include "generated_stub_builtin_function_map.h"
 
 void PrintUsage() {
-    std::cout << "usage: host_init_verifier [-p FILE] -i FILE <init rc file>\n"
+    std::cout << "usage: host_init_verifier [-p FILE] <init rc file>\n"
                  "\n"
                  "Tests an init script for correctness\n"
                  "\n"
                  "-p FILE\tSearch this passwd file for users and groups\n"
-                 "-i FILE\tParse this JSON file for the HIDL interface inheritance hierarchy\n"
               << std::endl;
 }
 
+Result<InterfaceInheritanceHierarchyMap> ReadInterfaceInheritanceHierarchy() {
+    InterfaceInheritanceHierarchyMap result;
+    for (const HidlInterfaceMetadata& iface : HidlInterfaceMetadata::all()) {
+        std::set<FQName> inherited_interfaces;
+        for (const std::string& intf : iface.inherited) {
+            FQName fqname;
+            if (!fqname.setTo(intf)) {
+                return Error() << "Unable to parse interface '" << intf << "'";
+            }
+            inherited_interfaces.insert(fqname);
+        }
+        FQName fqname;
+        if (!fqname.setTo(iface.name)) {
+            return Error() << "Unable to parse interface '" << iface.name << "'";
+        }
+        result[fqname] = inherited_interfaces;
+    }
+
+    return result;
+}
+
 int main(int argc, char** argv) {
     android::base::InitLogging(argv, &android::base::StdioLogger);
     android::base::SetMinimumLogSeverity(android::base::ERROR);
 
-    std::string interface_inheritance_hierarchy_file;
-
     while (true) {
         static const struct option long_options[] = {
                 {"help", no_argument, nullptr, 'h'},
                 {nullptr, 0, nullptr, 0},
         };
 
-        int arg = getopt_long(argc, argv, "p:i:", long_options, nullptr);
+        int arg = getopt_long(argc, argv, "p:", long_options, nullptr);
 
         if (arg == -1) {
             break;
@@ -176,9 +195,6 @@
             case 'p':
                 passwd_files.emplace_back(optarg);
                 break;
-            case 'i':
-                interface_inheritance_hierarchy_file = optarg;
-                break;
             default:
                 std::cerr << "getprop: getopt returned invalid result: " << arg << std::endl;
                 return EXIT_FAILURE;
@@ -188,13 +204,12 @@
     argc -= optind;
     argv += optind;
 
-    if (argc != 1 || interface_inheritance_hierarchy_file.empty()) {
+    if (argc != 1) {
         PrintUsage();
         return EXIT_FAILURE;
     }
 
-    auto interface_inheritance_hierarchy_map =
-            ReadInterfaceInheritanceHierarchy(interface_inheritance_hierarchy_file);
+    auto interface_inheritance_hierarchy_map = ReadInterfaceInheritanceHierarchy();
     if (!interface_inheritance_hierarchy_map) {
         LOG(ERROR) << interface_inheritance_hierarchy_map.error();
         return EXIT_FAILURE;
diff --git a/init/interface_utils.cpp b/init/interface_utils.cpp
index ddbacd7..1b76bba 100644
--- a/init/interface_utils.cpp
+++ b/init/interface_utils.cpp
@@ -21,7 +21,6 @@
 
 #include <android-base/strings.h>
 #include <hidl-util/FqInstance.h>
-#include <json/json.h>
 
 using android::FqInstance;
 using android::FQName;
@@ -42,37 +41,6 @@
 
 }  // namespace
 
-Result<InterfaceInheritanceHierarchyMap> ReadInterfaceInheritanceHierarchy(
-        const std::string& path) {
-    Json::Value root;
-    Json::Reader reader;
-    std::ifstream stream(path);
-    if (!reader.parse(stream, root)) {
-        return Error() << "Failed to read interface inheritance hierarchy file: " << path << "\n"
-                       << reader.getFormattedErrorMessages();
-    }
-
-    InterfaceInheritanceHierarchyMap result;
-    for (const Json::Value& entry : root) {
-        std::set<FQName> inherited_interfaces;
-        for (const Json::Value& intf : entry["inheritedInterfaces"]) {
-            FQName fqname;
-            if (!fqname.setTo(intf.asString())) {
-                return Error() << "Unable to parse interface '" << intf.asString() << "'";
-            }
-            inherited_interfaces.insert(fqname);
-        }
-        std::string intf_string = entry["interface"].asString();
-        FQName fqname;
-        if (!fqname.setTo(intf_string)) {
-            return Error() << "Unable to parse interface '" << intf_string << "'";
-        }
-        result[fqname] = inherited_interfaces;
-    }
-
-    return result;
-}
-
 Result<void> CheckInterfaceInheritanceHierarchy(const std::set<std::string>& instances,
                                                 const InterfaceInheritanceHierarchyMap& hierarchy) {
     std::set<FQName> interface_fqnames;
diff --git a/init/interface_utils.h b/init/interface_utils.h
index bd0c104..4ca377f 100644
--- a/init/interface_utils.h
+++ b/init/interface_utils.h
@@ -29,9 +29,6 @@
 
 using InterfaceInheritanceHierarchyMap = std::map<android::FQName, std::set<android::FQName>>;
 
-// Reads the HIDL interface inheritance hierarchy JSON file at the given path.
-Result<InterfaceInheritanceHierarchyMap> ReadInterfaceInheritanceHierarchy(const std::string& path);
-
 // For the given set of interfaces / interface instances, checks that each
 // interface's hierarchy of inherited interfaces is also included in the given
 // interface set. Uses the provided hierarchy data.
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/liblog/include/android/log.h b/liblog/include/android/log.h
index 2e6210e..7290789 100644
--- a/liblog/include/android/log.h
+++ b/liblog/include/android/log.h
@@ -124,8 +124,6 @@
 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().
@@ -152,7 +150,6 @@
 
   LOG_ID_MAX
 } log_id_t;
-#endif
 
 /**
  * Writes the constant string `text` to the log buffer `id`,
diff --git a/liblog/include/log/log_id.h b/liblog/include/log/log_id.h
index 4c6d809..c8fafe7 100644
--- a/liblog/include/log/log_id.h
+++ b/liblog/include/log/log_id.h
@@ -16,30 +16,12 @@
 
 #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.
  */
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/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/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/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/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/init.rc b/rootdir/init.rc
index c5bf1603..674ed01 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -754,6 +754,7 @@
     # to make it too large, since it may bring userdata loss, if they
     # are not aware of using fsync()/sync() to prepare sudden power-cut.
     write /sys/fs/f2fs/${dev.mnt.blk.data}/cp_interval 200
+    write /sys/fs/f2fs/${dev.mnt.blk.data}/gc_urgent_sleep_time 50
 
     # Permissions for System Server and daemons.
     chown system system /sys/power/autosleep