Merge "Revert "Update native watchdog to be triggered after 20 restarts instead of 4."" into main
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 25031bf..e26746b 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -108,7 +108,7 @@
                            "persist.device_config.memory_safety_native.permissive.process.%s",
                            getprogname());
   // DO NOT REPLACE this with GetBoolProperty. That uses std::string which allocates, so it is
-  // not async-safe (and this functiong gets used in a signal handler).
+  // not async-safe, and this function gets used in a signal handler.
   return property_parse_bool("persist.sys.mte.permissive") ||
          property_parse_bool("persist.device_config.memory_safety_native.permissive.default") ||
          property_parse_bool(process_sysprop_name) ||
diff --git a/fs_mgr/TEST_MAPPING b/fs_mgr/TEST_MAPPING
index 1989a5c..32e8b88 100644
--- a/fs_mgr/TEST_MAPPING
+++ b/fs_mgr/TEST_MAPPING
@@ -25,8 +25,6 @@
     {
       "name": "vab_legacy_tests"
     },
-    // TODO(b/279009697):
-    //{"name": "vabc_legacy_tests"},
     {
       "name": "cow_api_test"
     },
@@ -44,8 +42,6 @@
     {
       "name": "vab_legacy_tests"
     },
-    // TODO(b/279009697):
-    //{"name": "vabc_legacy_tests"}
     {
       "name": "snapuserd_test"
     }
diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp
index 5cc0346..c3ca758 100644
--- a/fs_mgr/libdm/Android.bp
+++ b/fs_mgr/libdm/Android.bp
@@ -71,6 +71,9 @@
         "libbase",
         "liblog",
     ],
+    header_libs: [
+        "libstorage_literals_headers",
+    ],
     srcs: [":libdm_test_srcs"],
     auto_gen_config: true,
     require_root: true,
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index fee67fdf..a963322 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -769,5 +769,25 @@
     return true;
 }
 
+bool DeviceMapper::SendMessage(const std::string& name, uint64_t sector,
+                               const std::string& message) {
+    std::string ioctl_buffer(sizeof(struct dm_ioctl) + sizeof(struct dm_target_msg), 0);
+    ioctl_buffer += message;
+    ioctl_buffer.push_back('\0');
+
+    struct dm_ioctl* io = reinterpret_cast<struct dm_ioctl*>(&ioctl_buffer[0]);
+    InitIo(io, name);
+    io->data_size = ioctl_buffer.size();
+    io->data_start = sizeof(struct dm_ioctl);
+    struct dm_target_msg* msg =
+            reinterpret_cast<struct dm_target_msg*>(&ioctl_buffer[sizeof(struct dm_ioctl)]);
+    msg->sector = sector;
+    if (ioctl(fd_, DM_TARGET_MSG, io)) {
+        PLOG(ERROR) << "DM_TARGET_MSG failed";
+        return false;
+    }
+    return true;
+}
+
 }  // namespace dm
 }  // namespace android
diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp
index 1f6bd1a..b5cc9aa 100644
--- a/fs_mgr/libdm/dm_target.cpp
+++ b/fs_mgr/libdm/dm_target.cpp
@@ -298,5 +298,43 @@
     return android::base::Join(argv, " ");
 }
 
+DmTargetThinPool::DmTargetThinPool(uint64_t start, uint64_t length, const std::string& metadata_dev,
+                                   const std::string& data_dev, uint64_t data_block_size,
+                                   uint64_t low_water_mark)
+    : DmTarget(start, length),
+      metadata_dev_(metadata_dev),
+      data_dev_(data_dev),
+      data_block_size_(data_block_size),
+      low_water_mark_(low_water_mark) {}
+
+std::string DmTargetThinPool::GetParameterString() const {
+    std::vector<std::string> args{
+            metadata_dev_,
+            data_dev_,
+            std::to_string(data_block_size_),
+            std::to_string(low_water_mark_),
+    };
+    return android::base::Join(args, " ");
+}
+
+bool DmTargetThinPool::Valid() const {
+    // data_block_size: must be between 128 (64KB) and 2097152 (1GB) and a multiple of 128 (64KB)
+    if (data_block_size_ < 128 || data_block_size_ > 2097152) return false;
+    if (data_block_size_ % 128) return false;
+    return true;
+}
+
+DmTargetThin::DmTargetThin(uint64_t start, uint64_t length, const std::string& pool_dev,
+                           uint64_t dev_id)
+    : DmTarget(start, length), pool_dev_(pool_dev), dev_id_(dev_id) {}
+
+std::string DmTargetThin::GetParameterString() const {
+    std::vector<std::string> args{
+            pool_dev_,
+            std::to_string(dev_id_),
+    };
+    return android::base::Join(args, " ");
+}
+
 }  // namespace dm
 }  // namespace android
diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp
index d043be6..b890f47 100644
--- a/fs_mgr/libdm/dm_test.cpp
+++ b/fs_mgr/libdm/dm_test.cpp
@@ -37,12 +37,14 @@
 #include <gtest/gtest.h>
 #include <libdm/dm.h>
 #include <libdm/loop_control.h>
+#include <storage_literals/storage_literals.h>
 #include "test_util.h"
 #include "utility.h"
 
 using namespace std;
 using namespace std::chrono_literals;
 using namespace android::dm;
+using namespace android::storage_literals;
 using android::base::make_scope_guard;
 using android::base::unique_fd;
 
@@ -773,3 +775,42 @@
     ASSERT_EQ(name, test_name_);
     ASSERT_FALSE(uuid.empty());
 }
