libfiemap: Add some dependency injection.
libsnapshot supports dependency injection for whether or not we use
recovery-specific code paths. Extend this to libfiemap.
Bug: 179006671
Test: vts_libsnapshot_test
Change-Id: Ief5a16d105cb51bc2593ebc2317a99c939371775
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 50f4f33..cfa43a5 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/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index cc2599d..948c382 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -2551,7 +2551,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;