Merge "Add vts10 suite to existing vts tests"
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index f28c778..c7bd1a8 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -103,9 +103,14 @@
     export_include_dirs: ["include"],
 }
 
-// Fallback implementation.
+// Fallback implementation, for use in the Bionic linker only.
 cc_library_static {
     name: "libdebuggerd_handler_fallback",
+    visibility: ["//bionic/linker"],
+    apex_available: [
+        "com.android.runtime",
+        "//apex_available:platform",
+    ],
     defaults: ["debuggerd_defaults"],
     recovery_available: true,
     srcs: [
@@ -118,8 +123,7 @@
         "libasync_safe",
         "libbase",
         "libdebuggerd",
-        "libunwindstack",
-        "libdexfile_support_static",  // libunwindstack dependency
+        "libunwindstack_no_dex",
         "liblzma",
         "libcutils",
     ],
@@ -127,14 +131,6 @@
     header_libs: ["bionic_libc_platform_headers"],
     export_header_lib_headers: ["bionic_libc_platform_headers"],
 
-    target: {
-        recovery: {
-            exclude_static_libs: [
-                "libdexfile_support_static",
-            ],
-        },
-    },
-
     export_include_dirs: ["include"],
 }
 
@@ -188,7 +184,7 @@
     ],
 
     static_libs: [
-        "libdexfile_support_static",  // libunwindstack dependency
+        "libdexfile_support",  // libunwindstack dependency
         "libunwindstack",
         "liblzma",
         "libbase",
@@ -201,7 +197,7 @@
     target: {
         recovery: {
             exclude_static_libs: [
-                "libdexfile_support_static",
+                "libdexfile_support",
             ],
         },
     },
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index b3f059c..bb3c260 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -457,8 +457,8 @@
     return;
   }
 
-  logger_list = android_logger_list_open(
-      android_name_to_log_id(filename), ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, tail, pid);
+  logger_list =
+      android_logger_list_open(android_name_to_log_id(filename), ANDROID_LOG_NONBLOCK, tail, pid);
 
   if (!logger_list) {
     ALOGE("Unable to open %s: %s\n", filename, strerror(errno));
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 957c26c..5c276b4 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -230,8 +230,14 @@
     // devices;
     // - CreateResult::ERROR if a fatal error occurred, mounting /system should
     // be aborted.
+    // This function mounts /metadata when called, and unmounts /metadata upon
+    // return.
     CreateResult RecoveryCreateSnapshotDevices();
 
+    // Same as RecoveryCreateSnapshotDevices(), but does not auto mount/umount
+    // /metadata.
+    CreateResult RecoveryCreateSnapshotDevices(const std::unique_ptr<AutoDevice>& metadata_device);
+
     // Dump debug information.
     bool Dump(std::ostream& os);
 
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index ed052b1..1eec6a4 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -2587,6 +2587,20 @@
         LOG(ERROR) << "Couldn't mount Metadata.";
         return CreateResult::NOT_CREATED;
     }