+
+TEST_F(DmTest, ThinProvisioning) {
+    if (!DeviceMapper::Instance().GetTargetByName("thin-pool", nullptr)) GTEST_SKIP();
+
+    constexpr uint64_t MetaSize = 2_MiB;
+    constexpr uint64_t DataSize = 64_MiB;
+    constexpr uint64_t ThinSize = 1_TiB;
+
+    // Prepare two loop devices for meta and data devices.
+    TemporaryFile meta;
+    ASSERT_GE(meta.fd, 0);
+    ASSERT_EQ(0, ftruncate64(meta.fd, MetaSize));
+    TemporaryFile data;
+    ASSERT_GE(data.fd, 0);
+    ASSERT_EQ(0, ftruncate64(data.fd, DataSize));
+
+    LoopDevice loop_meta(meta.fd, 10s);
+    ASSERT_TRUE(loop_meta.valid());
+    LoopDevice loop_data(data.fd, 10s);
+    ASSERT_TRUE(loop_data.valid());
+
+    // Create a thin-pool
+    DmTable poolTable;
+    poolTable.Emplace<DmTargetThinPool>(0, DataSize / kSectorSize, loop_meta.device(),
+                                        loop_data.device(), 128, 0);
+    TempDevice pool("pool", poolTable);
+    ASSERT_TRUE(pool.valid());
+
+    // Create a thin volume
+    uint64_t thin_volume_id = 0;
+    ASSERT_TRUE(DeviceMapper::Instance().SendMessage(
+            "pool", 0, "create_thin " + std::to_string(thin_volume_id)));
+
+    // Use a thin volume to create a 1T device
+    DmTable thinTable;
+    thinTable.Emplace<DmTargetThin>(0, ThinSize / kSectorSize, pool.path(), thin_volume_id);
+    TempDevice thin("thin", thinTable);
+    ASSERT_TRUE(thin.valid());
+}
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index fa97653..43d84f9 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -307,6 +307,9 @@
 
     bool GetDeviceNameAndUuid(dev_t dev, std::string* name, std::string* uuid);
 
+    // Send |message| to target, pointed by |name| and |sector|. Use 0 if |sector| is not needed.
+    bool SendMessage(const std::string& name, uint64_t sector, const std::string& message);
+
   private:
     // Maximum possible device mapper targets registered in the kernel.
     // This is only used to read the list of targets from kernel so we allocate
diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h
index 97f3c13..c49fc5e 100644
--- a/fs_mgr/libdm/include/libdm/dm_target.h
+++ b/fs_mgr/libdm/include/libdm/dm_target.h
@@ -349,6 +349,35 @@
     std::string GetParameterString() const override { return ""; }
 };
 
+class DmTargetThinPool final : public DmTarget {
+  public:
+    DmTargetThinPool(uint64_t start, uint64_t length, const std::string& metadata_dev,
+                     const std::string& data_dev, uint64_t data_block_size,
+                     uint64_t low_water_mark);
+
+    std::string name() const override { return "thin-pool"; }
+    std::string GetParameterString() const override;
+    bool Valid() const override;
+
+  private:
+    std::string metadata_dev_;
+    std::string data_dev_;
+    uint64_t data_block_size_;
+    uint64_t low_water_mark_;
+};
+
+class DmTargetThin final : public DmTarget {
+  public:
+    DmTargetThin(uint64_t start, uint64_t length, const std::string& pool_dev, uint64_t dev_id);
+
+    std::string name() const override { return "thin"; }
+    std::string GetParameterString() const override;
+
+  private:
+    std::string pool_dev_;
+    uint64_t dev_id_;
+};
+
 }  // namespace dm
 }  // namespace android
 
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
index 651083f..2c6eefb 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
@@ -45,7 +45,7 @@
     std::optional<uint64_t> max_blocks;
 
     // Number of CowOperations in a cluster. 0 for no clustering. Cannot be 1.
-    uint32_t cluster_ops = 200;
+    uint32_t cluster_ops = 1024;
 
     bool scratch_space = true;
 
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
index 8cc9964..73deafb 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
@@ -214,15 +214,6 @@
             return false;
         }
     }
-
-    // TODO: b/322279333
-    // Set compression factor to 4k during estimation.
-    // Once COW estimator is ready to support variable
-    // block size, this check has to be removed.
-    if (IsEstimating()) {
-        header_.max_compression_size = header_.block_size;
-    }
-
     return true;
 }
 
@@ -310,6 +301,14 @@
     return true;
 }
 
+size_t CowWriterV3::CachedDataSize() const {
+    size_t size = 0;
+    for (const auto& i : cached_data_) {
+        size += i.size();
+    }
+    return size;
+}
+
 bool CowWriterV3::EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks) {
     if (!CheckOpCount(num_blocks)) {
         return false;
@@ -342,7 +341,7 @@
     // Allow bigger batch sizes for ops without data. A single CowOperationV3
     // struct uses 14 bytes of memory, even if we cache 200 * 16 ops in memory,
     // it's only ~44K.
-    return cached_data_.size() >= batch_size_ ||
+    return CachedDataSize() >= batch_size_ * header_.block_size ||
            cached_ops_.size() >= batch_size_ * kNonDataOpBufferSize;
 }
 
@@ -397,13 +396,13 @@
         return false;
     }
     const auto bytes = reinterpret_cast<const uint8_t*>(data);
