Merge "Support appending vbmeta digest to id/fingerprint"
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 7b6f6c0..198e4de 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -276,6 +276,12 @@
     ],
 }
 
+cc_test_library {
+    name: "libcrash_test",
+    defaults: ["debuggerd_defaults"],
+    srcs: ["crash_test.cpp"],
+}
+
 cc_test {
     name: "debuggerd_test",
     defaults: ["debuggerd_defaults"],
@@ -341,6 +347,10 @@
         },
     },
 
+    data: [
+        ":libcrash_test",
+    ],
+
     test_suites: ["device-tests"],
 }
 
diff --git a/debuggerd/crash_test.cpp b/debuggerd/crash_test.cpp
new file mode 100644
index 0000000..c15145f
--- /dev/null
+++ b/debuggerd/crash_test.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+
+extern "C" void crash() {
+  *reinterpret_cast<volatile char*>(0xdead) = '1';
+}
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 93725b9..eb3738e 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <dirent.h>
+#include <dlfcn.h>
 #include <err.h>
 #include <fcntl.h>
 #include <malloc.h>
@@ -30,6 +31,7 @@
 
 #include <chrono>
 #include <regex>
+#include <string>
 #include <thread>
 
 #include <android/fdsan.h>
@@ -1510,6 +1512,60 @@
   ASSERT_MATCH(result, R"(Cause: stack pointer[^\n]*stack overflow.\n)");
 }
 
+static bool CopySharedLibrary(const char* tmp_dir, std::string* tmp_so_name) {
+  std::string test_lib(testing::internal::GetArgvs()[0]);
+  auto const value = test_lib.find_last_of('/');
+  if (value == std::string::npos) {
+    test_lib = "./";
+  } else {
+    test_lib = test_lib.substr(0, value + 1) + "./";
+  }
+  test_lib += "libcrash_test.so";
+
+  *tmp_so_name = std::string(tmp_dir) + "/libcrash_test.so";
+  std::string cp_cmd = android::base::StringPrintf("cp %s %s", test_lib.c_str(), tmp_dir);
+
+  // Copy the shared so to a tempory directory.
+  return system(cp_cmd.c_str()) == 0;
+}
+
+TEST_F(CrasherTest, unreadable_elf) {
+  int intercept_result;
+  unique_fd output_fd;
+  StartProcess([]() {
+    TemporaryDir td;
+    std::string tmp_so_name;
+    if (!CopySharedLibrary(td.path, &tmp_so_name)) {
+      _exit(1);
+    }
+    void* handle = dlopen(tmp_so_name.c_str(), RTLD_NOW);
+    if (handle == nullptr) {
+      _exit(1);
+    }
+    // Delete the original shared library so that we get the warning
+    // about unreadable elf files.
+    if (unlink(tmp_so_name.c_str()) == -1) {
+      _exit(1);
+    }
+    void (*crash_func)() = reinterpret_cast<void (*)()>(dlsym(handle, "crash"));
+    if (crash_func == nullptr) {
+      _exit(1);
+    }
+    crash_func();
+  });
+
+  StartIntercept(&output_fd);
+  FinishCrasher();
+  AssertDeath(SIGSEGV);
+  FinishIntercept(&intercept_result);
+
+  ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+  std::string result;
+  ConsumeFd(std::move(output_fd), &result);
+  ASSERT_MATCH(result, R"(NOTE: Function names and BuildId information is missing )");
+}
+
 TEST(tombstoned, proto) {
   const pid_t self = getpid();
   unique_fd tombstoned_socket, text_fd, proto_fd;
diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp
index 7657001..d4a35b3 100644
--- a/debuggerd/libdebuggerd/tombstone_proto.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto.cpp
@@ -395,6 +395,15 @@
                             unwinder->LastErrorAddress());
     }
   } else {
+    if (unwinder->elf_from_memory_not_file()) {
+      auto backtrace_note = thread.mutable_backtrace_note();
+      *backtrace_note->Add() =
+          "Function names and BuildId information is missing for some frames due";
+      *backtrace_note->Add() =
+          "to unreadable libraries. For unwinds of apps, only shared libraries";
+      *backtrace_note->Add() = "found under the lib/ directory are readable.";
+      *backtrace_note->Add() = "On this device, run setenforce 0 to make the libraries readable.";
+    }
     unwinder->SetDisplayBuildID(true);
     for (const auto& frame : unwinder->frames()) {
       BacktraceFrame* f = thread.add_current_backtrace();
diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
index 020b0a5..b780b22 100644
--- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
@@ -171,6 +171,10 @@
                                    const Thread& thread, bool should_log) {
   CBS("");
   CB(should_log, "backtrace:");
+  if (!thread.backtrace_note().empty()) {
+    CB(should_log, "  NOTE: %s",
+       android::base::Join(thread.backtrace_note(), "\n  NOTE: ").c_str());
+  }
   print_backtrace(callback, tombstone, thread.current_backtrace(), should_log);
 }
 
diff --git a/debuggerd/proto/tombstone.proto b/debuggerd/proto/tombstone.proto
index 294e4e5..22fc30e 100644
--- a/debuggerd/proto/tombstone.proto
+++ b/debuggerd/proto/tombstone.proto
@@ -119,11 +119,12 @@
   int32 id = 1;
   string name = 2;
   repeated Register registers = 3;
+  repeated string backtrace_note = 7;
   repeated BacktraceFrame current_backtrace = 4;
   repeated MemoryDump memory_dump = 5;
   int64 tagged_addr_ctrl = 6;
 
-  reserved 7 to 999;
+  reserved 8 to 999;
 }
 
 message BacktraceFrame {
diff --git a/fs_mgr/TEST_MAPPING b/fs_mgr/TEST_MAPPING
index a349408..84709b6 100644
--- a/fs_mgr/TEST_MAPPING
+++ b/fs_mgr/TEST_MAPPING
@@ -17,6 +17,9 @@
     },
     {
       "name": "libsnapshot_fuzzer_test"
+    },
+    {
+      "name": "cow_api_test"
     }
   ]
 }
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 42bf356..853b24d 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -298,6 +298,8 @@
             if (!ParseByteCount(arg, &entry->zram_backingdev_size)) {
                 LWARNING << "Warning: zram_backingdev_size= flag malformed: " << arg;
             }
+        } else if (StartsWith(flag, "lowerdir=")) {
+            entry->lowerdir = arg;
         } else {
             LWARNING << "Warning: unknown flag: " << flag;
         }
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index cb09383..9a94d79 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -92,6 +92,10 @@
     return false;
 }
 
+bool fs_mgr_overlayfs_mount_fstab_entry(const std::string&, const std::string&) {
+    return false;
+}
+
 std::vector<std::string> fs_mgr_overlayfs_required_devices(Fstab*) {
     return {};
 }
@@ -1295,6 +1299,18 @@
     }
 }
 
+bool fs_mgr_overlayfs_mount_fstab_entry(const std::string& lowers,
+                                        const std::string& mount_point) {
+    if (fs_mgr_overlayfs_invalid()) return false;
+
+    std::string aux = "lowerdir=" + lowers + ",override_creds=off";
+    auto rc = mount("overlay", mount_point.c_str(), "overlay", MS_RDONLY | MS_NOATIME, aux.c_str());
+
+    if (rc == 0) return true;
+
+    return false;
+}
+
 bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
     auto ret = false;
     if (fs_mgr_overlayfs_invalid()) return ret;
diff --git a/fs_mgr/include/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h
index d45e2de..ac95ef5 100644
--- a/fs_mgr/include/fs_mgr_overlayfs.h
+++ b/fs_mgr/include/fs_mgr_overlayfs.h
@@ -27,6 +27,7 @@
 android::fs_mgr::Fstab fs_mgr_overlayfs_candidate_list(const android::fs_mgr::Fstab& fstab);
 
 bool fs_mgr_overlayfs_mount_all(android::fs_mgr::Fstab* fstab);
