Merge "linker.config.json: remove libpac.so." into main
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/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/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/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);
     }
 }