+    return RecoveryCreateSnapshotDevices(mount);
+}
+
+CreateResult SnapshotManager::RecoveryCreateSnapshotDevices(
+        const std::unique_ptr<AutoDevice>& metadata_device) {
+    if (!device_->IsRecovery()) {
+        LOG(ERROR) << __func__ << " is only allowed in recovery.";
+        return CreateResult::NOT_CREATED;
+    }
+
+    if (metadata_device == nullptr || !metadata_device->HasDevice()) {
+        LOG(ERROR) << "Metadata not mounted.";
+        return CreateResult::NOT_CREATED;
+    }
 
     auto state_file = GetStateFilePath();
     if (access(state_file.c_str(), F_OK) != 0 && errno == ENOENT) {
diff --git a/init/Android.bp b/init/Android.bp
index 948734d..d512a4e 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -36,6 +36,7 @@
     "util.cpp",
 ]
 init_device_sources = [
+    "block_dev_initializer.cpp",
     "bootchart.cpp",
     "builtins.cpp",
     "devices.cpp",
diff --git a/init/Android.mk b/init/Android.mk
index 07b0f95..b49fb3b 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -48,6 +48,7 @@
 include $(CLEAR_VARS)
 LOCAL_CPPFLAGS := $(init_cflags)
 LOCAL_SRC_FILES := \
+    block_dev_initializer.cpp \
     devices.cpp \
     first_stage_init.cpp \
     first_stage_main.cpp \
@@ -105,9 +106,8 @@
     libgsi \
     libcom.android.sysprop.apex \
     liblzma \
-    libdexfile_support_static \
-    libunwindstack \
-    libbacktrace \
+    libunwindstack_no_dex \
+    libbacktrace_no_dex \
     libmodprobe \
     libext2_uuid \
     libprotobuf-cpp-lite \
diff --git a/init/block_dev_initializer.cpp b/init/block_dev_initializer.cpp
new file mode 100644
index 0000000..b423f86
--- /dev/null
+++ b/init/block_dev_initializer.cpp
@@ -0,0 +1,148 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <chrono>
+#include <string_view>
+#include <vector>
+
+#include <android-base/chrono_utils.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <fs_mgr.h>
+
+#include "block_dev_initializer.h"
+
+namespace android {
+namespace init {
+
+using android::base::Timer;
+using namespace std::chrono_literals;
+
+BlockDevInitializer::BlockDevInitializer() : uevent_listener_(16 * 1024 * 1024) {
+    auto boot_devices = android::fs_mgr::GetBootDevices();
+    device_handler_ = std::make_unique<DeviceHandler>(
+            std::vector<Permissions>{}, std::vector<SysfsPermissions>{}, std::vector<Subsystem>{},
+            std::move(boot_devices), false);
+}
+
+bool BlockDevInitializer::InitDeviceMapper() {
+    const std::string dm_path = "/devices/virtual/misc/device-mapper";
+    bool found = false;
+    auto dm_callback = [this, &dm_path, &found](const Uevent& uevent) {
+        if (uevent.path == dm_path) {
+            device_handler_->HandleUevent(uevent);
+            found = true;
+            return ListenerAction::kStop;
+        }
+        return ListenerAction::kContinue;
+    };
+    uevent_listener_.RegenerateUeventsForPath("/sys" + dm_path, dm_callback);
+    if (!found) {
+        LOG(INFO) << "device-mapper device not found in /sys, waiting for its uevent";
+        Timer t;
+        uevent_listener_.Poll(dm_callback, 10s);
+        LOG(INFO) << "Wait for device-mapper returned after " << t;
+    }
+    if (!found) {
+        LOG(ERROR) << "device-mapper device not found after polling timeout";
+        return false;
+    }
+    return true;
+}
+
+ListenerAction BlockDevInitializer::HandleUevent(const Uevent& uevent,
+                                                 std::set<std::string>* devices) {
+    // Ignore everything that is not a block device.
+    if (uevent.subsystem != "block") {
+        return ListenerAction::kContinue;
+    }
+
+    auto name = uevent.partition_name;
+    if (name.empty()) {
+        size_t base_idx = uevent.path.rfind('/');
+        if (base_idx == std::string::npos) {
+            return ListenerAction::kContinue;
+        }
+        name = uevent.path.substr(base_idx + 1);
+    }
+
+    auto iter = devices->find(name);
+    if (iter == devices->end()) {
+        return ListenerAction::kContinue;
+    }
+
+    LOG(VERBOSE) << __PRETTY_FUNCTION__ << ": found partition: " << name;
+
+    devices->erase(iter);
+    device_handler_->HandleUevent(uevent);
+    return devices->empty() ? ListenerAction::kStop : ListenerAction::kContinue;
+}
+
+bool BlockDevInitializer::InitDevices(std::set<std::string> devices) {
+    auto uevent_callback = [&, this](const Uevent& uevent) -> ListenerAction {
+        return HandleUevent(uevent, &devices);
+    };
+    uevent_listener_.RegenerateUevents(uevent_callback);
+
+    // UeventCallback() will remove found partitions from |devices|. So if it
+    // isn't empty here, it means some partitions are not found.
+    if (!devices.empty()) {
+        LOG(INFO) << __PRETTY_FUNCTION__
+                  << ": partition(s) not found in /sys, waiting for their uevent(s): "
+                  << android::base::Join(devices, ", ");
+        Timer t;
+        uevent_listener_.Poll(uevent_callback, 10s);
+        LOG(INFO) << "Wait for partitions returned after " << t;
+    }
+
+    if (!devices.empty()) {
+        LOG(ERROR) << __PRETTY_FUNCTION__ << ": partition(s) not found after polling timeout: "
+                   << android::base::Join(devices, ", ");
+        return false;
+    }
+    return true;
+}
+
+// Creates "/dev/block/dm-XX" for dm nodes by running coldboot on /sys/block/dm-XX.
+bool BlockDevInitializer::InitDmDevice(const std::string& device) {
+    const std::string device_name(basename(device.c_str()));
+    const std::string syspath = "/sys/block/" + device_name;
+    bool found = false;
+
+    auto uevent_callback = [&device_name, &device, this, &found](const Uevent& uevent) {
+        if (uevent.device_name == device_name) {
+            LOG(VERBOSE) << "Creating device-mapper device : " << device;
+            device_handler_->HandleUevent(uevent);
+            found = true;
+            return ListenerAction::kStop;
+        }
+        return ListenerAction::kContinue;
+    };
+
+    uevent_listener_.RegenerateUeventsForPath(syspath, uevent_callback);
+    if (!found) {
+        LOG(INFO) << "dm device '" << device << "' not found in /sys, waiting for its uevent";
+        Timer t;
+        uevent_listener_.Poll(uevent_callback, 10s);
+        LOG(INFO) << "wait for dm device '" << device << "' returned after " << t;
+    }
+    if (!found) {
+        LOG(ERROR) << "dm device '" << device << "' not found after polling timeout";
+        return false;
+    }
+    return true;
+}
+
+}  // namespace init
+}  // namespace android
diff --git a/init/block_dev_initializer.h b/init/block_dev_initializer.h
new file mode 100644
index 0000000..0d4c6e9
--- /dev/null
+++ b/init/block_dev_initializer.h
@@ -0,0 +1,41 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <memory>
+#include <set>
+#include <string>
+
+#include "devices.h"
+#include "uevent_listener.h"
+
+namespace android {
+namespace init {
+
+class BlockDevInitializer final {
+  public:
+    BlockDevInitializer();
+
+    bool InitDeviceMapper();
+    bool InitDevices(std::set<std::string> devices);
+    bool InitDmDevice(const std::string& device);
+
+  private:
+    ListenerAction HandleUevent(const Uevent& uevent, std::set<std::string>* devices);
+
+    std::unique_ptr<DeviceHandler> device_handler_;
+    UeventListener uevent_listener_;
+};
+
+}  // namespace init
+}  // namespace android
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 3451264..8eb2f97 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -42,6 +42,7 @@
 #include <liblp/liblp.h>
 #include <libsnapshot/snapshot.h>
 
+#include "block_dev_initializer.h"
 #include "devices.h"
 #include "switch_root.h"
 #include "uevent.h"
@@ -84,11 +85,7 @@
     bool InitDevices();
 
   protected:
-    ListenerAction HandleBlockDevice(const std::string& name, const Uevent&,
-                                     std::set<std::string>* required_devices);
     bool InitRequiredDevices(std::set<std::string> devices);
-    bool InitMappedDevice(const std::string& verity_device);
-    bool InitDeviceMapper();
     bool CreateLogicalPartitions();
     bool MountPartition(const Fstab::iterator& begin, bool erase_same_mounts,
                         Fstab::iterator* end = nullptr);
@@ -106,8 +103,6 @@
     // revocation check by DSU installation service.
     void CopyDsuAvbKeys();
 
-    ListenerAction UeventCallback(const Uevent& uevent, std::set<std::string>* required_devices);
-
     // Pure virtual functions.
     virtual bool GetDmVerityDevices(std::set<std::string>* devices) = 0;
     virtual bool SetUpDmVerity(FstabEntry* fstab_entry) = 0;
@@ -119,8 +114,7 @@
     // The super path is only set after InitDevices, and is invalid before.
     std::string super_path_;
     std::string super_partition_name_;
-    std::unique_ptr<DeviceHandler> device_handler_;
-    UeventListener uevent_listener_;
+    BlockDevInitializer block_dev_init_;
     // Reads all AVB keys before chroot into /system, as they might be used
     // later when mounting other partitions, e.g., /vendor and /product.
     std::map<std::string, std::vector<std::string>> preload_avb_key_blobs_;
@@ -234,13 +228,7 @@
 
 // Class Definitions
 // -----------------
-FirstStageMount::FirstStageMount(Fstab fstab)
-    : need_dm_verity_(false), fstab_(std::move(fstab)), uevent_listener_(16 * 1024 * 1024) {
-    auto boot_devices = android::fs_mgr::GetBootDevices();
-    device_handler_ = std::make_unique<DeviceHandler>(
-            std::vector<Permissions>{}, std::vector<SysfsPermissions>{}, std::vector<Subsystem>{},
-            std::move(boot_devices), false);
-
+FirstStageMount::FirstStageMount(Fstab fstab) : need_dm_verity_(false), fstab_(std::move(fstab)) {
     super_partition_name_ = fs_mgr_get_super_partition_name();
 }
 
@@ -308,62 +296,13 @@
 // Found partitions will then be removed from it for the subsequent member
 // function to check which devices are NOT created.
 bool FirstStageMount::InitRequiredDevices(std::set<std::string> devices) {
-    if (!InitDeviceMapper()) {
+    if (!block_dev_init_.InitDeviceMapper()) {
         return false;
     }
-
     if (devices.empty()) {
         return true;
     }
-
-    auto uevent_callback = [&, this](const Uevent& uevent) {
-        return UeventCallback(uevent, &devices);
-    };
-    uevent_listener_.RegenerateUevents(uevent_callback);
-
-    // UeventCallback() will remove found partitions from |devices|. So if it
-    // isn't empty here, it means some partitions are not found.
-    if (!devices.empty()) {
-        LOG(INFO) << __PRETTY_FUNCTION__
-                  << ": partition(s) not found in /sys, waiting for their uevent(s): "
-                  << android::base::Join(devices, ", ");
-        Timer t;
-        uevent_listener_.Poll(uevent_callback, 10s);
-        LOG(INFO) << "Wait for partitions returned after " << t;
-    }
-
-    if (!devices.empty()) {
-        LOG(ERROR) << __PRETTY_FUNCTION__ << ": partition(s) not found after polling timeout: "
-                   << android::base::Join(devices, ", ");
-        return false;
-    }
-
-    return true;
-}
-
-bool FirstStageMount::InitDeviceMapper() {
-    const std::string dm_path = "/devices/virtual/misc/device-mapper";
-    bool found = false;
-    auto dm_callback = [this, &dm_path, &found](const Uevent& uevent) {
-        if (uevent.path == dm_path) {
-            device_handler_->HandleUevent(uevent);
-            found = true;
-            return ListenerAction::kStop;
-        }
-        return ListenerAction::kContinue;
-    };
-    uevent_listener_.RegenerateUeventsForPath("/sys" + dm_path, dm_callback);
-    if (!found) {
-        LOG(INFO) << "device-mapper device not found in /sys, waiting for its uevent";
-        Timer t;
-        uevent_listener_.Poll(dm_callback, 10s);
-        LOG(INFO) << "Wait for device-mapper returned after " << t;
-    }
-    if (!found) {
-        LOG(ERROR) << "device-mapper device not found after polling timeout";
-        return false;
-    }
-    return true;
+    return block_dev_init_.InitDevices(std::move(devices));
 }
 
 bool FirstStageMount::InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata) {
@@ -419,75 +358,6 @@
     return android::fs_mgr::CreateLogicalPartitions(*metadata.get(), super_path_);
 }
 
-ListenerAction FirstStageMount::HandleBlockDevice(const std::string& name, const Uevent& uevent,
-                                                  std::set<std::string>* required_devices) {
-    // Matches partition name to create device nodes.
-    // Both required_devices_partition_names_ and uevent->partition_name have A/B
-    // suffix when A/B is used.
-    auto iter = required_devices->find(name);
-    if (iter != required_devices->end()) {
-        LOG(VERBOSE) << __PRETTY_FUNCTION__ << ": found partition: " << *iter;
-        required_devices->erase(iter);
-        device_handler_->HandleUevent(uevent);
-        if (required_devices->empty()) {
-            return ListenerAction::kStop;
-        } else {
-            return ListenerAction::kContinue;
-        }
-    }
-    return ListenerAction::kContinue;
-}
-
-ListenerAction FirstStageMount::UeventCallback(const Uevent& uevent,
-                                               std::set<std::string>* required_devices) {
-    // Ignores everything that is not a block device.
-    if (uevent.subsystem != "block") {
-        return ListenerAction::kContinue;
-    }
-
-    if (!uevent.partition_name.empty()) {
-        return HandleBlockDevice(uevent.partition_name, uevent, required_devices);
-    } else {
-        size_t base_idx = uevent.path.rfind('/');
-        if (base_idx != std::string::npos) {
-            return HandleBlockDevice(uevent.path.substr(base_idx + 1), uevent, required_devices);
-        }
-    }
-    // Not found a partition or find an unneeded partition, continue to find others.
-    return ListenerAction::kContinue;
-}
-
-// Creates "/dev/block/dm-XX" for dm-verity by running coldboot on /sys/block/dm-XX.
-bool FirstStageMount::InitMappedDevice(const std::string& dm_device) {
-    const std::string device_name(basename(dm_device.c_str()));
-    const std::string syspath = "/sys/block/" + device_name;
-    bool found = false;
-
-    auto verity_callback = [&device_name, &dm_device, this, &found](const Uevent& uevent) {
-        if (uevent.device_name == device_name) {
-            LOG(VERBOSE) << "Creating device-mapper device : " << dm_device;
-            device_handler_->HandleUevent(uevent);
-            found = true;
-            return ListenerAction::kStop;
-        }
-        return ListenerAction::kContinue;
-    };
-
-    uevent_listener_.RegenerateUeventsForPath(syspath, verity_callback);
-    if (!found) {
-        LOG(INFO) << "dm device '" << dm_device << "' not found in /sys, waiting for its uevent";
-        Timer t;
-        uevent_listener_.Poll(verity_callback, 10s);
-        LOG(INFO) << "wait for dm device '" << dm_device << "' returned after " << t;
-    }
-    if (!found) {
-        LOG(ERROR) << "dm device '" << dm_device << "' not found after polling timeout";
-        return false;
-    }
-
-    return true;
-}
-
 bool FirstStageMount::MountPartition(const Fstab::iterator& begin, bool erase_same_mounts,
                                      Fstab::iterator* end) {
     // Sets end to begin + 1, so we can just return on failure below.
@@ -499,7 +369,7 @@
         if (!fs_mgr_update_logical_partition(&(*begin))) {
             return false;
         }
-        if (!InitMappedDevice(begin->blk_device)) {
+        if (!block_dev_init_.InitDmDevice(begin->blk_device)) {
             return false;
         }
     }
@@ -666,7 +536,9 @@
     auto init_devices = [this](std::set<std::string> devices) -> bool {
         for (auto iter = devices.begin(); iter != devices.end();) {
             if (android::base::StartsWith(*iter, "/dev/block/dm-")) {
-                if (!InitMappedDevice(*iter)) return false;
+                if (!block_dev_init_.InitDmDevice(*iter)) {
+                    return false;
+                }
                 iter = devices.erase(iter);
             } else {
                 iter++;
@@ -782,7 +654,7 @@
                 // The exact block device name (fstab_rec->blk_device) is changed to
                 // "/dev/block/dm-XX". Needs to create it because ueventd isn't started in init
                 // first stage.
-                return InitMappedDevice(fstab_entry->blk_device);
+                return block_dev_init_.InitDmDevice(fstab_entry->blk_device);
             default:
                 return false;
         }
@@ -902,7 +774,7 @@
             // The exact block device name (fstab_rec->blk_device) is changed to
             // "/dev/block/dm-XX". Needs to create it because ueventd isn't started in init
             // first stage.
-            return InitMappedDevice(fstab_entry->blk_device);
+            return block_dev_init_.InitDmDevice(fstab_entry->blk_device);
         default:
             return false;
     }
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index 76caadc..dc989a0 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -50,20 +50,9 @@
     ],
 }
 
-cc_library {
-    name: "libbacktrace",
-    vendor_available: false,
-    recovery_available: true,
-    apex_available: [
-        "//apex_available:platform",
-        "//apex_available:anyapex",
-    ],
-    vndk: {
-        enabled: true,
-        support_system_process: true,
-    },
+cc_defaults {
+    name: "libbacktrace_defaults",
     defaults: ["libbacktrace_common"],
-    host_supported: true,
 
     cflags: [
         "-Wexit-time-destructors",
@@ -88,7 +77,6 @@
             shared_libs: [
                 "libbase",
                 "liblog",
-                "libunwindstack",
             ],
 
             static_libs: [
@@ -101,6 +89,30 @@
                 whole_static_libs: ["libasync_safe"],
             },
         },
+    },
+}
+
+cc_library {
+    name: "libbacktrace",
+    vendor_available: false,
+    recovery_available: true,
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
+    host_supported: true,
+    defaults: ["libbacktrace_defaults"],
+
+    target: {
+        linux: {
+            shared_libs: [
+                "libunwindstack",
+            ],
+        },
         vendor: {
             cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
         },
@@ -110,6 +122,21 @@
     },
 }
 
+// Static library without DEX support to avoid dependencies on the ART APEX.
+cc_library_static {
+    name: "libbacktrace_no_dex",
+    visibility: ["//system/core/debuggerd"],
+    defaults: ["libbacktrace_defaults"],
+    cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
+    target: {
+        linux: {
+            static_libs: [
+                "libunwindstack_no_dex",
+            ],
+        },
+    },
+}
+
 cc_test_library {
     name: "libbacktrace_test",
     defaults: ["libbacktrace_common"],
diff --git a/liblog/README.md b/liblog/README.md
index 871399a..f64f376 100644
--- a/liblog/README.md
+++ b/liblog/README.md
@@ -118,10 +118,9 @@
 finally a call closing the logs.  A single log can be opened with `android_logger_list_open()`; or
 multiple logs can be opened with `android_logger_list_alloc()`, calling in turn the
 `android_logger_open()` for each log id.  Each entry can be retrieved with
-`android_logger_list_read()`.  The log(s) can be closed with `android_logger_list_free()`.  The logs
-should be opened with an `ANDROID_LOG_RDONLY` mode.  `ANDROID_LOG_NONBLOCK` mode will report when
-the log reading is done with an `EAGAIN` error return code, otherwise the
-`android_logger_list_read()` call will block for new entries.
+`android_logger_list_read()`.  The log(s) can be closed with `android_logger_list_free()`.
+`ANDROID_LOG_NONBLOCK` mode will report when the log reading is done with an `EAGAIN` error return 
+code, otherwise the `android_logger_list_read()` call will block for new entries.
 
 The `ANDROID_LOG_WRAP` mode flag to the `android_logger_list_alloc_time()` signals logd to quiesce
 the reader until the buffer is about to prune at the start time then proceed to dumping content.
@@ -130,14 +129,12 @@
 logs to the persistent logs from before the last reboot.
 
 The value returned by `android_logger_open()` can be used as a parameter to the
-`android_logger_clear()` function to empty the sub-log.  It is recommended to only open log
-`ANDROID_LOG_WRONLY` in that case.
+`android_logger_clear()` function to empty the sub-log.
 
 The value returned by `android_logger_open()` can be used as a parameter to the
 `android_logger_get_log_(size|readable_size|version)` to retrieve the sub-log maximum size, readable
 size and log buffer format protocol version respectively.  `android_logger_get_id()` returns the id
-that was used when opening the sub-log.  It is recommended to open the log `ANDROID_LOG_RDONLY` in
-these cases.
+that was used when opening the sub-log.
 
 Errors
 ------
diff --git a/liblog/include/log/log_read.h b/liblog/include/log/log_read.h
index 18c1c33..05ad25f 100644
--- a/liblog/include/log/log_read.h
+++ b/liblog/include/log/log_read.h
@@ -141,10 +141,6 @@
                                       char* buf, size_t len);
 int android_logger_set_prune_list(struct logger_list* logger_list, const char* buf, size_t len);
 
-#define ANDROID_LOG_RDONLY O_RDONLY
-#define ANDROID_LOG_WRONLY O_WRONLY
-#define ANDROID_LOG_RDWR O_RDWR
-#define ANDROID_LOG_ACCMODE O_ACCMODE
 #ifndef O_NONBLOCK
 #define ANDROID_LOG_NONBLOCK 0x00000800
 #else
diff --git a/liblog/pmsg_reader.cpp b/liblog/pmsg_reader.cpp
index 64a92b7..129d767 100644
--- a/liblog/pmsg_reader.cpp
+++ b/liblog/pmsg_reader.cpp
@@ -185,7 +185,7 @@
   /* Add just enough clues in logger_list and transp to make API function */
   memset(&logger_list, 0, sizeof(logger_list));
 
-  logger_list.mode = ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK | ANDROID_LOG_RDONLY;
+  logger_list.mode = ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK;
   logger_list.log_mask = (unsigned)-1;
   if (logId != LOG_ID_ANY) {
     logger_list.log_mask = (1 << logId);
diff --git a/liblog/tests/libc_test.cpp b/liblog/tests/libc_test.cpp
index 3534eb8..1f26263 100644
--- a/liblog/tests/libc_test.cpp
+++ b/liblog/tests/libc_test.cpp
@@ -22,6 +22,10 @@
 TEST(libc, __pstore_append) {
 #ifdef __ANDROID__
 #ifndef NO_PSTORE
+  if (access("/dev/pmsg0", W_OK) != 0) {
+    GTEST_SKIP() << "pmsg0 not found, skipping test";
+  }
+
   FILE* fp;
   ASSERT_TRUE(NULL != (fp = fopen("/dev/pmsg0", "ae")));
   static const char message[] = "libc.__pstore_append\n";
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index 4366f3d..3a6ed90 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -648,8 +648,7 @@
 static void BM_log_latency(benchmark::State& state) {
   pid_t pid = getpid();
 
-  struct logger_list* logger_list =
-      android_logger_list_open(LOG_ID_EVENTS, ANDROID_LOG_RDONLY, 0, pid);
+  struct logger_list* logger_list = android_logger_list_open(LOG_ID_EVENTS, 0, 0, pid);
 
   if (!logger_list) {
     fprintf(stderr, "Unable to open events log: %s\n", strerror(errno));
@@ -723,8 +722,7 @@
 static void BM_log_delay(benchmark::State& state) {
   pid_t pid = getpid();
 
-  struct logger_list* logger_list =
-      android_logger_list_open(LOG_ID_EVENTS, ANDROID_LOG_RDONLY, 0, pid);
+  struct logger_list* logger_list = android_logger_list_open(LOG_ID_EVENTS, 0, 0, pid);
 
   if (!logger_list) {
     fprintf(stderr, "Unable to open events log: %s\n", strerror(errno));
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index a60d2df..a031531 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -82,7 +82,7 @@
   pid_t pid = getpid();
 
   auto logger_list = std::unique_ptr<struct logger_list, ListCloser>{
-      android_logger_list_open(log_buffer, ANDROID_LOG_RDONLY, 1000, pid)};
+      android_logger_list_open(log_buffer, 0, 1000, pid)};
   ASSERT_TRUE(logger_list);
 
   write_messages();
@@ -106,7 +106,7 @@
   }
 
   auto logger_list_non_block = std::unique_ptr<struct logger_list, ListCloser>{
-      android_logger_list_open(log_buffer, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)};
+      android_logger_list_open(log_buffer, ANDROID_LOG_NONBLOCK, 1000, pid)};
   ASSERT_TRUE(logger_list_non_block);
 
   size_t count = 0;
@@ -160,7 +160,6 @@
   return ret;
 }
 
-#ifndef NO_PSTORE
 static bool isPmsgActive() {
   pid_t pid = getpid();
 
@@ -170,7 +169,6 @@
 
   return std::string::npos != myPidFds.find(" -> /dev/pmsg0");
 }
-#endif /* NO_PSTORE */
 
 static bool isLogdwActive() {
   std::string logdwSignature =
@@ -222,16 +220,18 @@
   log_time ts(CLOCK_MONOTONIC);
   log_time ts1(ts);
 
+  bool has_pstore = access("/dev/pmsg0", W_OK) == 0;
+
   auto write_function = [&] {
     EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
     // Check that we can close and reopen the logger
     bool logdwActiveAfter__android_log_btwrite;
     if (getuid() == AID_ROOT) {
       tested__android_log_close = true;
-#ifndef NO_PSTORE
-      bool pmsgActiveAfter__android_log_btwrite = isPmsgActive();
-      EXPECT_TRUE(pmsgActiveAfter__android_log_btwrite);
-#endif /* NO_PSTORE */
+      if (has_pstore) {
+        bool pmsgActiveAfter__android_log_btwrite = isPmsgActive();
+        EXPECT_TRUE(pmsgActiveAfter__android_log_btwrite);
+      }
       logdwActiveAfter__android_log_btwrite = isLogdwActive();
       EXPECT_TRUE(logdwActiveAfter__android_log_btwrite);
     } else if (!tested__android_log_close) {
@@ -239,10 +239,10 @@
     }
     __android_log_close();
     if (getuid() == AID_ROOT) {
-#ifndef NO_PSTORE
-      bool pmsgActiveAfter__android_log_close = isPmsgActive();
-      EXPECT_FALSE(pmsgActiveAfter__android_log_close);
-#endif /* NO_PSTORE */
+      if (has_pstore) {
+        bool pmsgActiveAfter__android_log_close = isPmsgActive();
+        EXPECT_FALSE(pmsgActiveAfter__android_log_close);
+      }
       bool logdwActiveAfter__android_log_close = isLogdwActive();
       EXPECT_FALSE(logdwActiveAfter__android_log_close);
     }
@@ -250,10 +250,10 @@
     ts1 = log_time(CLOCK_MONOTONIC);
     EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1)));
     if (getuid() == AID_ROOT) {
-#ifndef NO_PSTORE
-      bool pmsgActiveAfter__android_log_btwrite = isPmsgActive();
-      EXPECT_TRUE(pmsgActiveAfter__android_log_btwrite);
-#endif /* NO_PSTORE */
+      if (has_pstore) {
+        bool pmsgActiveAfter__android_log_btwrite = isPmsgActive();
+        EXPECT_TRUE(pmsgActiveAfter__android_log_btwrite);
+      }
       logdwActiveAfter__android_log_btwrite = isLogdwActive();
       EXPECT_TRUE(logdwActiveAfter__android_log_btwrite);
     }
@@ -572,8 +572,7 @@
 
   v += pid & 0xFFFF;
 
-  ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
-                           LOG_ID_EVENTS, ANDROID_LOG_RDONLY, 1000, pid)));
+  ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(LOG_ID_EVENTS, 0, 1000, pid)));
 
   int count = 0;
 