+bool fs_mgr_overlayfs_mount_fstab_entry (const std::string& lowers, const std::string& mount_point);
 std::vector<std::string> fs_mgr_overlayfs_required_devices(android::fs_mgr::Fstab* fstab);
 bool fs_mgr_overlayfs_setup(const char* backing = nullptr, const char* mount_point = nullptr,
                             bool* change = nullptr, bool force = true);
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index 2704e47..f33768b 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -55,6 +55,7 @@
     std::string vbmeta_partition;
     uint64_t zram_backingdev_size = 0;
     std::string avb_keys;
+    std::string lowerdir;
 
     struct FsMgrFlags {
         bool wait : 1;
diff --git a/fs_mgr/libfiemap/binder.cpp b/fs_mgr/libfiemap/binder.cpp
index c8516ab..31a57a8 100644
--- a/fs_mgr/libfiemap/binder.cpp
+++ b/fs_mgr/libfiemap/binder.cpp
@@ -224,8 +224,9 @@
     return false;
 }
 
-std::unique_ptr<IImageManager> IImageManager::Open(
-        const std::string& dir, const std::chrono::milliseconds& /*timeout_ms*/) {
+std::unique_ptr<IImageManager> IImageManager::Open(const std::string& dir,
+                                                   const std::chrono::milliseconds& /*timeout_ms*/,
+                                                   const DeviceInfo&) {
     android::sp<IGsiService> service = android::gsi::GetGsiService();
     android::sp<IImageService> manager;
 
diff --git a/fs_mgr/libfiemap/image_manager.cpp b/fs_mgr/libfiemap/image_manager.cpp
index 44f659b..dcbbc54 100644
--- a/fs_mgr/libfiemap/image_manager.cpp
+++ b/fs_mgr/libfiemap/image_manager.cpp
@@ -55,7 +55,8 @@
 static constexpr char kTestImageMetadataDir[] = "/metadata/gsi/test";
 static constexpr char kOtaTestImageMetadataDir[] = "/metadata/gsi/ota/test";
 
-std::unique_ptr<ImageManager> ImageManager::Open(const std::string& dir_prefix) {
+std::unique_ptr<ImageManager> ImageManager::Open(const std::string& dir_prefix,
+                                                 const DeviceInfo& device_info) {
     auto metadata_dir = "/metadata/gsi/" + dir_prefix;
     auto data_dir = "/data/gsi/" + dir_prefix;
     auto install_dir_file = gsi::DsuInstallDirFile(gsi::GetDsuSlot(dir_prefix));
@@ -63,17 +64,28 @@
     if (ReadFileToString(install_dir_file, &path)) {
         data_dir = path;
     }
-    return Open(metadata_dir, data_dir);
+    return Open(metadata_dir, data_dir, device_info);
 }
 
 std::unique_ptr<ImageManager> ImageManager::Open(const std::string& metadata_dir,
-                                                 const std::string& data_dir) {
-    return std::unique_ptr<ImageManager>(new ImageManager(metadata_dir, data_dir));
+                                                 const std::string& data_dir,
+                                                 const DeviceInfo& device_info) {
+    return std::unique_ptr<ImageManager>(new ImageManager(metadata_dir, data_dir, device_info));
 }
 
-ImageManager::ImageManager(const std::string& metadata_dir, const std::string& data_dir)
-    : metadata_dir_(metadata_dir), data_dir_(data_dir) {
+ImageManager::ImageManager(const std::string& metadata_dir, const std::string& data_dir,
+                           const DeviceInfo& device_info)
+    : metadata_dir_(metadata_dir), data_dir_(data_dir), device_info_(device_info) {
     partition_opener_ = std::make_unique<android::fs_mgr::PartitionOpener>();
+
+    // Allow overriding whether ImageManager thinks it's in recovery, for testing.
+#ifdef __ANDROID_RECOVERY__
+    device_info_.is_recovery = {true};
+#else
+    if (!device_info_.is_recovery.has_value()) {
+        device_info_.is_recovery = {false};
+    }
+#endif
 }
 
 std::string ImageManager::GetImageHeaderPath(const std::string& name) {
@@ -261,10 +273,11 @@
         return false;
     }
 
-#if defined __ANDROID_RECOVERY__
-    LOG(ERROR) << "Cannot remove images backed by /data in recovery";
-    return false;
-#else
+    if (device_info_.is_recovery.value()) {
+        LOG(ERROR) << "Cannot remove images backed by /data in recovery";
+        return false;
+    }
+
     std::string message;
     auto header_file = GetImageHeaderPath(name);
     if (!SplitFiemap::RemoveSplitFiles(header_file, &message)) {
@@ -278,7 +291,6 @@
         LOG(ERROR) << "Error removing " << status_file << ": " << message;
     }
     return RemoveImageMetadata(metadata_dir_, name);
-#endif
 }
 
 // Create a block device for an image file, using its extents in its
@@ -521,6 +533,9 @@
     // filesystem. This should only happen on devices with no encryption, or
     // devices with FBE and no metadata encryption. For these cases it suffices
     // to perform normal file writes to /data/gsi (which is unencrypted).
+    //
+    // Note: this is not gated on DeviceInfo, because the recovery-specific path
+    // must only be used in actual recovery.
     std::string block_device;
     bool can_use_devicemapper;
     if (!FiemapWriter::GetBlockDeviceForFile(image_header, &block_device, &can_use_devicemapper)) {
diff --git a/fs_mgr/libfiemap/include/libfiemap/image_manager.h b/fs_mgr/libfiemap/include/libfiemap/image_manager.h
index 7e30509..3c87000 100644
--- a/fs_mgr/libfiemap/include/libfiemap/image_manager.h
+++ b/fs_mgr/libfiemap/include/libfiemap/image_manager.h
@@ -21,6 +21,7 @@
 #include <chrono>
 #include <functional>
 #include <memory>
+#include <optional>
 #include <set>
 #include <string>
 
@@ -37,11 +38,17 @@
 
     virtual ~IImageManager() {}
 
+    // Helper for dependency injection.
+    struct DeviceInfo {
+        std::optional<bool> is_recovery;
+    };
+
     // When linking to libfiemap_binder, the Open() call will use binder.
     // Otherwise, the Open() call will use the ImageManager implementation
-    // below.
+    // below. In binder mode, device_info is ignored.
     static std::unique_ptr<IImageManager> Open(const std::string& dir_prefix,
-                                               const std::chrono::milliseconds& timeout_ms);
+                                               const std::chrono::milliseconds& timeout_ms,
+                                               const DeviceInfo& device_info = {});
 
     // Flags for CreateBackingImage().
     static constexpr int CREATE_IMAGE_DEFAULT = 0x0;
@@ -131,11 +138,13 @@
     // Return an ImageManager for the given metadata and data directories. Both
     // directories must already exist.
     static std::unique_ptr<ImageManager> Open(const std::string& metadata_dir,
-                                              const std::string& data_dir);
+                                              const std::string& data_dir,
+                                              const DeviceInfo& device_info = {});
 
     // Helper function that derives the metadata and data dirs given a single
     // prefix.
-    static std::unique_ptr<ImageManager> Open(const std::string& dir_prefix);
+    static std::unique_ptr<ImageManager> Open(const std::string& dir_prefix,
+                                              const DeviceInfo& device_info = {});
 
     // Methods that must be implemented from IImageManager.
     FiemapStatus CreateBackingImage(const std::string& name, uint64_t size, int flags,
@@ -166,7 +175,8 @@
     FiemapStatus ZeroFillNewImage(const std::string& name, uint64_t bytes);
 
   private:
-    ImageManager(const std::string& metadata_dir, const std::string& data_dir);
+    ImageManager(const std::string& metadata_dir, const std::string& data_dir,
+                 const DeviceInfo& device_info);
     std::string GetImageHeaderPath(const std::string& name);
     std::string GetStatusFilePath(const std::string& image_name);
     bool MapWithLoopDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms,
@@ -187,6 +197,7 @@
     std::string metadata_dir_;
     std::string data_dir_;
     std::unique_ptr<IPartitionOpener> partition_opener_;
+    DeviceInfo device_info_;
 };
 
 // RAII helper class for mapping and opening devices with an ImageManager.
diff --git a/fs_mgr/libfiemap/passthrough.cpp b/fs_mgr/libfiemap/passthrough.cpp
index 1ccd9a0..d521804 100644
--- a/fs_mgr/libfiemap/passthrough.cpp
+++ b/fs_mgr/libfiemap/passthrough.cpp
@@ -20,9 +20,10 @@
 namespace fiemap {
 
 std::unique_ptr<IImageManager> IImageManager::Open(const std::string& dir_prefix,
-                                                   const std::chrono::milliseconds& timeout_ms) {
+                                                   const std::chrono::milliseconds& timeout_ms,
+                                                   const DeviceInfo& device_info) {
     (void)timeout_ms;
-    return ImageManager::Open(dir_prefix);
+    return ImageManager::Open(dir_prefix, device_info);
 }
 
 }  // namespace fiemap
diff --git a/fs_mgr/libfs_avb/Android.bp b/fs_mgr/libfs_avb/Android.bp
index c1c181a..6892025 100644
--- a/fs_mgr/libfs_avb/Android.bp
+++ b/fs_mgr/libfs_avb/Android.bp
@@ -78,6 +78,7 @@
     shared_libs: [
         "libbase",
         "libchrome",
+        "libcrypto",
     ],
     target: {
         darwin: {
@@ -107,9 +108,6 @@
     static_libs: [
         "libfs_avb_test_util",
     ],
-    shared_libs: [
-        "libcrypto",
-    ],
     compile_multilib: "first",
     data: [
         ":avbtool",
diff --git a/fs_mgr/libfs_avb/tests/fs_avb_test_util.cpp b/fs_mgr/libfs_avb/tests/fs_avb_test_util.cpp
index 17f4c4e..1c95cf0 100644
--- a/fs_mgr/libfs_avb/tests/fs_avb_test_util.cpp
+++ b/fs_mgr/libfs_avb/tests/fs_avb_test_util.cpp
@@ -122,6 +122,7 @@
                                                  const size_t padding_size) {
     VBMetaImage vbmeta_image;
     vbmeta_image.path = test_dir_.Append(output_file_name);
+    GTEST_LOG_(INFO) << "ExtractVBMetaImage: " << image_path << " to " << output_file_name;
     EXPECT_COMMAND(0,
                    "avbtool extract_vbmeta_image"
                    " --image %s"
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index c97dca0..104484d 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -251,6 +251,7 @@
         "snapshot_metadata_updater_test.cpp",
         "snapshot_reader_test.cpp",
         "snapshot_test.cpp",
+        "snapshot_writer_test.cpp",
     ],
     shared_libs: [
         "libbinder",
@@ -478,6 +479,9 @@
         "libgtest",
         "libsnapshot_cow",
     ],
+    test_suites: [
+        "device-tests"
+    ],
     test_min_api_level: 30,
     auto_gen_config: true,
     require_root: false,
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 195b6f2..d2fdfd6 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -392,6 +392,7 @@
     FRIEND_TEST(SnapshotUpdateTest, DaemonTransition);
     FRIEND_TEST(SnapshotUpdateTest, DataWipeAfterRollback);
     FRIEND_TEST(SnapshotUpdateTest, DataWipeRollbackInRecovery);
+    FRIEND_TEST(SnapshotUpdateTest, DataWipeWithStaleSnapshots);
     FRIEND_TEST(SnapshotUpdateTest, FullUpdateFlow);
     FRIEND_TEST(SnapshotUpdateTest, MergeCannotRemoveCow);
     FRIEND_TEST(SnapshotUpdateTest, MergeInRecovery);
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 8f3926a..245742e 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -2583,7 +2583,11 @@
 }
 
 bool SnapshotManager::ForceLocalImageManager() {
-    images_ = android::fiemap::ImageManager::Open(gsid_dir_);
+    android::fiemap::ImageManager::DeviceInfo device_info = {
+            .is_recovery = {device_->IsRecovery()},
+    };
+
+    images_ = android::fiemap::ImageManager::Open(gsid_dir_, device_info);
     if (!images_) {
         LOG(ERROR) << "Could not open ImageManager";
         return false;
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 45db7a4..9226b7f 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -1860,6 +1860,67 @@
     }
 }
 
+// Test update package that requests data wipe.
+TEST_F(SnapshotUpdateTest, DataWipeWithStaleSnapshots) {
+    AddOperationForPartitions();
+
+    // Execute the update.
+    ASSERT_TRUE(sm->BeginUpdate());
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+
+    // Write some data to target partitions.
+    for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
+        ASSERT_TRUE(WriteSnapshotAndHash(name)) << name;
+    }
+
+    // Create a stale snapshot that should not exist.
+    {
+        ASSERT_TRUE(AcquireLock());
+
+        PartitionCowCreator cow_creator = {
+                .compression_enabled = IsCompressionEnabled(),
+                .compression_algorithm = IsCompressionEnabled() ? "gz" : "none",
+        };
+        SnapshotStatus status;
+        status.set_name("sys_a");
+        status.set_device_size(1_MiB);
+        status.set_snapshot_size(2_MiB);
+        status.set_cow_partition_size(2_MiB);
+
+        ASSERT_TRUE(sm->CreateSnapshot(lock_.get(), &cow_creator, &status));
+        lock_ = nullptr;
+
+        ASSERT_TRUE(sm->EnsureImageManager());
+        ASSERT_TRUE(sm->image_manager()->CreateBackingImage("sys_a", 1_MiB, 0));
+    }
+
+    ASSERT_TRUE(sm->FinishedSnapshotWrites(true /* wipe */));
+
+    // Simulate shutting down the device.
+    ASSERT_TRUE(UnmapAll());
+
+    // Simulate a reboot into recovery.
+    auto test_device = new TestDeviceInfo(fake_super, "_b");
+    test_device->set_recovery(true);
+    auto new_sm = NewManagerForFirstStageMount(test_device);
+
+    ASSERT_TRUE(new_sm->HandleImminentDataWipe());
+    // Manually mount metadata so that we can call GetUpdateState() below.
+    MountMetadata();
+    EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::None);
+    ASSERT_FALSE(test_device->IsSlotUnbootable(1));
+    ASSERT_FALSE(test_device->IsSlotUnbootable(0));
+
+    // Now reboot into new slot.
+    test_device = new TestDeviceInfo(fake_super, "_b");
+    auto init = NewManagerForFirstStageMount(test_device);
+    ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
+    // Verify that we are on the downgraded build.
+    for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
+        ASSERT_TRUE(IsPartitionUnchanged(name)) << name;
+    }
+}
+
 TEST_F(SnapshotUpdateTest, Hashtree) {
     constexpr auto partition_size = 4_MiB;
     constexpr auto data_size = 3_MiB;
@@ -2247,9 +2308,27 @@
     void TearDown() override;
 
   private:
+    bool CreateFakeSuper();
+
     std::unique_ptr<IImageManager> super_images_;
 };
 
+bool SnapshotTestEnvironment::CreateFakeSuper() {
+    // Create and map the fake super partition.
+    static constexpr int kImageFlags =
+            IImageManager::CREATE_IMAGE_DEFAULT | IImageManager::CREATE_IMAGE_ZERO_FILL;
+    if (!super_images_->CreateBackingImage("fake-super", kSuperSize, kImageFlags)) {
+        LOG(ERROR) << "Could not create fake super partition";
+        return false;
+    }
+    if (!super_images_->MapImageDevice("fake-super", 10s, &fake_super)) {
+        LOG(ERROR) << "Could not map fake super partition";
+        return false;
+    }
+    test_device->set_fake_super(fake_super);
+    return true;
+}
+
 void SnapshotTestEnvironment::SetUp() {
     // b/163082876: GTEST_SKIP in Environment will make atest report incorrect results. Until
     // that is fixed, don't call GTEST_SKIP here, but instead call GTEST_SKIP in individual test
@@ -2275,27 +2354,36 @@
     sm = SnapshotManager::New(test_device);
     ASSERT_NE(nullptr, sm) << "Could not create snapshot manager";
 
+    // Use a separate image manager for our fake super partition.
+    super_images_ = IImageManager::Open("ota/test/super", 10s);
+    ASSERT_NE(nullptr, super_images_) << "Could not create image manager";
+
+    // Map the old image if one exists so we can safely unmap everything that
+    // depends on it.
+    bool recreate_fake_super;
+    if (super_images_->BackingImageExists("fake-super")) {
+        if (super_images_->IsImageMapped("fake-super")) {
+            ASSERT_TRUE(super_images_->GetMappedImageDevice("fake-super", &fake_super));
+        } else {
+            ASSERT_TRUE(super_images_->MapImageDevice("fake-super", 10s, &fake_super));
+        }
+        test_device->set_fake_super(fake_super);
+        recreate_fake_super = true;
+    } else {
+        ASSERT_TRUE(CreateFakeSuper());
+        recreate_fake_super = false;
+    }
+
     // Clean up previous run.
     MetadataMountedTest().TearDown();
     SnapshotUpdateTest().Cleanup();
     SnapshotTest().Cleanup();
 
-    // Use a separate image manager for our fake super partition.
-    super_images_ = IImageManager::Open("ota/test/super", 10s);
-    ASSERT_NE(nullptr, super_images_) << "Could not create image manager";
-
-    // Clean up any old copy.
-    DeleteBackingImage(super_images_.get(), "fake-super");
-
-    // Create and map the fake super partition.
-    static constexpr int kImageFlags =
-            IImageManager::CREATE_IMAGE_DEFAULT | IImageManager::CREATE_IMAGE_ZERO_FILL;
-    ASSERT_TRUE(super_images_->CreateBackingImage("fake-super", kSuperSize, kImageFlags))
-            << "Could not create fake super partition";
-
-    ASSERT_TRUE(super_images_->MapImageDevice("fake-super", 10s, &fake_super))
-            << "Could not map fake super partition";
-    test_device->set_fake_super(fake_super);
+    if (recreate_fake_super) {
+        // Clean up any old copy.
+        DeleteBackingImage(super_images_.get(), "fake-super");
+        ASSERT_TRUE(CreateFakeSuper());
+    }
 }
 
 void SnapshotTestEnvironment::TearDown() {
diff --git a/fs_mgr/libsnapshot/snapshot_writer.cpp b/fs_mgr/libsnapshot/snapshot_writer.cpp
index 8e379e4..080f3b7 100644
--- a/fs_mgr/libsnapshot/snapshot_writer.cpp
+++ b/fs_mgr/libsnapshot/snapshot_writer.cpp
@@ -90,7 +90,9 @@
     }
 
     const auto& cow_options = options();
-    reader->SetBlockDeviceSize(*cow_options.max_blocks * cow_options.block_size);
+    if (cow_options.max_blocks) {
+        reader->SetBlockDeviceSize(*cow_options.max_blocks * cow_options.block_size);
+    }
 
     return reader;
 }