-    const size_t num_blocks = (size / header_.block_size);
-    for (size_t i = 0; i < num_blocks;) {
-        const size_t blocks_to_write =
-                std::min<size_t>(batch_size_ - cached_data_.size(), num_blocks - i);
-
-        if (!ConstructCowOpCompressedBuffers(new_block_start + i, bytes + header_.block_size * i,
-                                             old_block + i, offset, type, blocks_to_write)) {
+    size_t num_blocks = (size / header_.block_size);
+    size_t total_written = 0;
+    while (total_written < num_blocks) {
+        size_t chunk = std::min(num_blocks - total_written, batch_size_);
+        if (!ConstructCowOpCompressedBuffers(new_block_start + total_written,
+                                             bytes + header_.block_size * total_written,
+                                             old_block + total_written, offset, type, chunk)) {
             return false;
         }
 
@@ -413,8 +412,7 @@
                        << ", op type: " << type;
             return false;
         }
-
-        i += blocks_to_write;
+        total_written += chunk;
     }
 
     return true;
@@ -482,7 +480,8 @@
 
     header_.sequence_data_count = num_ops;
 
-    // Ensure next_data_pos_ is updated as previously initialized + the newly added sequence buffer.
+    // Ensure next_data_pos_ is updated as previously initialized + the newly added sequence
+    // buffer.
     CHECK_EQ(next_data_pos_ + header_.sequence_data_count * sizeof(uint32_t),
              GetDataOffset(header_));
     next_data_pos_ = GetDataOffset(header_);
@@ -640,8 +639,8 @@
     //                   t1     t2     t1     t2    <- processed by these threads
     // Ordering is important here. We need to retrieve the compressed data in the same order we
     // processed it and assume that that we submit data beginning with the first thread and then
-    // round robin the consecutive data calls. We need to Fetch compressed buffers from the threads
-    // via the same ordering
+    // round robin the consecutive data calls. We need to Fetch compressed buffers from the
+    // threads via the same ordering
     for (size_t i = 0; i < compressed_vec.size(); i++) {
         compressed_buf.emplace_back(worker_buffers[i % num_threads][i / num_threads]);
     }
@@ -733,7 +732,8 @@
         }
         if (total_written != total_data_size) {
             PLOG(ERROR) << "write failed for data of size: " << data.size()
-                        << " at offset: " << next_data_pos_ << " " << errno;
+                        << " at offset: " << next_data_pos_ << " " << errno
+                        << ", only wrote: " << total_written;
             return false;
         }
     }
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
index e2dc698..871ed27 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
@@ -94,7 +94,7 @@
         }
         return false;
     }
-
+    size_t CachedDataSize() const;
     bool ReadBackVerification();
     bool FlushCacheOps();
     void InitWorkers();
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 6d344bd..de91bd2 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -3018,6 +3018,7 @@
         status.set_merge_phase(old_status.merge_phase());
         status.set_userspace_snapshots(old_status.userspace_snapshots());
         status.set_io_uring_enabled(old_status.io_uring_enabled());
+        status.set_legacy_snapuserd(old_status.legacy_snapuserd());
     }
     return WriteSnapshotUpdateStatus(lock, status);
 }
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 8d0c898..80dad17 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -2883,7 +2883,16 @@
     ::testing::AddGlobalTestEnvironment(new ::android::snapshot::SnapshotTestEnvironment());
     gflags::ParseCommandLineFlags(&argc, &argv, false);
 
-    android::base::SetProperty("ctl.stop", "snapuserd");
+    bool vab_legacy = false;
+    if (FLAGS_force_mode == "vab-legacy") {
+        vab_legacy = true;
+    }
+
+    if (!vab_legacy) {
+        // This is necessary if the configuration we're testing doesn't match the device.
+        android::base::SetProperty("ctl.stop", "snapuserd");
+        android::snapshot::KillSnapuserd();
+    }
 
     std::unordered_set<std::string> modes = {"", "vab-legacy"};
     if (modes.count(FLAGS_force_mode) == 0) {
@@ -2891,13 +2900,12 @@
         return 1;
     }
 
-    // This is necessary if the configuration we're testing doesn't match the device.
-    android::snapshot::KillSnapuserd();
-
     int ret = RUN_ALL_TESTS();
 
     android::base::SetProperty("snapuserd.test.io_uring.force_disable", "0");
 
-    android::snapshot::KillSnapuserd();
+    if (!vab_legacy) {
+        android::snapshot::KillSnapuserd();
+    }
     return ret;
 }
diff --git a/fs_mgr/libsnapshot/snapshotctl.cpp b/fs_mgr/libsnapshot/snapshotctl.cpp
index 5d3f96c..192e1d6 100644
--- a/fs_mgr/libsnapshot/snapshotctl.cpp
+++ b/fs_mgr/libsnapshot/snapshotctl.cpp
@@ -47,7 +47,9 @@
 
 #include "partition_cow_creator.h"
 
+#ifdef SNAPSHOTCTL_USERDEBUG_OR_ENG
 #include <BootControlClient.h>
+#endif
 
 using namespace std::chrono_literals;
 using namespace std::string_literals;