@@ -728,8 +727,7 @@
 
   v += pid & 0xFFFF;
 
-  ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
-                           LOG_ID_EVENTS, ANDROID_LOG_RDONLY, 1000, pid)));
+  ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(LOG_ID_EVENTS, 0, 1000, pid)));
 
   int count = 0;
 
@@ -1093,11 +1091,11 @@
   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)};
+      android_logger_list_open(LOG_ID_MAIN, 0, 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)};
+      android_logger_list_open(LOG_ID_MAIN, 0, expected_count2, pid)};
   ASSERT_TRUE(logger_list2);
 
   for (int i = 25; i > 0; --i) {
@@ -1128,14 +1126,12 @@
   }
 
   // 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)};
+  auto logger_list_non_block1 = std::unique_ptr<struct logger_list, ListCloser>{
+      android_logger_list_open(LOG_ID_MAIN, 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)};
+  auto logger_list_non_block2 = std::unique_ptr<struct logger_list, ListCloser>{
+      android_logger_list_open(LOG_ID_MAIN, ANDROID_LOG_NONBLOCK, expected_count2, pid)};
   ASSERT_TRUE(logger_list_non_block2);
   count1 = 0;
   count2 = 0;
@@ -1542,8 +1538,8 @@
 
   pid_t pid = getpid();
 