diff --git a/fs_mgr/libsnapshot/snapshot_writer_test.cpp b/fs_mgr/libsnapshot/snapshot_writer_test.cpp
new file mode 100644
index 0000000..da48eb9
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapshot_writer_test.cpp
@@ -0,0 +1,62 @@
+//
+// Copyright (C) 2021 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 <libsnapshot/snapshot.h>
+
+#include <unordered_set>
+
+#include <android-base/file.h>
+#include <gtest/gtest.h>
+#include <libsnapshot/snapshot_writer.h>
+#include <payload_consumer/file_descriptor.h>
+
+namespace android::snapshot {
+class CompressedSnapshotWriterTest : public ::testing::Test {
+  public:
+    static constexpr size_t BLOCK_SIZE = 4096;
+};
+
+TEST_F(CompressedSnapshotWriterTest, ReadAfterWrite) {
+    TemporaryFile cow_device_file{};
+    android::snapshot::CowOptions options{.block_size = BLOCK_SIZE};
+    android::snapshot::CompressedSnapshotWriter snapshot_writer{options};
+    snapshot_writer.SetCowDevice(android::base::unique_fd{cow_device_file.fd});
+    snapshot_writer.Initialize();
+    std::vector<unsigned char> buffer;
+    buffer.resize(BLOCK_SIZE);
+    std::fill(buffer.begin(), buffer.end(), 123);
+
+    ASSERT_TRUE(snapshot_writer.AddRawBlocks(0, buffer.data(), buffer.size()));
+    ASSERT_TRUE(snapshot_writer.Finalize());
+    auto cow_reader = snapshot_writer.OpenReader();
+    ASSERT_NE(cow_reader, nullptr);
+    ASSERT_TRUE(snapshot_writer.AddRawBlocks(1, buffer.data(), buffer.size()));
+    ASSERT_TRUE(snapshot_writer.AddRawBlocks(2, buffer.data(), buffer.size()));
+    ASSERT_TRUE(snapshot_writer.Finalize());
+    // After wrigin some data, if we call OpenReader() again, writes should
+    // be visible to the newly opened reader. update_engine relies on this
+    // behavior for verity writes.
+    cow_reader = snapshot_writer.OpenReader();
+    ASSERT_NE(cow_reader, nullptr);
+    std::vector<unsigned char> read_back;
+    read_back.resize(buffer.size());
+    cow_reader->Seek(BLOCK_SIZE, SEEK_SET);
+    const auto bytes_read = cow_reader->Read(read_back.data(), read_back.size());
+    ASSERT_EQ((size_t)(bytes_read), BLOCK_SIZE);
+    ASSERT_EQ(read_back, buffer);
+}
+
+}  // namespace android::snapshot
diff --git a/init/README.md b/init/README.md
index 4a262c9..75dc328 100644
--- a/init/README.md
+++ b/init/README.md
@@ -277,6 +277,8 @@
   CLD_EXITED or an status other than '0', reboot the system with the target specified in
   _target_. _target_ takes the same format as the parameter to sys.powerctl. This is particularly
   intended to be used with the `exec_start` builtin for any must-have checks during boot.