@@ -92,6 +94,7 @@
 namespace android {
 namespace snapshot {
 
+#ifdef SNAPSHOTCTL_USERDEBUG_OR_ENG
 class MapSnapshots {
   public:
     MapSnapshots(std::string path = "");
@@ -462,6 +465,7 @@
     }
     return true;
 }
+#endif
 
 bool DumpCmdHandler(int /*argc*/, char** argv) {
     android::base::InitLogging(argv, TeeLogger(LogdLogger(), &StderrLogger));
@@ -485,6 +489,7 @@
     return false;
 }
 
+#ifdef SNAPSHOTCTL_USERDEBUG_OR_ENG
 bool GetVerityPartitions(std::vector<std::string>& partitions) {
     auto& dm = android::dm::DeviceMapper::Instance();
     auto dm_block_devices = dm.FindDmPartitions();
@@ -637,7 +642,6 @@
     return cow.FinishSnapshotWrites();
 }
 
-#ifdef SNAPSHOTCTL_USERDEBUG_OR_ENG
 bool CreateTestUpdate(SnapshotManager* sm) {
     chromeos_update_engine::DeltaArchiveManifest manifest;
 
@@ -761,13 +765,13 @@
         {"map", MapCmdHandler},
 #ifdef SNAPSHOTCTL_USERDEBUG_OR_ENG
         {"test-blank-ota", TestOtaHandler},
-#endif
-        {"unmap", UnmapCmdHandler},
         {"apply-update", ApplyUpdate},
         {"map-snapshots", MapPrecreatedSnapshots},
         {"unmap-snapshots", UnMapPrecreatedSnapshots},
         {"delete-snapshots", DeletePrecreatedSnapshots},
         {"revert-snapshots", RemovePrecreatedSnapshots},
+#endif
+        {"unmap", UnmapCmdHandler},
         // clang-format on
 };
 
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index f843821..00f8038 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -50,6 +50,7 @@
     std::cerr << "  create <dm-name> [-ro] <targets...>" << std::endl;
     std::cerr << "  delete <dm-name>" << std::endl;
     std::cerr << "  list <devices | targets> [-v]" << std::endl;
+    std::cerr << "  message <dm-name> <sector> <message>" << std::endl;
     std::cerr << "  getpath <dm-name>" << std::endl;
     std::cerr << "  getuuid <dm-name>" << std::endl;
     std::cerr << "  ima <dm-name>" << std::endl;
@@ -203,6 +204,46 @@
             return std::make_unique<DmTargetUser>(start_sector, num_sectors, control_device);
         } else if (target_type == "error") {
             return std::make_unique<DmTargetError>(start_sector, num_sectors);
+        } else if (target_type == "thin-pool") {
+            if (!HasArgs(4)) {
+                std::cerr << "Expected \"thin-pool\" <metadata dev> <data dev> <data block size> "
+                             "<low water mark> <feature args>"
+                          << std::endl;
+                return nullptr;
+            }
+
+            std::string metadata_dev = NextArg();
+            std::string data_dev = NextArg();
+            std::string data_block_size_str = NextArg();
+            std::string low_water_mark_str = NextArg();
+
+            uint64_t data_block_size;
+            if (!android::base::ParseUint(data_block_size_str, &data_block_size)) {
+                std::cerr << "Data block size must be an unsigned integer.\n";
+                return nullptr;
+            }
+            uint64_t low_water_mark;
+            if (!android::base::ParseUint(low_water_mark_str, &low_water_mark)) {
+                std::cerr << "Low water mark must be an unsigned integer.\n";
+                return nullptr;
+            }
+            return std::make_unique<DmTargetThinPool>(start_sector, num_sectors, metadata_dev,
+                                                      data_dev, data_block_size, low_water_mark);
+        } else if (target_type == "thin") {
+            if (!HasArgs(2)) {
+                std::cerr << "Expected \"thin\" <pool dev> <dev id>" << std::endl;
+                return nullptr;
+            }
+
+            std::string pool_dev = NextArg();
+            std::string dev_id_str = NextArg();
+
+            uint64_t dev_id;
+            if (!android::base::ParseUint(dev_id_str, &dev_id)) {
+                std::cerr << "Dev id must be an unsigned integer.\n";
+                return nullptr;
+            }
+            return std::make_unique<DmTargetThin>(start_sector, num_sectors, pool_dev, dev_id);
         } else {
             std::cerr << "Unrecognized target type: " << target_type << std::endl;
             return nullptr;
@@ -417,6 +458,24 @@
     return -EINVAL;
 }
 