-  struct logger_list* logger_list = android_logger_list_open(
-      LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid);
+  struct logger_list* logger_list =
+      android_logger_list_open(LOG_ID_EVENTS, ANDROID_LOG_NONBLOCK, 1000, pid);
 
   int count = 0;
   if (logger_list == NULL) return count;
@@ -1832,10 +1828,8 @@
   gid = getgid();
   pid_t pid = getpid();
 
-  ASSERT_TRUE(NULL !=
-              (logger_list = android_logger_list_open(
-                   LOG_ID_SECURITY, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-                   1000, pid)));
+  ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(LOG_ID_SECURITY, ANDROID_LOG_NONBLOCK,
+                                                              1000, pid)));
 
   log_time ts(CLOCK_MONOTONIC);
 
diff --git a/liblog/tests/log_read_test.cpp b/liblog/tests/log_read_test.cpp
index 1be99aa..3e09617 100644
--- a/liblog/tests/log_read_test.cpp
+++ b/liblog/tests/log_read_test.cpp
@@ -34,8 +34,7 @@
   // This test assumes the log buffers are filled with noise from
   // normal operations. It will fail if done immediately after a
   // logcat -c.
-  struct logger_list* logger_list =
-      android_logger_list_alloc(ANDROID_LOG_WRONLY, 0, 0);
+  struct logger_list* logger_list = android_logger_list_alloc(0, 0, 0);
 
   for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
     log_id_t id = static_cast<log_id_t>(i);