+  A service being stopped by init (e.g. using the `stop` or `class_reset` commands) is not
+  considered a failure for the purpose of this setting.
 
 `restart_period <seconds>`
 > If a non-oneshot service exits, it will be restarted at its start time plus
diff --git a/init/README.ueventd.md b/init/README.ueventd.md
index 3ffca88..d22f68f 100644
--- a/init/README.ueventd.md
+++ b/init/README.ueventd.md
@@ -130,6 +130,10 @@
 Will launch `/vendor/bin/led_coeffs.bin` as the system user instead of serving the default firmware
 for `/devices/leds/red/firmware/coeffs.bin`.
 
+The `devpath` argument may include asterisks (`*`) to match multiple paths. For example, the string
+`/dev/*/red` will match `/dev/leds/red` as well as `/dev/lights/red`. The pattern matching follows
+the rules of the fnmatch() function.
+
 Ueventd will provide the uevent `DEVPATH` and `FIRMWARE` to this external program on the environment
 via environment variables with the same names. Ueventd will use the string written to stdout as the
 new name of the firmware to load. It will still look for the new firmware in the list of firmware
diff --git a/init/firmware_handler_test.cpp b/init/firmware_handler_test.cpp
index 5124a6f..f6e75b0 100644
--- a/init/firmware_handler_test.cpp
+++ b/init/firmware_handler_test.cpp
@@ -103,6 +103,23 @@
     return 0;
 }
 