+static int DmMessageCmdHandler(int argc, char** argv) {
+    if (argc != 3) {
+        std::cerr << "Usage: dmctl message <name> <sector> <message>" << std::endl;
+        return -EINVAL;
+    }
+    uint64_t sector;
+    if (!android::base::ParseUint(argv[1], &sector)) {
+        std::cerr << "Invalid argument for sector: " << argv[1] << std::endl;
+        return -EINVAL;
+    }
+    DeviceMapper& dm = DeviceMapper::Instance();
+    if (!dm.SendMessage(argv[0], sector, argv[2])) {
+        std::cerr << "Could not send message to " << argv[0] << std::endl;
+        return -EINVAL;
+    }
+    return 0;
+}
+
 static int HelpCmdHandler(int /* argc */, char** /* argv */) {
     Usage();
     return 0;
@@ -576,6 +635,7 @@
         {"delete", DmDeleteCmdHandler},
         {"replace", DmReplaceCmdHandler},
         {"list", DmListCmdHandler},
+        {"message", DmMessageCmdHandler},
         {"help", HelpCmdHandler},
         {"getpath", GetPathCmdHandler},
         {"getuuid", GetUuidCmdHandler},
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index 356aaa0..bfe636b 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -408,18 +408,6 @@
 
     LOG(INFO) << "init first stage started!";
 
-    // We only allow /vendor partition in debuggable Microdrod until it is verified during boot.
-    // TODO(b/285855436): remove this check.
-    if (IsMicrodroid()) {
-        bool mount_vendor =
-                cmdline.find("androidboot.microdroid.mount_vendor=1") != std::string::npos;
-        bool debuggable =
-                bootconfig.find("androidboot.microdroid.debuggable = \"1\"") != std::string::npos;
-        if (mount_vendor && !debuggable) {
-            LOG(FATAL) << "Attempted to mount /vendor partition for non-debuggable Microdroid VM";
-        }
-    }
-
     auto old_root_dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/"), closedir};
     if (!old_root_dir) {
         PLOG(ERROR) << "Could not opendir(\"/\"), not freeing ramdisk";
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 836d536..ae216c6 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -396,9 +396,10 @@
     use_snapuserd_ = sm->IsSnapuserdRequired();
     if (use_snapuserd_) {
         if (sm->UpdateUsesUserSnapshots()) {
-            LaunchFirstStageSnapuserd(SnapshotDriver::DM_USER);
+            LaunchFirstStageSnapuserd();
         } else {
-            LaunchFirstStageSnapuserd(SnapshotDriver::DM_SNAPSHOT);
+            LOG(FATAL) << "legacy virtual-ab is no longer supported";
+            return false;
         }
     }
 
diff --git a/init/snapuserd_transition.cpp b/init/snapuserd_transition.cpp
index dea7af9..9e3ff41 100644
--- a/init/snapuserd_transition.cpp
+++ b/init/snapuserd_transition.cpp
@@ -62,7 +62,7 @@
 static constexpr char kSnapuserdLabel[] = "u:object_r:snapuserd_exec:s0";
 static constexpr char kSnapuserdSocketLabel[] = "u:object_r:snapuserd_socket:s0";
 
-void LaunchFirstStageSnapuserd(SnapshotDriver driver) {
+void LaunchFirstStageSnapuserd() {
     SocketDescriptor socket_desc;
     socket_desc.name = android::snapshot::kSnapuserdSocket;
     socket_desc.type = SOCK_STREAM;
@@ -85,22 +85,13 @@
     if (pid == 0) {
         socket->Publish();
 
-        if (driver == SnapshotDriver::DM_USER) {
-            char arg0[] = "/system/bin/snapuserd";
-            char arg1[] = "-user_snapshot";
-            char* const argv[] = {arg0, arg1, nullptr};
-            if (execv(arg0, argv) < 0) {
-                PLOG(FATAL) << "Cannot launch snapuserd; execv failed";
-            }
-            _exit(127);
-        } else {
-            char arg0[] = "/system/bin/snapuserd";
-            char* const argv[] = {arg0, nullptr};
-            if (execv(arg0, argv) < 0) {
-                PLOG(FATAL) << "Cannot launch snapuserd; execv failed";
-            }
-            _exit(127);
+        char arg0[] = "/system/bin/snapuserd";
+        char arg1[] = "-user_snapshot";
+        char* const argv[] = {arg0, arg1, nullptr};
+        if (execv(arg0, argv) < 0) {
+            PLOG(FATAL) << "Cannot launch snapuserd; execv failed";
         }
+        _exit(127);
     }
 
     auto client = SnapuserdClient::Connect(android::snapshot::kSnapuserdSocket, 10s);
diff --git a/init/snapuserd_transition.h b/init/snapuserd_transition.h
index 557d105..e86e8da 100644
--- a/init/snapuserd_transition.h
+++ b/init/snapuserd_transition.h
@@ -29,13 +29,8 @@
 namespace android {
 namespace init {
 
-enum class SnapshotDriver {
-    DM_SNAPSHOT,
-    DM_USER,
-};
-
 // Fork and exec a new copy of snapuserd.
-void LaunchFirstStageSnapuserd(SnapshotDriver driver);
+void LaunchFirstStageSnapuserd();
 
 class SnapuserdSelinuxHelper final {
     using SnapshotManager = android::snapshot::SnapshotManager;
diff --git a/init/test_kill_services/Android.bp b/init/test_kill_services/Android.bp
index 37361a8..ada87d8 100644
--- a/init/test_kill_services/Android.bp
+++ b/init/test_kill_services/Android.bp
@@ -10,7 +10,10 @@
 cc_test {
     name: "init_kill_services_test",
     srcs: ["init_kill_services_test.cpp"],
-    shared_libs: ["libbase"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+    ],
     test_suites: ["general-tests"],
 
     // TODO(b/153565474): switch back to auto-generation
diff --git a/init/test_kill_services/init_kill_services_test.cpp b/init/test_kill_services/init_kill_services_test.cpp
index 510ad8a..3af92bb 100644
--- a/init/test_kill_services/init_kill_services_test.cpp
+++ b/init/test_kill_services/init_kill_services_test.cpp
@@ -18,15 +18,20 @@
 
 #include <android-base/logging.h>
 #include <android-base/properties.h>
+#include <hidl/ServiceManagement.h>
 
 #include <iostream>
 
 using ::android::base::GetProperty;
 using ::android::base::SetProperty;
 using ::android::base::WaitForProperty;
+using ::android::hardware::isHidlSupported;
 using std::literals::chrono_literals::operator""s;
 
 void ExpectKillingServiceRecovers(const std::string& service_name) {
+    if (!isHidlSupported() && service_name == "hwservicemanager") {
+        GTEST_SKIP() << "No HIDL support on device so hwservicemanager will not be running";
+    }
     LOG(INFO) << "before we say hi to " << service_name << ", I can't have apexd around!";
 
     // b/280514080 - servicemanager will restart apexd, and apexd will restart the
diff --git a/libcutils/abi-dumps/arm64/source-based/libcutils.so.lsdump b/libcutils/abi-dumps/arm64/source-based/libcutils.so.lsdump
index 333e61c..67c7514 100644
--- a/libcutils/abi-dumps/arm64/source-based/libcutils.so.lsdump
+++ b/libcutils/abi-dumps/arm64/source-based/libcutils.so.lsdump
@@ -290,6 +290,9 @@
    "name" : "fs_write_atomic_int"
   },
   {
+   "name" : "get_fs_config"
+  },
+  {
    "name" : "hashmapCreate"
   },
   {
@@ -1274,6 +1277,27 @@
    "source_file" : "system/core/libcutils/include/cutils/fs.h"
   },
   {
+   "function_name" : "get_fs_config",
+   "linker_set_key" : "get_fs_config",
+   "parameters" :
+   [
+    {
+     "referenced_type" : "_ZTIPKc"
+    },
+    {
+     "referenced_type" : "_ZTIb"
+    },
+    {
+     "referenced_type" : "_ZTIPKc"
+    },
+    {
+     "referenced_type" : "_ZTIP9fs_config"
+    }
+   ],
+   "return_type" : "_ZTIb",
+   "source_file" : "system/core/libcutils/include/private/fs_config.h"
+  },
+  {
    "function_name" : "hashmapCreate",
    "linker_set_key" : "hashmapCreate",
    "parameters" :
@@ -2392,6 +2416,15 @@
   },
   {
    "alignment" : 8,
+   "linker_set_key" : "_ZTIP9fs_config",
+   "name" : "fs_config *",
+   "referenced_type" : "_ZTI9fs_config",
+   "self_type" : "_ZTIP9fs_config",
+   "size" : 8,
+   "source_file" : "system/core/libcutils/include/private/fs_config.h"
+  },
+  {
+   "alignment" : 8,
    "linker_set_key" : "_ZTIP9str_parms",
    "name" : "str_parms *",
    "referenced_type" : "_ZTI9str_parms",
@@ -2684,6 +2717,37 @@
    "self_type" : "_ZTI5cnode",
    "size" : 40,
    "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+  },
+  {
+   "alignment" : 8,
+   "fields" :
+   [
+    {
+     "field_name" : "uid",
+     "referenced_type" : "_ZTIj"
+    },
+    {
+     "field_name" : "gid",
+     "field_offset" : 32,
+     "referenced_type" : "_ZTIj"
+    },
+    {
+     "field_name" : "mode",
+     "field_offset" : 64,
+     "referenced_type" : "_ZTIj"
+    },
+    {
+     "field_name" : "capabilities",
+     "field_offset" : 128,
+     "referenced_type" : "_ZTIm"
+    }
+   ],
+   "linker_set_key" : "_ZTI9fs_config",
+   "name" : "fs_config",
+   "referenced_type" : "_ZTI9fs_config",
+   "self_type" : "_ZTI9fs_config",
+   "size" : 24,
+   "source_file" : "system/core/libcutils/include/private/fs_config.h"
   }
  ],
  "rvalue_reference_types" : []
diff --git a/libcutils/abi-dumps/arm_arm64/source-based/libcutils.so.lsdump b/libcutils/abi-dumps/arm_arm64/source-based/libcutils.so.lsdump
index f612fb9..f75240c 100644
--- a/libcutils/abi-dumps/arm_arm64/source-based/libcutils.so.lsdump
+++ b/libcutils/abi-dumps/arm_arm64/source-based/libcutils.so.lsdump
@@ -300,6 +300,9 @@
    "name" : "fs_write_atomic_int"
   },
   {
+   "name" : "get_fs_config"
+  },
+  {
    "name" : "hashmapCreate"
   },
   {
@@ -1284,6 +1287,27 @@
    "source_file" : "system/core/libcutils/include/cutils/fs.h"
   },
   {
+   "function_name" : "get_fs_config",
+   "linker_set_key" : "get_fs_config",
+   "parameters" :
+   [
+    {
+     "referenced_type" : "_ZTIPKc"
+    },
+    {
+     "referenced_type" : "_ZTIb"
+    },
+    {
+     "referenced_type" : "_ZTIPKc"
+    },
+    {
+     "referenced_type" : "_ZTIP9fs_config"
+    }
+   ],
+   "return_type" : "_ZTIb",
+   "source_file" : "system/core/libcutils/include/private/fs_config.h"
+  },
+  {
    "function_name" : "hashmapCreate",
    "linker_set_key" : "hashmapCreate",
    "parameters" :
@@ -2402,6 +2426,15 @@
   },
   {
    "alignment" : 4,
+   "linker_set_key" : "_ZTIP9fs_config",
+   "name" : "fs_config *",
+   "referenced_type" : "_ZTI9fs_config",
+   "self_type" : "_ZTIP9fs_config",
+   "size" : 4,
+   "source_file" : "system/core/libcutils/include/private/fs_config.h"
+  },
+  {
+   "alignment" : 4,
    "linker_set_key" : "_ZTIP9str_parms",
    "name" : "str_parms *",
    "referenced_type" : "_ZTI9str_parms",
@@ -2694,6 +2727,37 @@
    "self_type" : "_ZTI5cnode",
    "size" : 20,
    "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+  },
+  {
+   "alignment" : 8,
+   "fields" :
+   [
+    {
+     "field_name" : "uid",
+     "referenced_type" : "_ZTIj"
+    },
+    {
+     "field_name" : "gid",
+     "field_offset" : 32,
+     "referenced_type" : "_ZTIj"
+    },
+    {
+     "field_name" : "mode",
+     "field_offset" : 64,
+     "referenced_type" : "_ZTIt"
+    },
+    {
+     "field_name" : "capabilities",
+     "field_offset" : 128,
+     "referenced_type" : "_ZTIy"
+    }
+   ],
+   "linker_set_key" : "_ZTI9fs_config",
+   "name" : "fs_config",
+   "referenced_type" : "_ZTI9fs_config",
+   "self_type" : "_ZTI9fs_config",
+   "size" : 24,
+   "source_file" : "system/core/libcutils/include/private/fs_config.h"
   }
  ],
  "rvalue_reference_types" : []
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index 919be2f..5efe209 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -91,7 +91,7 @@
     { 00751, AID_ROOT,         AID_SHELL,        0, "vendor/bin" },
     { 00751, AID_ROOT,         AID_SHELL,        0, "vendor/apex/*/bin" },
     { 00755, AID_ROOT,         AID_SHELL,        0, "vendor" },
-    { 00755, AID_ROOT,         AID_ROOT,         0, 0 },
+    {},
         // clang-format on
 };
 #ifndef __ANDROID_VNDK__
@@ -218,17 +218,32 @@
     { 00640, AID_ROOT,      AID_SHELL,     0, "fstab.*" },
     { 00750, AID_ROOT,      AID_SHELL,     0, "init*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "odm/bin/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "odm/framework/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "odm/app/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "odm/priv-app/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "product/bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "product/apex/*bin/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "product/framework/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "product/app/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "product/priv-app/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/xbin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/apex/*/bin/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "system/framework/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "system/app/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "system/priv-app/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system_ext/bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system_ext/apex/*/bin/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "system_ext/framework/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "system_ext/app/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "system_ext/priv-app/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/apex/*bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/xbin/*" },
-    { 00644, AID_ROOT,      AID_ROOT,      0, 0 },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "vendor/framework/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "vendor/app/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "vendor/priv-app/*" },
+    {},
         // clang-format on
 };
 #ifndef __ANDROID_VNDK__
@@ -318,8 +333,8 @@
 auto __for_testing_only__fs_config_cmp = fs_config_cmp;
 #endif
 
-void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid,
-               unsigned* mode, uint64_t* capabilities) {
+bool get_fs_config(const char* path, bool dir, const char* target_out_path,
+                   struct fs_config* fs_conf) {
     const struct fs_path_config* pc;
     size_t which, plen;
 
@@ -362,11 +377,11 @@
             if (fs_config_cmp(dir, prefix, len, path, plen)) {
                 free(prefix);
                 close(fd);
-                *uid = header.uid;
-                *gid = header.gid;
-                *mode = (*mode & (~07777)) | header.mode;
-                *capabilities = header.capabilities;
-                return;
+                fs_conf->uid = header.uid;
+                fs_conf->gid = header.gid;
+                fs_conf->mode = header.mode;
+                fs_conf->capabilities = header.capabilities;
+                return true;
             }
             free(prefix);
         }
@@ -375,11 +390,28 @@
 
     for (pc = dir ? android_dirs : android_files; pc->prefix; pc++) {
         if (fs_config_cmp(dir, pc->prefix, strlen(pc->prefix), path, plen)) {
-            break;
+            fs_conf->uid = pc->uid;
+            fs_conf->gid = pc->gid;
+            fs_conf->mode = pc->mode;
+            fs_conf->capabilities = pc->capabilities;
+            return true;
         }
     }
-    *uid = pc->uid;
-    *gid = pc->gid;
-    *mode = (*mode & (~07777)) | pc->mode;
-    *capabilities = pc->capabilities;
+    return false;
+}
+
+void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid,
+               unsigned* mode, uint64_t* capabilities) {
+    struct fs_config conf;
+    if (get_fs_config(path, dir, target_out_path, &conf)) {
+        *uid = conf.uid;
+        *gid = conf.gid;
+        *mode = (*mode & S_IFMT) | conf.mode;
+        *capabilities = conf.capabilities;
+    } else {
+        *uid = AID_ROOT;
+        *gid = AID_ROOT;
+        *mode = (*mode & S_IFMT) | (dir ? 0755 : 0644);
+        *capabilities = 0;
+    }
 }
diff --git a/libcutils/include/private/fs_config.h b/libcutils/include/private/fs_config.h
index 45f46e5..9a727bc 100644
--- a/libcutils/include/private/fs_config.h
+++ b/libcutils/include/private/fs_config.h
@@ -21,8 +21,11 @@
 
 #pragma once
 
+#include <fcntl.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <sys/cdefs.h>
+#include <unistd.h>
 
 #include <linux/capability.h>
 
@@ -30,17 +33,27 @@
 
 __BEGIN_DECLS
 
-/*
- * Used in:
- *  build/tools/fs_config/fs_config.c
- *  build/tools/fs_get_stats/fs_get_stats.c
- *  system/extras/ext4_utils/make_ext4fs_main.c
- *  external/squashfs-tools/squashfs-tools/android.c
- *  system/core/cpio/mkbootfs.c
- *  system/core/adb/file_sync_service.cpp
- *  system/extras/ext4_utils/canned_fs_config.c
- */
+/* This API is deprecated. New users should call get_fs_config. */
 void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid,
                unsigned* mode, uint64_t* capabilities);
 
+struct fs_config {
+  uid_t uid;
+  gid_t gid;
+  mode_t mode;
+  uint64_t capabilities;
+};
+
+/*
+ * If a file system configuration was found for the specified path, store it to *conf.
+ * Returns whether a file system configuration was found.
+ *
+ * dir: Whether path refers to a directory.
+ * target_out_path: Path to the base directory to read the file system configuration from, or a null
+ * pointer to use the root directory as the base. Host code should pass $ANDROID_PRODUCT_OUT or
+ * equivalent, and device code should pass a null pointer.
+ */
+bool get_fs_config(const char* path, bool dir, const char* target_out_path,
+                   struct fs_config* conf);
+
 __END_DECLS
diff --git a/libutils/CallStack.cpp b/libutils/CallStack.cpp
index fe827eb..029f4a7 100644
--- a/libutils/CallStack.cpp
+++ b/libutils/CallStack.cpp
@@ -89,7 +89,8 @@
 // The following four functions may be used via weak symbol references from libutils.
 // Clients assume that if any of these symbols are available, then deleteStack() is.
 
-#ifdef WEAKS_AVAILABLE
+// Apple and Windows does not support this, so only compile on other platforms.
+#if !defined(__APPLE__) && !defined(_WIN32)
 
 CallStack::CallStackUPtr CallStack::getCurrentInternal(int ignoreDepth) {
     CallStack::CallStackUPtr stack(new CallStack());
@@ -110,6 +111,6 @@
     delete stack;
 }
 
-#endif // WEAKS_AVAILABLE
+#endif  // !defined(__APPLE__) && !defined(_WIN32)
 
 }; // namespace android
diff --git a/libutils/CallStack_test.cpp b/libutils/CallStack_test.cpp
index 2cfaf61..7afc2c3 100644
--- a/libutils/CallStack_test.cpp
+++ b/libutils/CallStack_test.cpp
@@ -18,10 +18,16 @@
 
 #include <thread>
 
+#include <android-base/test_utils.h>
 #include <android-base/threads.h>
 #include <gtest/gtest.h>
 #include <utils/CallStack.h>
 
+#if defined(__ANDROID__)
+#include <log/log.h>
+#include <log/log_read.h>
+#endif
+
 __attribute__((__noinline__)) extern "C" void CurrentCaller(android::String8& backtrace) {
     android::CallStack cs;
     cs.update();
@@ -61,3 +67,38 @@
 
     ASSERT_NE(-1, cs.toString().find("(ThreadBusyWait")) << "Full backtrace:\n" << cs.toString();
 }
+
+#if defined(__ANDROID__)
+TEST(CallStackTest, log_stack) {
+    android::CallStack::logStack("callstack_test");
+    auto logger_list = android_logger_list_open(android_name_to_log_id("main"),
+                                                ANDROID_LOG_NONBLOCK, 1000, getpid());
+    ASSERT_NE(nullptr, logger_list);
+    std::string log;
+    while (true) {
+        log_msg log_msg;
+        auto ret = android_logger_list_read(logger_list, &log_msg);
+        if (ret == -EAGAIN) {
+            break;
+        }
+        ASSERT_GT(ret, 0);
+        if (log_msg.msg() == nullptr) {
+            continue;
+        }
+        // First get the tag.
+        char* msg = &log_msg.msg()[1];
+        if (std::string(msg) != "callstack_test") {
+            continue;
+        }
+        // Now move past the tag.
+        msg = &msg[strlen(msg) + 1];
+        log += msg;
+        log += '\n';
+    }
+    ASSERT_NE("", log) << "No messages found in the log from the test.";
+    // Look for a backtrace line such as:
+    //   #00 pc 00000000000536e4  libutils_test (testing::Test::Run()+436)
+    ASSERT_MATCH(log, "#\\d+ pc \\d+");
+    android_logger_list_close(logger_list);
+}
+#endif
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 7444f96..593bb1e 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -223,13 +223,6 @@
 	$(hide) sed -i -e 's?%EXPORT_GLOBAL_HWASAN_OPTIONS%?$(EXPORT_GLOBAL_HWASAN_OPTIONS)?g' $@
 	$(hide) sed -i -e 's?%EXPORT_GLOBAL_SCUDO_ALLOCATION_RING_BUFFER_SIZE%?$(EXPORT_GLOBAL_SCUDO_ALLOCATION_RING_BUFFER_SIZE)?g' $@
 
-# Append PLATFORM_VNDK_VERSION to base name.
-define append_vndk_version
-$(strip \
-  $(basename $(1)).$(PLATFORM_VNDK_VERSION)$(suffix $(1)) \
-)
-endef
-
 #######################################
 # sanitizer.libraries.txt
 include $(CLEAR_VARS)
diff --git a/rootdir/etc/linker.config.json b/rootdir/etc/linker.config.json
index d72ac66..8b3542f 100644
--- a/rootdir/etc/linker.config.json
+++ b/rootdir/etc/linker.config.json
@@ -9,8 +9,6 @@
     "libnativehelper.so",
     "libnativeloader.so",
     "libsigchain.so",
-    // TODO(b/122876336): Remove libpac.so once it's migrated to Webview
-    "libpac.so",
     // TODO(b/120786417 or b/134659294): libicuuc.so
     // and libicui18n.so are kept for app compat.
     "libicui18n.so",
@@ -32,6 +30,8 @@
   ],
   "provideLibs": [
     "libaptX_encoder.so",
-    "libaptXHD_encoder.so"
+    "libaptXHD_encoder.so",
+    "libEGL.so",
+    "libGLESv2.so"
   ]
 }