diff --git a/liblog/tests/log_wrap_test.cpp b/liblog/tests/log_wrap_test.cpp
index e06964f..755898a 100644
--- a/liblog/tests/log_wrap_test.cpp
+++ b/liblog/tests/log_wrap_test.cpp
@@ -32,7 +32,7 @@
 static void read_with_wrap() {
   // Read the last line in the log to get a starting timestamp. We're assuming
   // the log is not empty.
-  const int mode = ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK;
+  const int mode = ANDROID_LOG_NONBLOCK;
   struct logger_list* logger_list =
       android_logger_list_open(LOG_ID_MAIN, mode, 1000, 0);
 
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 36449eb..9afc9a3 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -35,20 +35,13 @@
     },
 }
 
-cc_library {
-    name: "libunwindstack",
-    vendor_available: true,
-    recovery_available: true,
-    vndk: {
-        enabled: true,
-        support_system_process: true,
-    },
+cc_defaults {
+    name: "libunwindstack_defaults",
     defaults: ["libunwindstack_flags"],
     export_include_dirs: ["include"],
 
     srcs: [
         "ArmExidx.cpp",
-        "DexFile.cpp",
         "DexFiles.cpp",
         "DwarfCfa.cpp",
         "DwarfEhFrameWithHdr.cpp",
@@ -77,7 +70,6 @@
     ],
 
     cflags: [
-        "-DDEXFILE_SUPPORT",
         "-Wexit-time-destructors",
     ],
 
@@ -89,24 +81,6 @@
                 "-g",
             ],
         },
-        vendor: {
-            cflags: ["-UDEXFILE_SUPPORT"],
-            exclude_srcs: [
-                "DexFile.cpp",
-            ],
-            exclude_shared_libs: [
-                "libdexfile_support",
-            ],
-        },
-        recovery: {
-            cflags: ["-UDEXFILE_SUPPORT"],
-            exclude_srcs: [
-                "DexFile.cpp",
-            ],
-            exclude_shared_libs: [
-                "libdexfile_support",
-            ],
-        },
     },
 
     arch: {
@@ -124,12 +98,56 @@
 
     shared_libs: [
         "libbase",
-        "libdexfile_support",
         "liblog",
         "liblzma",
     ],
 }
 
+cc_library {
+    name: "libunwindstack",
+    vendor_available: true,
+    recovery_available: true,
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
+    defaults: ["libunwindstack_defaults"],
+
+    srcs: ["DexFile.cpp"],
+    cflags: ["-DDEXFILE_SUPPORT"],
+    shared_libs: ["libdexfile_support"],
+
+    target: {
+        vendor: {
+            cflags: ["-UDEXFILE_SUPPORT"],
+            exclude_srcs: ["DexFile.cpp"],
+            exclude_shared_libs: ["libdexfile_support"],
+        },
+        recovery: {
+            cflags: ["-UDEXFILE_SUPPORT"],
+            exclude_srcs: ["DexFile.cpp"],
+            exclude_shared_libs: ["libdexfile_support"],
+        },
+    },
+}
+
+// Static library without DEX support to avoid dependencies on the ART APEX.
+cc_library_static {
+    name: "libunwindstack_no_dex",
+    recovery_available: true,
+    defaults: ["libunwindstack_defaults"],
+
+    visibility: [
+        "//system/core/debuggerd",
+        "//system/core/init",
+        "//system/core/libbacktrace",
+    ],
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.runtime",
+    ],
+}
+
 //-------------------------------------------------------------------------
 // Unit Tests
 //-------------------------------------------------------------------------
diff --git a/libziparchive/include/ziparchive/zip_archive.h b/libziparchive/include/ziparchive/zip_archive.h
index 098a9cb..435bfb6 100644
--- a/libziparchive/include/ziparchive/zip_archive.h
+++ b/libziparchive/include/ziparchive/zip_archive.h
@@ -145,7 +145,7 @@
   /** The size in bytes of the archive itself. Used by zipinfo. */
   off64_t archive_size;
   /** The number of entries in the archive. */