+TEST(firmware_handler, Matching) {
+    ExternalFirmwareHandler h("/dev/path/a.bin", getuid(), "/test");
+    ASSERT_TRUE(h.match("/dev/path/a.bin"));
+    ASSERT_FALSE(h.match("/dev/path/a.bi"));
+
+    h = ExternalFirmwareHandler("/dev/path/a.*", getuid(), "/test");
+    ASSERT_TRUE(h.match("/dev/path/a.bin"));
+    ASSERT_TRUE(h.match("/dev/path/a.bix"));
+    ASSERT_FALSE(h.match("/dev/path/b.bin"));
+
+    h = ExternalFirmwareHandler("/dev/*/a.bin", getuid(), "/test");
+    ASSERT_TRUE(h.match("/dev/path/a.bin"));
+    ASSERT_TRUE(h.match("/dev/other/a.bin"));
+    ASSERT_FALSE(h.match("/dev/other/c.bin"));
+    ASSERT_FALSE(h.match("/dev/path/b.bin"));
+}
+
 }  // namespace init
 }  // namespace android
 
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index 84cda98..78e5b60 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -329,23 +329,10 @@
 
     // If "/force_debuggable" is present, the second-stage init will use a userdebug
     // sepolicy and load adb_debug.prop to allow adb root, if the device is unlocked.
-    bool found_debuggable = false;
-    std::string adb_debug_prop("/adb_debug.prop");
-    std::string userdebug_sepolicy("/userdebug_plat_sepolicy.cil");
     if (access("/force_debuggable", F_OK) == 0) {
-        found_debuggable = true;
-    } else if (access("/first_stage_ramdisk/force_debuggable", F_OK) == 0) {
-        // Fallback to legacy debug resource paths.
-        // TODO(b/186485355): removes the fallback path once it is not needed.
-        found_debuggable = true;
-        adb_debug_prop.insert(0, "/first_stage_ramdisk");
-        userdebug_sepolicy.insert(0, "/first_stage_ramdisk");
-    }
-
-    if (found_debuggable) {
         std::error_code ec;  // to invoke the overloaded copy_file() that won't throw.
-        if (!fs::copy_file(adb_debug_prop, kDebugRamdiskProp, ec) ||
-            !fs::copy_file(userdebug_sepolicy, kDebugRamdiskSEPolicy, ec)) {
+        if (!fs::copy_file("/adb_debug.prop", kDebugRamdiskProp, ec) ||
+            !fs::copy_file("/userdebug_plat_sepolicy.cil", kDebugRamdiskSEPolicy, ec)) {
             LOG(ERROR) << "Failed to setup debug ramdisk";
         } else {
             // setenv for second-stage init to read above kDebugRamdisk* files.
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 3faf430..a733839 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -331,6 +331,12 @@
     if (devices.empty()) {
         return true;
     }
+    // excluding overlays
+    for (auto iter = devices.begin(); iter != devices.end(); ) {
+        if (*iter=="overlay")  iter = devices.erase(iter);
+        else iter++;
+    }
+
     return block_dev_init_.InitDevices(std::move(devices));
 }
 
@@ -542,6 +548,11 @@
             continue;
         }
 
+        if (current->fs_type == "overlay") {
+            ++current;
+            continue;
+        }
+
         // Skip raw partition entries such as boot, dtbo, etc.
         // Having emmc fstab entries allows us to probe current->vbmeta_partition
         // in InitDevices() when they are AVB chained partitions.
@@ -591,6 +602,13 @@
     };
     MapScratchPartitionIfNeeded(&fstab_, init_devices);
 
+    for (auto current = fstab_.begin(); current != fstab_.end(); ) {
+        if (current->fs_type == "overlay") {
+            fs_mgr_overlayfs_mount_fstab_entry(current->lowerdir, current->mount_point);
+        }
+        ++current;
+    }
+
     fs_mgr_overlayfs_mount_all(&fstab_);
 
     return true;
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 6511bce..ff9da42 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -1230,55 +1230,10 @@
 
 constexpr auto ANDROIDBOOT_PREFIX = "androidboot."sv;
 
-// emulator specific, should be removed once emulator is migrated to
-// bootconfig, see b/182291166.
-static std::string RemapEmulatorPropertyName(const std::string_view qemu_key) {
-    if (StartsWith(qemu_key, "dalvik."sv) || StartsWith(qemu_key, "opengles."sv) ||
-        StartsWith(qemu_key, "config."sv)) {
-        return std::string(qemu_key);
-    } else if (qemu_key == "uirenderer"sv) {
-        return "debug.hwui.renderer"s;
-    } else if (qemu_key == "media.ccodec"sv) {
-        return "debug.stagefright.ccodec"s;
-    } else {
-        return "qemu."s + std::string(qemu_key);
-    }
-}
-
 static void ProcessKernelCmdline() {
     ImportKernelCmdline([&](const std::string& key, const std::string& value) {
-        constexpr auto qemu_prefix = "qemu."sv;
-
         if (StartsWith(key, ANDROIDBOOT_PREFIX)) {
             InitPropertySet("ro.boot." + key.substr(ANDROIDBOOT_PREFIX.size()), value);
-        } else if (StartsWith(key, qemu_prefix)) {
-            // emulator specific, should be retired once emulator migrates to
-            // androidboot.
-            const auto new_name =
-                    RemapEmulatorPropertyName(std::string_view(key).substr(qemu_prefix.size()));
-            if (!new_name.empty()) {
-                InitPropertySet("ro.boot." + new_name, value);
-            }
-        } else if (key == "qemu") {
-            // emulator specific, should be retired once emulator migrates to
-            // androidboot.
-            InitPropertySet("ro.boot." + key, value);
-        } else if (key == "android.bootanim" && value == "0") {
-            // emulator specific, should be retired once emulator migrates to
-            // androidboot.
-            InitPropertySet("ro.boot.debug.sf.nobootanimation", "1");
-        } else if (key == "android.checkjni") {
-            // emulator specific, should be retired once emulator migrates to
-            // androidboot.
-            std::string value_bool;
-            if (value == "0") {
-                value_bool = "false";
-            } else if (value == "1") {
-                value_bool = "true";
-            } else {
-                value_bool = value;
-            }
-            InitPropertySet("ro.boot.dalvik.vm.checkjni", value_bool);
         }
     });
 }
diff --git a/init/service.cpp b/init/service.cpp
index c3069f5..5af81bf 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -194,6 +194,8 @@
                   << ") process group...";
         int max_processes = 0;
         int r;
+
+        flags_ |= SVC_STOPPING;
         if (signal == SIGTERM) {
             r = killProcessGroupOnce(proc_attr_.uid, pid_, signal, &max_processes);
         } else {
@@ -277,7 +279,8 @@
         f(siginfo);
     }
 
-    if ((siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) && on_failure_reboot_target_) {
+    if ((siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) && on_failure_reboot_target_ &&
+        !(flags_ & SVC_STOPPING)) {
         LOG(ERROR) << "Service with 'reboot_on_failure' option failed, shutting down system.";
         trigger_shutdown(*on_failure_reboot_target_);
     }
@@ -287,7 +290,7 @@
     if (flags_ & SVC_TEMPORARY) return;
 
     pid_ = 0;
-    flags_ &= (~SVC_RUNNING);
+    flags_ &= ~(SVC_RUNNING | SVC_STOPPING);
     start_order_ = 0;
 
     // Oneshot processes go into the disabled state on exit,
@@ -411,7 +414,8 @@
     bool disabled = (flags_ & (SVC_DISABLED | SVC_RESET));
     // Starting a service removes it from the disabled or reset state and
     // immediately takes it out of the restarting state if it was in there.
-    flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));
+    flags_ &= (~(SVC_DISABLED | SVC_RESTARTING | SVC_RESET | SVC_RESTART | SVC_DISABLED_START |
+                 SVC_STOPPING));
 
     // Running processes require no additional work --- if they're in the
     // process of exiting, we've ensured that they will immediately restart