diff --git a/toolbox/OWNERS b/toolbox/OWNERS
index 5e2c581..898ddce 100644
--- a/toolbox/OWNERS
+++ b/toolbox/OWNERS
@@ -1,2 +1,3 @@
 include platform/system/core:/janitors/OWNERS
 per-file modprobe.c=willmcvicker@google.com,dvander@google.com
+per-file getevent.c=file:platform/frameworks/base:/INPUT_OWNERS
diff --git a/toolbox/getevent.c b/toolbox/getevent.c
index f65bb20..7b896e9 100644
--- a/toolbox/getevent.c
+++ b/toolbox/getevent.c
@@ -441,7 +441,7 @@
     if(res < (int)sizeof(*event)) {
         if(errno == EINTR)
             return 0;
-        fprintf(stderr, "could not get event, %s\n", strerror(errno));
+        fprintf(stderr, "could not get inotify events, %s\n", strerror(errno));
         return 1;
     }
     //printf("got %d bytes of event information\n", res);
@@ -664,7 +664,7 @@
                 if(ufds[i].revents & POLLIN) {
                     res = read(ufds[i].fd, &event, sizeof(event));
                     if(res < (int)sizeof(event)) {
-                        fprintf(stderr, "could not get event\n");
+                        fprintf(stderr, "could not get evdev event, %s\n", strerror(errno));
                         return 1;
                     }
                     if(get_time) {
diff --git a/trusty/keymint/src/keymint_hal_main.rs b/trusty/keymint/src/keymint_hal_main.rs
index eda986a..ef0c598 100644
--- a/trusty/keymint/src/keymint_hal_main.rs
+++ b/trusty/keymint/src/keymint_hal_main.rs
@@ -82,7 +82,7 @@
 }
 
 fn main() {
-    if let Err(e) = inner_main() {
+    if let Err(HalServiceError(e)) = inner_main() {
         panic!("HAL service failed: {:?}", e);
     }
 }
diff --git a/trusty/secretkeeper/src/hal_main.rs b/trusty/secretkeeper/src/hal_main.rs
index df30493..b31db13 100644
--- a/trusty/secretkeeper/src/hal_main.rs
+++ b/trusty/secretkeeper/src/hal_main.rs
@@ -91,7 +91,7 @@
 }
 
 fn main() {
-    if let Err(e) = inner_main() {
+    if let Err(HalServiceError(e)) = inner_main() {
         panic!("HAL service failed: {:?}", e);
     }
 }