-  size_t entry_count;
+  uint64_t entry_count;
 };
 
 /**
@@ -188,6 +188,15 @@
                        const std::string_view optional_suffix = "");
 
 /*
+ * Start iterating over all entries of a zip file. Use the matcher functor to
+ * restrict iteration to entry names that make the functor return true.
+ *
+ * Returns 0 on success and negative values on failure.
+ */
+int32_t StartIteration(ZipArchiveHandle archive, void** cookie_ptr,
+                       std::function<bool(std::string_view entry_name)> matcher);
+
+/*
  * Advance to the next element in the zipfile in iteration order.
  *
  * Returns 0 on success, -1 if there are no more elements in this
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index aa8bafc..6b6502b 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -32,6 +32,7 @@
 #include <unistd.h>
 
 #include <memory>
+#include <optional>
 #include <vector>
 
 #if defined(__APPLE__)
@@ -65,6 +66,10 @@
 // The maximum number of bytes to scan backwards for the EOCD start.
 static const uint32_t kMaxEOCDSearch = kMaxCommentLen + sizeof(EocdRecord);
 
+// Set a reasonable cap (256 GiB) for the zip file size. So the data is always valid when
+// we parse the fields in cd or local headers as 64 bits signed integers.
+static constexpr uint64_t kMaxFileLength = 256 * static_cast<uint64_t>(1u << 30u);
+
 /*
  * A Read-only Zip archive.
  *
@@ -125,12 +130,27 @@
   }
 }
 
-static int32_t MapCentralDirectory0(const char* debug_file_name, ZipArchive* archive,
-                                    off64_t file_length, uint32_t read_amount,
-                                    uint8_t* scan_buffer) {
+struct CentralDirectoryInfo {
+  uint64_t num_records;
+  // The size of the central directory (in bytes).
+  uint64_t cd_size;
+  // The offset of the start of the central directory, relative
+  // to the start of the file.
+  uint64_t cd_start_offset;
+};
+
+static ZipError FindCentralDirectoryInfoForZip64(CentralDirectoryInfo* /* cdInfo */) {
+  ALOGW("Zip: Parsing zip64 EOCD isn't supported yet.");
+  return kInvalidFile;
+}
+
+static ZipError FindCentralDirectoryInfo(const char* debug_file_name, ZipArchive* archive,
+                                         off64_t file_length, uint32_t read_amount,
+                                         CentralDirectoryInfo* cdInfo) {
+  std::vector<uint8_t> scan_buffer(read_amount);
   const off64_t search_start = file_length - read_amount;
 
-  if (!archive->mapped_zip.ReadAtOffset(scan_buffer, read_amount, search_start)) {
+  if (!archive->mapped_zip.ReadAtOffset(scan_buffer.data(), read_amount, search_start)) {
     ALOGE("Zip: read %" PRId64 " from offset %" PRId64 " failed", static_cast<int64_t>(read_amount),
           static_cast<int64_t>(search_start));
     return kIoError;
@@ -159,7 +179,7 @@
   }
 
   const off64_t eocd_offset = search_start + i;
-  const EocdRecord* eocd = reinterpret_cast<const EocdRecord*>(scan_buffer + i);
+  auto eocd = reinterpret_cast<const EocdRecord*>(scan_buffer.data() + i);
   /*
    * Verify that there's no trailing space at the end of the central directory
    * and its comment.
@@ -171,6 +191,13 @@
     return kInvalidFile;
   }
 
+  // One of the field is 0xFFFFFFFF, look for the zip64 EOCD instead.
+  if (eocd->cd_size == UINT32_MAX || eocd->cd_start_offset == UINT32_MAX) {
+    ALOGV("Looking for the zip64 EOCD, cd_size: %" PRIu32 "cd_start_offset: %" PRId32,
+          eocd->cd_size, eocd->cd_start_offset);
+    return FindCentralDirectoryInfoForZip64(cdInfo);
+  }
+
   /*
    * Grab the CD offset and size, and the number of entries in the
    * archive and verify that they look reasonable.
@@ -180,47 +207,29 @@
           eocd->cd_start_offset, eocd->cd_size, static_cast<int64_t>(eocd_offset));
     return kInvalidOffset;
   }
-  if (eocd->num_records == 0) {
-#if defined(__ANDROID__)
-    ALOGW("Zip: empty archive?");
-#endif
-    return kEmptyArchive;
-  }
 
-  ALOGV("+++ num_entries=%" PRIu32 " dir_size=%" PRIu32 " dir_offset=%" PRIu32, eocd->num_records,
-        eocd->cd_size, eocd->cd_start_offset);
-
-  // It all looks good.  Create a mapping for the CD, and set the fields
-  // in archive.
-  if (!archive->InitializeCentralDirectory(static_cast<off64_t>(eocd->cd_start_offset),
-                                           static_cast<size_t>(eocd->cd_size))) {
-    return kMmapFailed;
-  }
-
-  archive->num_entries = eocd->num_records;
-  archive->directory_offset = eocd->cd_start_offset;
-
-  return 0;
+  *cdInfo = {.num_records = eocd->num_records,
+             .cd_size = eocd->cd_size,
+             .cd_start_offset = eocd->cd_start_offset};
+  return kSuccess;
 }
 
 /*
  * Find the zip Central Directory and memory-map it.
  *
- * On success, returns 0 after populating fields from the EOCD area:
+ * On success, returns kSuccess after populating fields from the EOCD area:
  *   directory_offset
  *   directory_ptr
  *   num_entries
  */
-static int32_t MapCentralDirectory(const char* debug_file_name, ZipArchive* archive) {
-  // Test file length. We use lseek64 to make sure the file
-  // is small enough to be a zip file (Its size must be less than
-  // 0xffffffff bytes).
+static ZipError MapCentralDirectory(const char* debug_file_name, ZipArchive* archive) {
+  // Test file length. We use lseek64 to make sure the file is small enough to be a zip file.
   off64_t file_length = archive->mapped_zip.GetFileLength();
   if (file_length == -1) {
     return kInvalidFile;
   }
 
-  if (file_length > static_cast<off64_t>(0xffffffff)) {
+  if (file_length > kMaxFileLength) {
     ALOGV("Zip: zip file too long %" PRId64, static_cast<int64_t>(file_length));
     return kInvalidFile;
   }
@@ -247,10 +256,39 @@
     read_amount = static_cast<uint32_t>(file_length);
   }
 
-  std::vector<uint8_t> scan_buffer(read_amount);
-  int32_t result =
-      MapCentralDirectory0(debug_file_name, archive, file_length, read_amount, scan_buffer.data());
-  return result;
+  CentralDirectoryInfo cdInfo = {};
+  if (auto result =
+          FindCentralDirectoryInfo(debug_file_name, archive, file_length, read_amount, &cdInfo);
+      result != kSuccess) {
+    return result;
+  }
+
+  if (cdInfo.num_records == 0) {
+#if defined(__ANDROID__)
+    ALOGW("Zip: empty archive?");
+#endif
+    return kEmptyArchive;
+  }
+
+  if (cdInfo.cd_size >= SIZE_MAX) {
+    ALOGW("Zip: The size of central directory doesn't fit in range of size_t: %" PRIu64,
+          cdInfo.cd_size);
+    return kInvalidFile;
+  }
+
+  ALOGV("+++ num_entries=%" PRIu64 " dir_size=%" PRIu64 " dir_offset=%" PRIu64, cdInfo.num_records,
+        cdInfo.cd_size, cdInfo.cd_start_offset);
+
+  // It all looks good.  Create a mapping for the CD, and set the fields in archive.
+  if (!archive->InitializeCentralDirectory(static_cast<off64_t>(cdInfo.cd_start_offset),
+                                           static_cast<size_t>(cdInfo.cd_size))) {
+    return kMmapFailed;
+  }
+
+  archive->num_entries = cdInfo.num_records;
+  archive->directory_offset = cdInfo.cd_start_offset;
+
+  return kSuccess;
 }
 
 /*
@@ -262,13 +300,12 @@
 static int32_t ParseZipArchive(ZipArchive* archive) {
   const uint8_t* const cd_ptr = archive->central_directory.GetBasePtr();
   const size_t cd_length = archive->central_directory.GetMapLength();
-  const uint16_t num_entries = archive->num_entries;
+  const uint64_t num_entries = archive->num_entries;
 
-  // TODO(xunchang) parse the zip64 Eocd
-  if (num_entries > UINT16_MAX) {
-    archive->cd_entry_map = CdEntryMapZip64::Create();
+  if (num_entries <= UINT16_MAX) {
+    archive->cd_entry_map = CdEntryMapZip32::Create(static_cast<uint16_t>(num_entries));
   } else {
-    archive->cd_entry_map = CdEntryMapZip32::Create(num_entries);
+    archive->cd_entry_map = CdEntryMapZip64::Create();
   }
   if (archive->cd_entry_map == nullptr) {
     return kAllocationFailed;
@@ -280,9 +317,9 @@
    */
   const uint8_t* const cd_end = cd_ptr + cd_length;
   const uint8_t* ptr = cd_ptr;
-  for (uint16_t i = 0; i < num_entries; i++) {
+  for (uint64_t i = 0; i < num_entries; i++) {
     if (ptr > cd_end - sizeof(CentralDirectoryRecord)) {
-      ALOGW("Zip: ran off the end (item #%" PRIu16 ", %zu bytes of central directory)", i,
+      ALOGW("Zip: ran off the end (item #%" PRIu64 ", %zu bytes of central directory)", i,
             cd_length);
 #if defined(__ANDROID__)
       android_errorWriteLog(0x534e4554, "36392138");
@@ -292,14 +329,7 @@
 
     const CentralDirectoryRecord* cdr = reinterpret_cast<const CentralDirectoryRecord*>(ptr);
     if (cdr->record_signature != CentralDirectoryRecord::kSignature) {
-      ALOGW("Zip: missed a central dir sig (at %" PRIu16 ")", i);
-      return kInvalidFile;
-    }
-
-    const off64_t local_header_offset = cdr->local_file_header_offset;
-    if (local_header_offset >= archive->directory_offset) {
-      ALOGW("Zip: bad LFH offset %" PRId64 " at entry %" PRIu16,
-            static_cast<int64_t>(local_header_offset), i);
+      ALOGW("Zip: missed a central dir sig (at %" PRIu64 ")", i);
       return kInvalidFile;
     }
 
@@ -308,15 +338,37 @@
     const uint16_t comment_length = cdr->comment_length;
     const uint8_t* file_name = ptr + sizeof(CentralDirectoryRecord);
 
-    if (file_name + file_name_length > cd_end) {
-      ALOGW("Zip: file name for entry %" PRIu16
+    if (file_name_length >= cd_length || file_name > cd_end - file_name_length) {
+      ALOGW("Zip: file name for entry %" PRIu64
             " exceeds the central directory range, file_name_length: %" PRIu16 ", cd_length: %zu",
             i, file_name_length, cd_length);
       return kInvalidEntryName;
     }
+
+    const uint8_t* extra_field = file_name + file_name_length;
+    if (extra_length >= cd_length || extra_field > cd_end - extra_length) {
+      ALOGW("Zip: extra field for entry %" PRIu64
+            " exceeds the central directory range, file_name_length: %" PRIu16 ", cd_length: %zu",
+            i, extra_length, cd_length);
+      return kInvalidFile;
+    }
+
+    off64_t local_header_offset = cdr->local_file_header_offset;
+    if (local_header_offset == UINT32_MAX) {
+      // TODO(xunchang) parse the zip64 eocd
+      ALOGW("Zip: Parsing zip64 cd entry isn't supported yet");
+      return kInvalidFile;
+    }
+
+    if (local_header_offset >= archive->directory_offset) {
+      ALOGW("Zip: bad LFH offset %" PRId64 " at entry %" PRIu64,
+            static_cast<int64_t>(local_header_offset), i);
+      return kInvalidFile;
+    }
+
     // Check that file name is valid UTF-8 and doesn't contain NUL (U+0000) characters.
     if (!IsValidEntryName(file_name, file_name_length)) {
-      ALOGW("Zip: invalid file name at entry %" PRIu16, i);
+      ALOGW("Zip: invalid file name at entry %" PRIu64, i);
       return kInvalidEntryName;
     }
 
@@ -331,7 +383,7 @@
 
     ptr += sizeof(CentralDirectoryRecord) + file_name_length + extra_length + comment_length;
     if ((ptr - cd_ptr) > static_cast<int64_t>(cd_length)) {
-      ALOGW("Zip: bad CD advance (%tu vs %zu) at entry %" PRIu16, ptr - cd_ptr, cd_length, i);
+      ALOGW("Zip: bad CD advance (%tu vs %zu) at entry %" PRIu64, ptr - cd_ptr, cd_length, i);
       return kInvalidFile;
     }
   }
@@ -351,14 +403,14 @@
     return kInvalidFile;
   }
 
-  ALOGV("+++ zip good scan %" PRIu16 " entries", num_entries);
+  ALOGV("+++ zip good scan %" PRIu64 " entries", num_entries);
 
   return 0;
 }
 
 static int32_t OpenArchiveInternal(ZipArchive* archive, const char* debug_file_name) {
   int32_t result = MapCentralDirectory(debug_file_name, archive);
-  return result != 0 ? result : ParseZipArchive(archive);
+  return result != kSuccess ? result : ParseZipArchive(archive);
 }
 
 int32_t OpenArchiveFd(int fd, const char* debug_file_name, ZipArchiveHandle* handle,
@@ -489,7 +541,15 @@
   // Figure out the local header offset from the central directory. The
   // actual file data will begin after the local header and the name /
   // extra comments.
-  const off64_t local_header_offset = cdr->local_file_header_offset;
+  off64_t local_header_offset = cdr->local_file_header_offset;
+  // One of the info field is UINT32_MAX, try to parse the real value in the zip64 extended info in
+  // the extra field.
+  if (cdr->uncompressed_size == UINT32_MAX || cdr->compressed_size == UINT32_MAX ||
+      cdr->local_file_header_offset == UINT32_MAX) {
+    ALOGW("Zip: Parsing zip64 local file header isn't supported yet");
+    return kInvalidFile;
+  }
+
   if (local_header_offset + static_cast<off64_t>(sizeof(LocalFileHeader)) >= cd_offset) {
     ALOGW("Zip: bad local hdr offset in zip");
     return kInvalidOffset;
@@ -616,31 +676,40 @@
 struct IterationHandle {
   ZipArchive* archive;
 
-  std::string prefix;
-  std::string suffix;
+  std::function<bool(std::string_view)> matcher;
 
   uint32_t position = 0;
 
-  IterationHandle(ZipArchive* archive, std::string_view in_prefix, std::string_view in_suffix)
-      : archive(archive), prefix(in_prefix), suffix(in_suffix) {}
+  IterationHandle(ZipArchive* archive, std::function<bool(std::string_view)> in_matcher)
+      : archive(archive), matcher(std::move(in_matcher)) {}
+
+  bool Match(std::string_view entry_name) const { return matcher(entry_name); }
 };
 
 int32_t StartIteration(ZipArchiveHandle archive, void** cookie_ptr,
                        const std::string_view optional_prefix,
                        const std::string_view optional_suffix) {
-  if (archive == nullptr || archive->cd_entry_map == nullptr) {
-    ALOGW("Zip: Invalid ZipArchiveHandle");
-    return kInvalidHandle;
-  }
-
   if (optional_prefix.size() > static_cast<size_t>(UINT16_MAX) ||
       optional_suffix.size() > static_cast<size_t>(UINT16_MAX)) {
     ALOGW("Zip: prefix/suffix too long");
     return kInvalidEntryName;
   }
+  auto matcher = [prefix = std::string(optional_prefix),
+                  suffix = std::string(optional_suffix)](std::string_view name) mutable {
+    return android::base::StartsWith(name, prefix) && android::base::EndsWith(name, suffix);
+  };
+  return StartIteration(archive, cookie_ptr, std::move(matcher));
+}
+
+int32_t StartIteration(ZipArchiveHandle archive, void** cookie_ptr,
+                       std::function<bool(std::string_view)> matcher) {
+  if (archive == nullptr || archive->cd_entry_map == nullptr) {
+    ALOGW("Zip: Invalid ZipArchiveHandle");
+    return kInvalidHandle;
+  }
 
   archive->cd_entry_map->ResetIteration();
-  *cookie_ptr = new IterationHandle(archive, optional_prefix, optional_suffix);
+  *cookie_ptr = new IterationHandle(archive, matcher);
   return 0;
 }
 
@@ -690,8 +759,7 @@
   auto entry = archive->cd_entry_map->Next(archive->central_directory.GetBasePtr());
   while (entry != std::pair<std::string_view, uint64_t>()) {
     const auto [entry_name, offset] = entry;
-    if (android::base::StartsWith(entry_name, handle->prefix) &&
-        android::base::EndsWith(entry_name, handle->suffix)) {
+    if (handle->Match(entry_name)) {
       const int error = FindEntry(archive, entry_name, offset, data);
       if (!error && name) {
         *name = entry_name;
diff --git a/libziparchive/zip_archive_common.h b/libziparchive/zip_archive_common.h
index 8b99bde..a92d4d2 100644
--- a/libziparchive/zip_archive_common.h
+++ b/libziparchive/zip_archive_common.h
@@ -21,6 +21,8 @@
 
 #include <inttypes.h>
 
+#include <optional>
+
 // The "end of central directory" (EOCD) record. Each archive
 // contains exactly once such record which appears at the end of
 // the archive. It contains archive wide information like the
@@ -173,6 +175,89 @@
   DISALLOW_COPY_AND_ASSIGN(DataDescriptor);
 } __attribute__((packed));
 
+// The zip64 end of central directory locator helps to find the zip64 EOCD.
+struct Zip64EocdLocator {
+  static constexpr uint32_t kSignature = 0x07064b50;
+
+  // The signature of zip64 eocd locator, must be |kSignature|
+  uint32_t locator_signature;
+  // The start disk of the zip64 eocd. This implementation assumes that each
+  // archive spans a single disk only.
+  uint32_t eocd_start_disk;
+  // The offset offset of the zip64 end of central directory record.
+  uint64_t zip64_eocd_offset;
+  // The total number of disks. This implementation assumes that each archive
+  // spans a single disk only.
+  uint32_t num_of_disks;
+
+ private:
+  Zip64EocdLocator() = default;
+  DISALLOW_COPY_AND_ASSIGN(Zip64EocdLocator);
+} __attribute__((packed));
+
+// The optional zip64 EOCD. If one of the fields in the end of central directory
+// record is too small to hold required data, the field SHOULD be  set to -1
+// (0xFFFF or 0xFFFFFFFF) and the ZIP64 format record SHOULD be created.
+struct Zip64EocdRecord {
+  static constexpr uint32_t kSignature = 0x06064b50;
+
+  // The signature of zip64 eocd record, must be |kSignature|
+  uint32_t record_signature;
+  // Size of zip64 end of central directory record. It SHOULD be the size of the
+  // remaining record and SHOULD NOT include the leading 12 bytes.
+  uint64_t record_size;
+  // The version of the tool that make this archive.
+  uint16_t version_made_by;
+  // Tool version needed to extract this archive.
+  uint16_t version_needed;
+  // Number of this disk.
+  uint32_t disk_num;
+  // Number of the disk with the start of the central directory.
+  uint32_t cd_start_disk;
+  // Total number of entries in the central directory on this disk.
+  // This implementation assumes that each archive spans a single
+  // disk only. i.e, that num_records_on_disk == num_records.
+  uint64_t num_records_on_disk;
+  // The total number of central directory records.
+  uint64_t num_records;
+  // The size of the central directory in bytes.
+  uint64_t cd_size;
+  // The offset of the start of the central directory, relative to the start of
+  // the file.
+  uint64_t cd_start_offset;
+
+ private:
+  Zip64EocdRecord() = default;
+  DISALLOW_COPY_AND_ASSIGN(Zip64EocdRecord);
+} __attribute__((packed));
+
+// The possible contents of the Zip64 Extended Information Extra Field. It may appear in
+// the 'extra' field of a central directory record or local file header. The order of
+// the fields in the zip64 extended information record is fixed, but the fields MUST
+// only appear if the corresponding local or central directory record field is set to
+// 0xFFFF or 0xFFFFFFFF. And this entry in the Local header MUST include BOTH original
+// and compressed file size fields.
+struct Zip64ExtendedInfo {
+  static constexpr uint16_t kHeaderId = 0x0001;
+  // The header tag for this 'extra' block, should be |kHeaderId|.
+  uint16_t header_id;
+  // The size in bytes of the remaining data (excluding the top 4 bytes).
+  uint16_t data_size;
+  // Size in bytes of the uncompressed file.
+  std::optional<uint64_t> uncompressed_file_size;
+  // Size in bytes of the compressed file.
+  std::optional<uint64_t> compressed_file_size;
+  // Local file header offset relative to the start of the zip file.
+  std::optional<uint64_t> local_header_offset;
+
+  // This implementation assumes that each archive spans a single disk only. So
+  // the disk_number is not used.
+  // uint32_t disk_num;
+ private:
+  Zip64ExtendedInfo() = default;
+  DISALLOW_COPY_AND_ASSIGN(Zip64ExtendedInfo);
+};
+
 // mask value that signifies that the entry has a DD
 static const uint32_t kGPBDDFlagMask = 0x0008;
 
diff --git a/libziparchive/zip_archive_private.h b/libziparchive/zip_archive_private.h
index 3509b89..5f5232f 100644
--- a/libziparchive/zip_archive_private.h
+++ b/libziparchive/zip_archive_private.h
@@ -95,7 +95,7 @@
   std::unique_ptr<android::base::MappedFile> directory_map;
 
   // number of entries in the Zip archive
-  uint16_t num_entries;
+  uint64_t num_entries;
   std::unique_ptr<CdEntryMapInterface> cd_entry_map;
 
   ZipArchive(MappedZipFile&& map, bool assume_ownership);
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index 5caca8a..6c1a9a1 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -227,6 +227,22 @@
   CloseArchive(handle);
 }
 
+static void AssertIterationNames(void* iteration_cookie,
+                                 const std::vector<std::string>& expected_names_sorted) {
+  ZipEntry data;
+  std::vector<std::string> names;
+  std::string name;
+  for (size_t i = 0; i < expected_names_sorted.size(); ++i) {
+    ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
+    names.push_back(name);
+  }
+  // End of iteration.
+  ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
+  // Assert that the names are as expected.
+  std::sort(names.begin(), names.end());
+  ASSERT_EQ(expected_names_sorted, names);
+}
+
 static void AssertIterationOrder(const std::string_view prefix, const std::string_view suffix,
                                  const std::vector<std::string>& expected_names_sorted) {
   ZipArchiveHandle handle;
@@ -234,23 +250,19 @@
 
   void* iteration_cookie;
   ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, prefix, suffix));
-
-  ZipEntry data;
-  std::vector<std::string> names;
-
-  std::string name;
-  for (size_t i = 0; i < expected_names_sorted.size(); ++i) {
-    ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
-    names.push_back(name);
-  }
-
-  // End of iteration.
-  ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
+  AssertIterationNames(iteration_cookie, expected_names_sorted);
   CloseArchive(handle);
+}
 
-  // Assert that the names are as expected.
-  std::sort(names.begin(), names.end());
-  ASSERT_EQ(expected_names_sorted, names);
+static void AssertIterationOrderWithMatcher(std::function<bool(std::string_view)> matcher,
+                                            const std::vector<std::string>& expected_names_sorted) {
+  ZipArchiveHandle handle;
+  ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
+
+  void* iteration_cookie;
+  ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, matcher));
+  AssertIterationNames(iteration_cookie, expected_names_sorted);
+  CloseArchive(handle);
 }
 
 TEST(ziparchive, Iteration) {
@@ -279,6 +291,30 @@
   AssertIterationOrder("b", ".txt", kExpectedMatchesSorted);
 }
 
+TEST(ziparchive, IterationWithAdditionalMatchesExactly) {
+  static const std::vector<std::string> kExpectedMatchesSorted = {"a.txt"};
+  auto matcher = [](std::string_view name) { return name == "a.txt"; };
+  AssertIterationOrderWithMatcher(matcher, kExpectedMatchesSorted);
+}
+
+TEST(ziparchive, IterationWithAdditionalMatchesWithSuffix) {
+  static const std::vector<std::string> kExpectedMatchesSorted = {"a.txt", "b.txt", "b/c.txt",
+                                                                  "b/d.txt"};
+  auto matcher = [](std::string_view name) {
+    return name == "a.txt" || android::base::EndsWith(name, ".txt");
+  };
+  AssertIterationOrderWithMatcher(matcher, kExpectedMatchesSorted);
+}
+
+TEST(ziparchive, IterationWithAdditionalMatchesWithPrefixAndSuffix) {
+  static const std::vector<std::string> kExpectedMatchesSorted = {"a.txt", "b/c.txt", "b/d.txt"};
+  auto matcher = [](std::string_view name) {
+    return name == "a.txt" ||
+           (android::base::EndsWith(name, ".txt") && android::base::StartsWith(name, "b/"));
+  };
+  AssertIterationOrderWithMatcher(matcher, kExpectedMatchesSorted);
+}
+
 TEST(ziparchive, IterationWithBadPrefixAndSuffix) {
   ZipArchiveHandle handle;
   ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
diff --git a/libziparchive/ziptool.cpp b/libziparchive/ziptool.cpp
index dd42e90..f345ffc 100644
--- a/libziparchive/ziptool.cpp
+++ b/libziparchive/ziptool.cpp
@@ -133,8 +133,8 @@
     if (!flag_1 && includes.empty() && excludes.empty()) {
       ZipArchiveInfo info{GetArchiveInfo(zah)};
       printf("Archive:  %s\n", archive_name);
-      printf("Zip file size: %" PRId64 " bytes, number of entries: %zu\n", info.archive_size,
-             info.entry_count);
+      printf("Zip file size: %" PRId64 " bytes, number of entries: %" PRIu64 "\n",
+             info.archive_size, info.entry_count);
     }
   }
 }
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 76a970f..b065855 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -513,7 +513,7 @@
     unsigned long setLogSize = 0;
     const char* setPruneList = nullptr;
     const char* setId = nullptr;
-    int mode = ANDROID_LOG_RDONLY;
+    int mode = 0;
     std::string forceFilters;
     size_t tail_lines = 0;
     log_time tail_time(log_time::EPOCH);
@@ -591,8 +591,7 @@
                     break;
                 }
                 if (long_options[option_index].name == wrap_str) {
-                    mode |= ANDROID_LOG_WRAP | ANDROID_LOG_RDONLY |
-                            ANDROID_LOG_NONBLOCK;
+                    mode |= ANDROID_LOG_WRAP | ANDROID_LOG_NONBLOCK;
                     // ToDo: implement API that supports setting a wrap timeout
                     size_t dummy = ANDROID_LOG_WRAP_DEFAULT_TIMEOUT;
                     if (optarg && (!ParseUint(optarg, &dummy) || dummy < 1)) {
@@ -626,21 +625,19 @@
 
             case 'c':
                 clearLog = true;
-                mode |= ANDROID_LOG_WRONLY;
                 break;
 
             case 'L':
-                mode |= ANDROID_LOG_RDONLY | ANDROID_LOG_PSTORE |
-                        ANDROID_LOG_NONBLOCK;
+                mode |= ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK;
                 break;
 
             case 'd':
-                mode |= ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK;
+                mode |= ANDROID_LOG_NONBLOCK;
                 break;
 
             case 't':
                 got_t = true;
-                mode |= ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK;
+                mode |= ANDROID_LOG_NONBLOCK;
                 FALLTHROUGH_INTENDED;
             case 'T':
                 if (strspn(optarg, "0123456789") != strlen(optarg)) {
diff --git a/logd/LogTags.cpp b/logd/LogTags.cpp
index 0cc7886..8299e66 100644
--- a/logd/LogTags.cpp
+++ b/logd/LogTags.cpp
@@ -289,9 +289,8 @@
 // special pmsg event for log tags, and build up our internal
 // database with any found.
 void LogTags::ReadPersistEventLogTags() {
-    struct logger_list* logger_list = android_logger_list_alloc(
-        ANDROID_LOG_RDONLY | ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK, 0,
-        (pid_t)0);
+    struct logger_list* logger_list =
+            android_logger_list_alloc(ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK, 0, (pid_t)0);
     if (!logger_list) return;
 
     struct logger* e = android_logger_open(logger_list, LOG_ID_EVENTS);
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index f47bee1..c7f3480 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -870,10 +870,8 @@
     ASSERT_EQ(0, info.si_status);
 
     struct logger_list* logger_list;
-    ASSERT_TRUE(nullptr !=
-                (logger_list = android_logger_list_open(
-                     LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-                     0, pid)));
+    ASSERT_TRUE(nullptr != (logger_list = android_logger_list_open(LOG_ID_EVENTS,
+                                                                   ANDROID_LOG_NONBLOCK, 0, pid)));
 
     int expected_count = (count < 2) ? count : 2;
     int expected_chatty_count = (count <= 2) ? 0 : 1;