diff --git a/init/service.h b/init/service.h
index 043555f..89b1f09 100644
--- a/init/service.h
+++ b/init/service.h
@@ -54,6 +54,7 @@
                                      // should not be killed during shutdown
 #define SVC_TEMPORARY 0x1000  // This service was started by 'exec' and should be removed from the
                               // service list once it is reaped.
+#define SVC_STOPPING 0x2000  // service is being stopped by init
 
 #define NR_SVC_SUPP_GIDS 12    // twelve supplementary groups
 
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 6201569..6395567 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -141,6 +141,7 @@
         "Errors.cpp",
         "FileMap.cpp",
         "JenkinsHash.cpp",
+        "LightRefBase.cpp",
         "NativeHandle.cpp",
         "Printer.cpp",
         "RefBase.cpp",
diff --git a/libutils/LightRefBase.cpp b/libutils/LightRefBase.cpp
new file mode 100644
index 0000000..e08ffec
--- /dev/null
+++ b/libutils/LightRefBase.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#define LOG_TAG "LightRefBase"
+
+#include <utils/LightRefBase.h>
+
+#include <log/log.h>
+
+namespace android {
+
+void LightRefBase_reportIncStrongRequireStrongFailed(const void* thiz) {
+    LOG_ALWAYS_FATAL("incStrongRequireStrong() called on %p which isn't already owned", thiz);
+}
+
+}  // namespace android
diff --git a/libutils/StrongPointer_test.cpp b/libutils/StrongPointer_test.cpp
index 29f6bd4..f27c1f1 100644
--- a/libutils/StrongPointer_test.cpp
+++ b/libutils/StrongPointer_test.cpp
@@ -30,17 +30,34 @@
     ~SPFoo() {
         *mDeleted = true;
     }
-private:
+
+  private:
     bool* mDeleted;
 };
 
-TEST(StrongPointer, move) {
+class SPLightFoo : virtual public VirtualLightRefBase {
+  public:
+    explicit SPLightFoo(bool* deleted_check) : mDeleted(deleted_check) { *mDeleted = false; }
+
+    ~SPLightFoo() { *mDeleted = true; }
+
+  private:
+    bool* mDeleted;
+};
+
+template <typename T>
+class StrongPointer : public ::testing::Test {};
+
+using RefBaseTypes = ::testing::Types<SPFoo, SPLightFoo>;
+TYPED_TEST_CASE(StrongPointer, RefBaseTypes);
+
+TYPED_TEST(StrongPointer, move) {
     bool isDeleted;
-    sp<SPFoo> sp1 = sp<SPFoo>::make(&isDeleted);
-    SPFoo* foo = sp1.get();
+    sp<TypeParam> sp1 = sp<TypeParam>::make(&isDeleted);
+    TypeParam* foo = sp1.get();
     ASSERT_EQ(1, foo->getStrongCount());
     {
-        sp<SPFoo> sp2 = std::move(sp1);
+        sp<TypeParam> sp2 = std::move(sp1);
         ASSERT_EQ(1, foo->getStrongCount()) << "std::move failed, incremented refcnt";
         ASSERT_EQ(nullptr, sp1.get()) << "std::move failed, sp1 is still valid";
         // The strong count isn't increasing, let's double check the old object
@@ -50,33 +67,42 @@
     ASSERT_FALSE(isDeleted) << "deleted too early! still has a reference!";
     {
         // Now let's double check it deletes on time
-        sp<SPFoo> sp2 = std::move(sp1);
+        sp<TypeParam> sp2 = std::move(sp1);
     }
     ASSERT_TRUE(isDeleted) << "foo was leaked!";
 }
 
-TEST(StrongPointer, NullptrComparison) {
-    sp<SPFoo> foo;
+TYPED_TEST(StrongPointer, NullptrComparison) {
+    sp<TypeParam> foo;
     ASSERT_EQ(foo, nullptr);
     ASSERT_EQ(nullptr, foo);
 }
 
-TEST(StrongPointer, PointerComparison) {
+TYPED_TEST(StrongPointer, PointerComparison) {
     bool isDeleted;
-    sp<SPFoo> foo = sp<SPFoo>::make(&isDeleted);
+    sp<TypeParam> foo = sp<TypeParam>::make(&isDeleted);
     ASSERT_EQ(foo.get(), foo);
     ASSERT_EQ(foo, foo.get());
     ASSERT_NE(nullptr, foo);
     ASSERT_NE(foo, nullptr);
 }
 
-TEST(StrongPointer, AssertStrongRefExists) {
-    // uses some other refcounting method, or non at all
+TYPED_TEST(StrongPointer, Deleted) {
     bool isDeleted;
-    SPFoo* foo = new SPFoo(&isDeleted);
+    sp<TypeParam> foo = sp<TypeParam>::make(&isDeleted);
 
-    // can only get a valid sp<> object when you construct it as an sp<> object
-    EXPECT_DEATH(sp<SPFoo>::fromExisting(foo), "");
+    auto foo2 = sp<TypeParam>::fromExisting(foo.get());
 
+    EXPECT_FALSE(isDeleted);
+    foo = nullptr;
+    EXPECT_FALSE(isDeleted);
+    foo2 = nullptr;
+    EXPECT_TRUE(isDeleted);
+}
+
+TYPED_TEST(StrongPointer, AssertStrongRefExists) {
+    bool isDeleted;
+    TypeParam* foo = new TypeParam(&isDeleted);
+    EXPECT_DEATH(sp<TypeParam>::fromExisting(foo), "");
     delete foo;
 }
diff --git a/libutils/include/utils/LightRefBase.h b/libutils/include/utils/LightRefBase.h
index b04e5c1..40edf67 100644
--- a/libutils/include/utils/LightRefBase.h
+++ b/libutils/include/utils/LightRefBase.h
@@ -28,6 +28,8 @@
 
 class ReferenceRenamer;
 
+void LightRefBase_reportIncStrongRequireStrongFailed(const void* thiz);
+
 template <class T>
 class LightRefBase
 {
@@ -36,6 +38,11 @@
     inline void incStrong(__attribute__((unused)) const void* id) const {
         mCount.fetch_add(1, std::memory_order_relaxed);
     }
+    inline void incStrongRequireStrong(__attribute__((unused)) const void* id) const {
+        if (0 == mCount.fetch_add(1, std::memory_order_relaxed)) {
+            LightRefBase_reportIncStrongRequireStrongFailed(this);
+        }
+    }
     inline void decStrong(__attribute__((unused)) const void* id) const {
         if (mCount.fetch_sub(1, std::memory_order_release) == 1) {
             std::atomic_thread_fence(std::memory_order_acquire);
@@ -59,7 +66,6 @@
     mutable std::atomic<int32_t> mCount;
 };
 
-
 // This is a wrapper around LightRefBase that simply enforces a virtual
 // destructor to eliminate the template requirement of LightRefBase
 class VirtualLightRefBase : public LightRefBase<VirtualLightRefBase> {
diff --git a/cpio/Android.bp b/mkbootfs/Android.bp
similarity index 100%
rename from cpio/Android.bp
rename to mkbootfs/Android.bp
diff --git a/cpio/mkbootfs.c b/mkbootfs/mkbootfs.c
similarity index 100%
rename from cpio/mkbootfs.c
rename to mkbootfs/mkbootfs.c
diff --git a/rootdir/etc/linker.config.json b/rootdir/etc/linker.config.json
index a22ef6f..6b03a1d 100644
--- a/rootdir/etc/linker.config.json
+++ b/rootdir/etc/linker.config.json
@@ -1,13 +1,14 @@
 {
   "requireLibs": [
+    "libandroidicu.so",
     "libdexfile.so",
     "libdexfiled.so",
+    "libicu.so",
+    "libjdwp.so",
     "libnativebridge.so",
     "libnativehelper.so",
     "libnativeloader.so",
     "libsigchain.so",
-    "libandroidicu.so",
-    "libicu.so",
     // TODO(b/122876336): Remove libpac.so once it's migrated to Webview
     "libpac.so",
     // TODO(b/120786417 or b/134659294): libicuuc.so
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 4ec5d33..1013d41 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -692,7 +692,7 @@
     mkdir /data/apex 0755 root system encryption=None
     mkdir /data/apex/active 0755 root system
     mkdir /data/apex/backup 0700 root system
-    mkdir /data/apex/decompressed 0700 root system encryption=Require
+    mkdir /data/apex/decompressed 0755 root system encryption=Require
     mkdir /data/apex/hashtree 0700 root system
     mkdir /data/apex/sessions 0700 root system
     mkdir /data/app-staging 0751 system system encryption=DeleteIfNecessary
diff --git a/trusty/metrics/Android.bp b/trusty/metrics/Android.bp
new file mode 100644
index 0000000..e0533bc
--- /dev/null
+++ b/trusty/metrics/Android.bp
@@ -0,0 +1,51 @@
+// Copyright (C) 2021 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.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_library {
+    name: "libtrusty_metrics",
+    vendor: true,
+    srcs: [
+        "metrics.cpp",
+    ],
+    export_include_dirs: [
+        "include",
+    ],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libtrusty",
+    ],
+}
+
+cc_test {
+    name: "libtrusty_metrics_test",
+    vendor: true,
+    srcs: [
+        "metrics_test.cpp",
+    ],
+    static_libs: [
+        "libtrusty_metrics",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "liblog",
+        "libtrusty",
+    ],
+    require_root: true,
+}
diff --git a/trusty/metrics/include/trusty/metrics/metrics.h b/trusty/metrics/include/trusty/metrics/metrics.h
new file mode 100644
index 0000000..6949e9b
--- /dev/null
+++ b/trusty/metrics/include/trusty/metrics/metrics.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <string>
+
+#include <android-base/result.h>
+#include <android-base/unique_fd.h>
+
+namespace android {
+namespace trusty {
+namespace metrics {
+
+using android::base::Result;
+using android::base::unique_fd;
+
+class TrustyMetrics {
+  public:
+    /* Wait for next event with a given timeout. Negative timeout means infinite timeout. */
+    Result<void> WaitForEvent(int timeout_ms = -1);
+    /* Attempt to handle an event from Metrics TA in a non-blocking manner. */
+    Result<void> HandleEvent();
+    /* Expose TIPC channel so that client can integrate it into an event loop with other fds. */
+    int GetRawFd() { return metrics_fd_; };
+
+  protected:
+    TrustyMetrics(std::string tipc_dev) : tipc_dev_(std::move(tipc_dev)), metrics_fd_(-1) {}
+    virtual ~TrustyMetrics(){};
+
+    Result<void> Open();
+    virtual void HandleCrash(const std::string& app_id) = 0;
+    virtual void HandleEventDrop() = 0;
+
+  private:
+    std::string tipc_dev_;
+    unique_fd metrics_fd_;
+};
+
+}  // namespace metrics
+}  // namespace trusty
+}  // namespace android
diff --git a/trusty/metrics/include/trusty/metrics/tipc.h b/trusty/metrics/include/trusty/metrics/tipc.h
new file mode 100644
index 0000000..66d0876
--- /dev/null
+++ b/trusty/metrics/include/trusty/metrics/tipc.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+/**
+ * DOC: Metrics
+ *
+ * Metrics interface provides a way for Android to get Trusty metrics data.
+ *
+ * Currently, only "push" model is supported. Clients are expected to connect to
+ * metrics service, listen for events, e.g. app crash events, and respond to
+ * every event with a &struct metrics_req.
+ *
+ * Communication is driven by metrics service, i.e. requests/responses are all
+ * sent from/to metrics service.
+ *
+ * Note that the type of the event is not known to the client ahead of time.
+ *
+ * In the future, if we need to have Android "pull" metrics data from Trusty,
+ * that can be done by introducing a separate port.
+ *
+ * This interface is shared between Android and Trusty. There is a copy in each
+ * repository. They must be kept in sync.
+ */
+
+#define METRICS_PORT "com.android.trusty.metrics"
+
+/**
+ * enum metrics_cmd - command identifiers for metrics interface
+ * @METRICS_CMD_RESP_BIT:          message is a response
+ * @METRICS_CMD_REQ_SHIFT:         number of bits used by @METRICS_CMD_RESP_BIT
+ * @METRICS_CMD_REPORT_EVENT_DROP: report gaps in the event stream
+ * @METRICS_CMD_REPORT_CRASH:      report an app crash event
+ */
+enum metrics_cmd {
+    METRICS_CMD_RESP_BIT = 1,
+    METRICS_CMD_REQ_SHIFT = 1,
+
+    METRICS_CMD_REPORT_EVENT_DROP = (1 << METRICS_CMD_REQ_SHIFT),
+    METRICS_CMD_REPORT_CRASH = (2 << METRICS_CMD_REQ_SHIFT),
+};
+
+/**
+ * enum metrics_error - metrics error codes
+ * @METRICS_NO_ERROR:        no error
+ * @METRICS_ERR_UNKNOWN_CMD: unknown or not implemented command
+ */
+enum metrics_error {
+    METRICS_NO_ERROR = 0,
+    METRICS_ERR_UNKNOWN_CMD = 1,
+};
+
+/**
+ * struct metrics_req - common structure for metrics requests
+ * @cmd:      command identifier - one of &enum metrics_cmd
+ * @reserved: must be 0
+ */
+struct metrics_req {
+    uint32_t cmd;
+    uint32_t reserved;
+} __attribute__((__packed__));
+
+/**
+ * struct metrics_resp - common structure for metrics responses
+ * @cmd: command identifier - %METRICS_CMD_RESP_BIT or'ed with a cmd in
+ *                            one of &enum metrics_cmd
+ * @status: response status, one of &enum metrics_error
+ */
+struct metrics_resp {
+    uint32_t cmd;
+    uint32_t status;
+} __attribute__((__packed__));
+
+/**
+ * struct metrics_report_crash_req - arguments of %METRICS_CMD_REPORT_CRASH
+ *                                   requests
+ * @app_id_len: length of app ID that follows this structure
+ */
+struct metrics_report_crash_req {
+    uint32_t app_id_len;
+} __attribute__((__packed__));
+
+#define METRICS_MAX_APP_ID_LEN 256
+
+#define METRICS_MAX_MSG_SIZE                                                \
+    (sizeof(struct metrics_req) + sizeof(struct metrics_report_crash_req) + \
+     METRICS_MAX_APP_ID_LEN)
diff --git a/trusty/metrics/metrics.cpp b/trusty/metrics/metrics.cpp
new file mode 100644
index 0000000..3ac128a
--- /dev/null
+++ b/trusty/metrics/metrics.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2021 The Android Open Sourete 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.
+ */
+
+#define LOG_TAG "metrics"
+
+#include <android-base/logging.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <trusty/metrics/metrics.h>
+#include <trusty/metrics/tipc.h>
+#include <trusty/tipc.h>
+#include <unistd.h>
+
+namespace android {
+namespace trusty {
+namespace metrics {
+
+using android::base::ErrnoError;
+using android::base::Error;
+
+Result<void> TrustyMetrics::Open() {
+    int fd = tipc_connect(tipc_dev_.c_str(), METRICS_PORT);
+    if (fd < 0) {
+        return ErrnoError() << "failed to connect to Trusty metrics TA";
+    }
+
+    int flags = fcntl(fd, F_GETFL, 0);
+    if (flags < 0) {
+        return ErrnoError() << "failed F_GETFL";
+    }
+
+    int rc = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+    if (rc < 0) {
+        return ErrnoError() << "failed F_SETFL";
+    }
+
+    metrics_fd_.reset(fd);
+    return {};
+}
+
+Result<void> TrustyMetrics::WaitForEvent(int timeout_ms) {
+    if (!metrics_fd_.ok()) {
+        return Error() << "connection to Metrics TA has not been initialized yet";
+    }
+
+    struct pollfd pfd = {
+            .fd = metrics_fd_,
+            .events = POLLIN,
+    };
+
+    int rc = poll(&pfd, 1, timeout_ms);
+    if (rc != 1) {
+        return ErrnoError() << "failed poll()";
+    }
+
+    if (!(pfd.revents & POLLIN)) {
+        return ErrnoError() << "channel not ready";
+    }
+
+    return {};
+}
+
+Result<void> TrustyMetrics::HandleEvent() {
+    if (!metrics_fd_.ok()) {
+        return Error() << "connection to Metrics TA has not been initialized yet";
+    }
+
+    uint8_t msg[METRICS_MAX_MSG_SIZE];
+
+    auto rc = read(metrics_fd_, msg, sizeof(msg));
+    if (rc < 0) {
+        return ErrnoError() << "failed to read metrics message";
+    }
+    size_t msg_len = rc;
+
+    if (msg_len < sizeof(metrics_req)) {
+        return Error() << "message too small: " << rc;
+    }
+    auto req = reinterpret_cast<metrics_req*>(msg);
+    size_t offset = sizeof(metrics_req);
+    uint32_t status = METRICS_NO_ERROR;
+
+    switch (req->cmd) {
+        case METRICS_CMD_REPORT_CRASH: {
+            if (msg_len < offset + sizeof(metrics_report_crash_req)) {
+                return Error() << "message too small: " << rc;
+            }
+            auto crash_args = reinterpret_cast<metrics_report_crash_req*>(msg + offset);
+            offset += sizeof(metrics_report_crash_req);
+
+            if (msg_len < offset + crash_args->app_id_len) {
+                return Error() << "message too small: " << rc;
+            }
+            auto app_id_ptr = reinterpret_cast<char*>(msg + offset);
+            std::string app_id(app_id_ptr, crash_args->app_id_len);
+
+            HandleCrash(app_id);
+            break;
+        }
+
+        case METRICS_CMD_REPORT_EVENT_DROP:
+            HandleEventDrop();
+            break;
+
+        default:
+            status = METRICS_ERR_UNKNOWN_CMD;
+            break;
+    }
+
+    metrics_resp resp = {
+            .cmd = req->cmd | METRICS_CMD_RESP_BIT,
+            .status = status,
+    };
+
+    rc = write(metrics_fd_, &resp, sizeof(resp));
+    if (rc < 0) {
+        return ErrnoError() << "failed to request next metrics event";
+    }
+
+    if (rc != (int)sizeof(resp)) {
+        return Error() << "unexpected number of bytes sent event: " << rc;
+    }
+
+    return {};
+}
+
+}  // namespace metrics
+}  // namespace trusty
+}  // namespace android
diff --git a/trusty/metrics/metrics_test.cpp b/trusty/metrics/metrics_test.cpp
new file mode 100644
index 0000000..407ddf2
--- /dev/null
+++ b/trusty/metrics/metrics_test.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2021 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 <android-base/unique_fd.h>
+#include <binder/IPCThreadState.h>
+#include <gtest/gtest.h>
+#include <poll.h>
+#include <trusty/metrics/metrics.h>
+#include <trusty/tipc.h>
+
+#define TIPC_DEV "/dev/trusty-ipc-dev0"
+#define CRASHER_PORT "com.android.trusty.metrics.test.crasher"
+
+namespace android {
+namespace trusty {
+namespace metrics {
+
+using android::base::unique_fd;
+
+static void TriggerCrash() {
+    size_t num_retries = 3;
+    int fd = -1;
+
+    for (size_t i = 0; i < num_retries; i++) {
+        /* It's possible to time out waiting for crasher TA to restart. */
+        fd = tipc_connect(TIPC_DEV, CRASHER_PORT);
+        if (fd >= 0) {
+            break;
+        }
+    }
+
+    unique_fd crasher(fd);
+    ASSERT_GE(crasher, 0);
+
+    int msg = 0;
+    int rc = write(crasher, &msg, sizeof(msg));
+    ASSERT_EQ(rc, sizeof(msg));
+}
+
+class TrustyMetricsTest : public TrustyMetrics, public ::testing::Test {
+  public:
+    TrustyMetricsTest() : TrustyMetrics(TIPC_DEV) {}
+
+    virtual void HandleCrash(const std::string& app_id) override { crashed_app_ = app_id; }
+
+    virtual void HandleEventDrop() override { event_drop_count_++; }
+
+    virtual void SetUp() override {
+        auto ret = Open();
+        ASSERT_TRUE(ret.ok()) << ret.error();
+    }
+
+    void WaitForAndHandleEvent() {
+        auto ret = WaitForEvent(30000 /* 30 second timeout */);
+        ASSERT_TRUE(ret.ok()) << ret.error();
+
+        ret = HandleEvent();
+        ASSERT_TRUE(ret.ok()) << ret.error();
+    }
+
+    std::string crashed_app_;
+    size_t event_drop_count_;
+};
+
+TEST_F(TrustyMetricsTest, Crash) {
+    TriggerCrash();
+    WaitForAndHandleEvent();
+
+    /* Check that correct TA crashed. */
+    ASSERT_EQ(crashed_app_, "36f5b435-5bd3-4526-8b76-200e3a7e79f3:crasher");
+}
+
+TEST_F(TrustyMetricsTest, PollSet) {
+    int binder_fd;
+    int rc = IPCThreadState::self()->setupPolling(&binder_fd);
+    ASSERT_EQ(rc, 0);
+    ASSERT_GE(binder_fd, 0);
+
+    TriggerCrash();
+
+    struct pollfd pfds[] = {
+            {
+                    .fd = binder_fd,
+                    .events = POLLIN,
+            },
+            {
+                    .fd = GetRawFd(),
+                    .events = POLLIN,
+            },
+    };
+
+    rc = poll(pfds, 2, 30000 /* 30 second timeout */);
+    /* We expect one event on the metrics fd. */
+    ASSERT_EQ(rc, 1);
+    ASSERT_TRUE(pfds[1].revents & POLLIN);
+
+    auto ret = HandleEvent();
+    ASSERT_TRUE(ret.ok()) << ret.error();
+
+    /* Check that correct TA crashed. */
+    ASSERT_EQ(crashed_app_, "36f5b435-5bd3-4526-8b76-200e3a7e79f3:crasher");
+}
+
+TEST_F(TrustyMetricsTest, EventDrop) {
+    /* We know the size of the internal event queue is less than this. */
+    size_t num_events = 3;
+
+    ASSERT_EQ(event_drop_count_, 0);
+
+    for (auto i = 0; i < num_events; i++) {
+        TriggerCrash();
+    }
+
+    for (auto i = 0; i < num_events; i++) {
+        WaitForAndHandleEvent();
+        if (event_drop_count_ > 0) {
+            break;
+        }
+    }
+
+    ASSERT_EQ(event_drop_count_, 1);
+}
+
+}  // namespace metrics
+}  // namespace trusty
+}  // namespace android