summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Anderson <dvander@google.com>2019-08-01 12:53:06 -0700
committerDavid Anderson <dvander@google.com>2019-08-01 18:00:43 -0700
commit551ae3aa39dbe5fcf124db4324e33242b5f7002c (patch)
tree9fdd9959a7f974ab62ab8364e113dfb2df974b96
parentb00d15e8cb62163b052678214d718ab660e4aaf6 (diff)
downloadgsid-551ae3aa39dbe5fcf124db4324e33242b5f7002c.tar.gz
Add a library to wrap libfiemap differences between recovery and normal AOSP.
libsnapshot has to work both in normal boot and in recovery. Normally, we want libfiemap to be used through gsid, via binder, to consolidate the necessary SELinux permissions. However binder is not available in recovery, so instead we introduce a compile-time abstraction layer. Recovery should link to libfiemap; otherwise, libfiemap_binder should be used instead. They both present the same API. Bug: 134536978 Test: manual test Change-Id: I60370af2175723141e61f0ee301cad40d2f331c1
-rw-r--r--Android.bp2
-rw-r--r--aidl/android/gsi/IGsiService.aidl6
-rw-r--r--aidl/android/gsi/IImageService.aidl (renamed from aidl/android/gsi/IImageManager.aidl)2
-rw-r--r--gsi_service.cpp29
-rw-r--r--gsi_service.h6
-rw-r--r--libfiemap/Android.bp17
-rw-r--r--libfiemap/binder.cpp164
-rw-r--r--libfiemap/image_manager.cpp20
-rw-r--r--libfiemap/include/libfiemap/image_manager.h61
9 files changed, 264 insertions, 43 deletions
diff --git a/Android.bp b/Android.bp
index 36631b0..da02c78 100644
--- a/Android.bp
+++ b/Android.bp
@@ -99,7 +99,7 @@ filegroup {
srcs: [
"aidl/android/gsi/GsiInstallParams.aidl",
"aidl/android/gsi/GsiProgress.aidl",
- "aidl/android/gsi/IImageManager.aidl",
+ "aidl/android/gsi/IImageService.aidl",
"aidl/android/gsi/IGsid.aidl",
"aidl/android/gsi/IGsiService.aidl",
"aidl/android/gsi/MappedImage.aidl",
diff --git a/aidl/android/gsi/IGsiService.aidl b/aidl/android/gsi/IGsiService.aidl
index 4468eb7..6ca0af5 100644
--- a/aidl/android/gsi/IGsiService.aidl
+++ b/aidl/android/gsi/IGsiService.aidl
@@ -18,7 +18,7 @@ package android.gsi;
import android.gsi.GsiInstallParams;
import android.gsi.GsiProgress;
-import android.gsi.IImageManager;
+import android.gsi.IImageService;
import android.os.ParcelFileDescriptor;
/** {@hide} */
@@ -184,11 +184,11 @@ interface IGsiService {
int wipeGsiUserdata();
/**
- * Open a handle to an IImageManager for the given metadata and data storage paths.
+ * Open a handle to an IImageService for the given metadata and data storage paths.
*
* @param prefix A prefix used to organize images. The data path will become
* /data/gsi/{prefix} and the metadata path will become
* /metadata/gsi/{prefix}.
*/
- IImageManager openImageManager(@utf8InCpp String prefix);
+ IImageService openImageService(@utf8InCpp String prefix);
}
diff --git a/aidl/android/gsi/IImageManager.aidl b/aidl/android/gsi/IImageService.aidl
index 11bae33..62c2636 100644
--- a/aidl/android/gsi/IImageManager.aidl
+++ b/aidl/android/gsi/IImageService.aidl
@@ -19,7 +19,7 @@ package android.gsi;
import android.gsi.MappedImage;
/** {@hide} */
-interface IImageManager {
+interface IImageService {
/* These flags match fiemap::ImageManager::CreateBackingImage. */
const int CREATE_IMAGE_DEFAULT = 0x0;
const int CREATE_IMAGE_READONLY = 0x1;
diff --git a/gsi_service.cpp b/gsi_service.cpp
index a208c5e..352b2c2 100644
--- a/gsi_service.cpp
+++ b/gsi_service.cpp
@@ -32,7 +32,7 @@
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
-#include <android/gsi/BnImageManager.h>
+#include <android/gsi/BnImageService.h>
#include <android/gsi/IGsiService.h>
#include <ext4_utils/ext4_utils.h>
#include <fs_mgr.h>
@@ -396,9 +396,9 @@ static binder::Status UidSecurityError() {
return binder::Status::fromExceptionCode(binder::Status::EX_SECURITY, String8(message.c_str()));
}
-class ImageManagerService : public BinderService<ImageManagerService>, public BnImageManager {
+class ImageService : public BinderService<ImageService>, public BnImageService {
public:
- ImageManagerService(GsiService* service, std::unique_ptr<ImageManager>&& impl, uid_t uid);
+ ImageService(GsiService* service, std::unique_ptr<ImageManager>&& impl, uid_t uid);
binder::Status createBackingImage(const std::string& name, int64_t size, int flags) override;
binder::Status deleteBackingImage(const std::string& name) override;
binder::Status mapImageDevice(const std::string& name, int32_t timeout_ms,
@@ -415,12 +415,10 @@ class ImageManagerService : public BinderService<ImageManagerService>, public Bn
uid_t uid_;
};
-ImageManagerService::ImageManagerService(GsiService* service, std::unique_ptr<ImageManager>&& impl,
- uid_t uid)
+ImageService::ImageService(GsiService* service, std::unique_ptr<ImageManager>&& impl, uid_t uid)
: service_(service), parent_(service->parent()), impl_(std::move(impl)), uid_(uid) {}
-binder::Status ImageManagerService::createBackingImage(const std::string& name, int64_t size,
- int flags) {
+binder::Status ImageService::createBackingImage(const std::string& name, int64_t size, int flags) {
if (!CheckUid()) return UidSecurityError();
std::lock_guard<std::mutex> guard(parent_->lock());
@@ -431,7 +429,7 @@ binder::Status ImageManagerService::createBackingImage(const std::string& name,
return binder::Status::ok();
}
-binder::Status ImageManagerService::deleteBackingImage(const std::string& name) {
+binder::Status ImageService::deleteBackingImage(const std::string& name) {
if (!CheckUid()) return UidSecurityError();
std::lock_guard<std::mutex> guard(parent_->lock());
@@ -442,8 +440,8 @@ binder::Status ImageManagerService::deleteBackingImage(const std::string& name)
return binder::Status::ok();
}
-binder::Status ImageManagerService::mapImageDevice(const std::string& name, int32_t timeout_ms,
- MappedImage* mapping) {
+binder::Status ImageService::mapImageDevice(const std::string& name, int32_t timeout_ms,
+ MappedImage* mapping) {
if (!CheckUid()) return UidSecurityError();
std::lock_guard<std::mutex> guard(parent_->lock());
@@ -454,7 +452,7 @@ binder::Status ImageManagerService::mapImageDevice(const std::string& name, int3
return binder::Status::ok();
}
-binder::Status ImageManagerService::unmapImageDevice(const std::string& name) {
+binder::Status ImageService::unmapImageDevice(const std::string& name) {
if (!CheckUid()) return UidSecurityError();
std::lock_guard<std::mutex> guard(parent_->lock());
@@ -465,8 +463,7 @@ binder::Status ImageManagerService::unmapImageDevice(const std::string& name) {
return binder::Status::ok();
}
-binder::Status ImageManagerService::backingImageExists(const std::string& name,
- bool* _aidl_return) {
+binder::Status ImageService::backingImageExists(const std::string& name, bool* _aidl_return) {
if (!CheckUid()) return UidSecurityError();
std::lock_guard<std::mutex> guard(parent_->lock());
@@ -479,8 +476,8 @@ bool ImageManagerService::CheckUid() {
return uid_ == IPCThreadState::self()->getCallingUid();
}
-binder::Status GsiService::openImageManager(const std::string& prefix,
- android::sp<IImageManager>* _aidl_return) {
+binder::Status GsiService::openImageService(const std::string& prefix,
+ android::sp<IImageService>* _aidl_return) {
static constexpr char kImageMetadataPrefix[] = "/metadata/gsi/";
static constexpr char kImageDataPrefix[] = "/data/gsi/";
@@ -511,7 +508,7 @@ binder::Status GsiService::openImageManager(const std::string& prefix,
return BinderError("Unknown error");
}
- *_aidl_return = new ImageManagerService(this, std::move(impl), uid);
+ *_aidl_return = new ImageService(this, std::move(impl), uid);
return binder::Status::ok();
}
diff --git a/gsi_service.h b/gsi_service.h
index 6d72921..30ec2d7 100644
--- a/gsi_service.h
+++ b/gsi_service.h
@@ -44,7 +44,7 @@ class Gsid : public BinderService<Gsid>, public BnGsid {
private:
friend class GsiService;
- friend class ImageManagerService;
+ friend class ImageService;
std::mutex& lock() { return lock_; }
@@ -77,8 +77,8 @@ class GsiService : public BinderService<GsiService>, public BnGsiService {
binder::Status getGsiBootStatus(int* _aidl_return) override;
binder::Status getInstalledGsiImageDir(std::string* _aidl_return) override;
binder::Status wipeGsiUserdata(int* _aidl_return) override;
- binder::Status openImageManager(const std::string& prefix,
- android::sp<IImageManager>* _aidl_return) override;
+ binder::Status openImageService(const std::string& prefix,
+ android::sp<IImageService>* _aidl_return) override;
// This is in GsiService, rather than GsiInstaller, since we need to access
// it outside of the main lock which protects the unique_ptr.
diff --git a/libfiemap/Android.bp b/libfiemap/Android.bp
index 0cbd464..9ae80e4 100644
--- a/libfiemap/Android.bp
+++ b/libfiemap/Android.bp
@@ -47,6 +47,23 @@ cc_library_static {
],
}
+cc_library_static {
+ name: "libfiemap_binder",
+ srcs: [
+ "binder.cpp",
+ ],
+ static_libs: [
+ "gsi_aidl_interface-cpp",
+ "libfiemap",
+ "libgsi",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ ],
+ export_include_dirs: ["include"],
+}
+
cc_test {
name: "fiemap_writer_test",
cflags: [
diff --git a/libfiemap/binder.cpp b/libfiemap/binder.cpp
new file mode 100644
index 0000000..dde2e22
--- /dev/null
+++ b/libfiemap/binder.cpp
@@ -0,0 +1,164 @@
+//
+// Copyright (C) 2019 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.
+//
+
+#if !defined(__ANDROID_RECOVERY__)
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/gsi/IGsiService.h>
+#include <android/gsi/IGsid.h>
+#include <binder/IServiceManager.h>
+#include <libfiemap/image_manager.h>
+#include <libgsi/libgsi.h>
+
+namespace android {
+namespace fiemap {
+
+using namespace android::gsi;
+using namespace std::chrono_literals;
+
+class ImageManagerBinder final : public IImageManager {
+ public:
+ ImageManagerBinder(android::sp<IGsiService>&& service, android::sp<IImageService>&& manager);
+ bool CreateBackingImage(const std::string& name, uint64_t size, int flags) override;
+ bool DeleteBackingImage(const std::string& name) override;
+ bool MapImageDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms,
+ std::string* path) override;
+ bool UnmapImageDevice(const std::string& name) override;
+ bool BackingImageExists(const std::string& name) override;
+
+ private:
+ android::sp<IGsiService> service_;
+ android::sp<IImageService> manager_;
+};
+
+ImageManagerBinder::ImageManagerBinder(android::sp<IGsiService>&& service,
+ android::sp<IImageService>&& manager)
+ : service_(std::move(service)), manager_(std::move(manager)) {}
+
+bool ImageManagerBinder::CreateBackingImage(const std::string& name, uint64_t size, int flags) {
+ auto status = manager_->createBackingImage(name, size, flags);
+ if (!status.isOk()) {
+ LOG(ERROR) << __PRETTY_FUNCTION__
+ << " binder returned: " << status.exceptionMessage().string();
+ return false;
+ }
+ return true;
+}
+
+bool ImageManagerBinder::DeleteBackingImage(const std::string& name) {
+ auto status = manager_->deleteBackingImage(name);
+ if (!status.isOk()) {
+ LOG(ERROR) << __PRETTY_FUNCTION__
+ << " binder returned: " << status.exceptionMessage().string();
+ return false;
+ }
+ return true;
+}
+
+bool ImageManagerBinder::MapImageDevice(const std::string& name,
+ const std::chrono::milliseconds& timeout_ms,
+ std::string* path) {
+ MappedImage map;
+ auto status = manager_->mapImageDevice(name, timeout_ms.count(), &map);
+ if (!status.isOk()) {
+ LOG(ERROR) << __PRETTY_FUNCTION__
+ << " binder returned: " << status.exceptionMessage().string();
+ return false;
+ }
+ *path = map.path;
+ return true;
+}
+
+bool ImageManagerBinder::UnmapImageDevice(const std::string& name) {
+ auto status = manager_->unmapImageDevice(name);
+ if (!status.isOk()) {
+ LOG(ERROR) << __PRETTY_FUNCTION__
+ << " binder returned: " << status.exceptionMessage().string();
+ return false;
+ }
+ return true;
+}
+
+bool ImageManagerBinder::BackingImageExists(const std::string& name) {
+ bool retval;
+ auto status = manager_->backingImageExists(name, &retval);
+ if (!status.isOk()) {
+ LOG(ERROR) << __PRETTY_FUNCTION__
+ << " binder returned: " << status.exceptionMessage().string();
+ return false;
+ }
+ return retval;
+}
+
+static android::sp<IGsid> AcquireIGsid(const std::chrono::milliseconds& timeout_ms) {
+ if (android::base::GetProperty("init.svc.gsid", "") != "running") {
+ if (!android::base::SetProperty("ctl.start", "gsid") ||
+ !android::base::WaitForProperty("init.svc.gsid", "running", timeout_ms)) {
+ LOG(ERROR) << "Could not start the gsid service";
+ return nullptr;
+ }
+ // Sleep for 250ms to give the service time to register.
+ usleep(250 * 1000);
+ }
+ auto sm = android::defaultServiceManager();
+ auto name = android::String16(kGsiServiceName);
+ auto service = sm->checkService(name);
+ return android::interface_cast<IGsid>(service);
+}
+
+static android::sp<IGsid> GetGsiService(const std::chrono::milliseconds& timeout_ms) {
+ auto start_time = std::chrono::steady_clock::now();
+
+ std::chrono::milliseconds elapsed = std::chrono::milliseconds::zero();
+ do {
+ if (auto gsid = AcquireIGsid(timeout_ms - elapsed); gsid != nullptr) {
+ return gsid;
+ }
+ auto now = std::chrono::steady_clock::now();
+ elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
+ } while (elapsed <= timeout_ms);
+
+ LOG(ERROR) << "Timed out trying to acquire IGsid interface";
+ return nullptr;
+}
+
+std::unique_ptr<IImageManager> IImageManager::Open(const std::string& dir,
+ const std::chrono::milliseconds& timeout_ms) {
+ auto gsid = GetGsiService(timeout_ms);
+ if (!gsid) {
+ return nullptr;
+ }
+
+ android::sp<IGsiService> service;
+ auto status = gsid->getClient(&service);
+ if (!status.isOk() || !service) {
+ LOG(ERROR) << "Could not acquire IGsiService";
+ return nullptr;
+ }
+
+ android::sp<IImageService> manager;
+ status = service->openImageService(dir, &manager);
+ if (!status.isOk() || !manager) {
+ LOG(ERROR) << "Could not acquire IImageManager: " << status.exceptionMessage().string();
+ return nullptr;
+ }
+ return std::make_unique<ImageManagerBinder>(std::move(service), std::move(manager));
+}
+
+} // namespace fiemap
+} // namespace android
+
+#endif // __ANDROID_RECOVERY__
diff --git a/libfiemap/image_manager.cpp b/libfiemap/image_manager.cpp
index baf1509..e389905 100644
--- a/libfiemap/image_manager.cpp
+++ b/libfiemap/image_manager.cpp
@@ -46,6 +46,18 @@ using android::fs_mgr::GetPartitionName;
static constexpr char kTestImageMetadataDir[] = "/metadata/gsi/test";
+std::unique_ptr<IImageManager> __attribute__((weak))
+IImageManager::Open(const std::string& dir_prefix, const std::chrono::milliseconds& timeout_ms) {
+ (void)timeout_ms;
+ return ImageManager::Open(dir_prefix);
+}
+
+std::unique_ptr<ImageManager> ImageManager::Open(const std::string& dir_prefix) {
+ auto metadata_dir = "/metadata/gsi/" + dir_prefix;
+ auto data_dir = "/data/gsi/" + dir_prefix;
+ return Open(metadata_dir, data_dir);
+}
+
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));
@@ -103,6 +115,10 @@ bool ImageManager::BackingImageExists(const std::string& name) {
return access(header_file.c_str(), F_OK) == 0;
}
+bool ImageManager::CreateBackingImage(const std::string& name, uint64_t size, int flags) {
+ return CreateBackingImage(name, size, flags, nullptr);
+}
+
bool ImageManager::CreateBackingImage(const std::string& name, uint64_t size, int flags,
std::function<bool(uint64_t, uint64_t)>&& on_progress) {
auto data_path = GetImageHeaderPath(name);
@@ -551,7 +567,7 @@ bool ImageManager::Validate() {
return true;
}
-std::unique_ptr<MappedDevice> MappedDevice::Open(ImageManager* manager,
+std::unique_ptr<MappedDevice> MappedDevice::Open(IImageManager* manager,
const std::chrono::milliseconds& timeout_ms,
const std::string& name) {
std::string path;
@@ -566,7 +582,7 @@ std::unique_ptr<MappedDevice> MappedDevice::Open(ImageManager* manager,
return device;
}
-MappedDevice::MappedDevice(ImageManager* manager, const std::string& name, const std::string& path)
+MappedDevice::MappedDevice(IImageManager* manager, const std::string& name, const std::string& path)
: manager_(manager), name_(name), path_(path) {
// The device is already mapped; try and open it.
fd_.reset(open(path.c_str(), O_RDWR | O_CLOEXEC));
diff --git a/libfiemap/include/libfiemap/image_manager.h b/libfiemap/include/libfiemap/image_manager.h
index 2be2c8b..b1a4317 100644
--- a/libfiemap/include/libfiemap/image_manager.h
+++ b/libfiemap/include/libfiemap/image_manager.h
@@ -28,13 +28,17 @@
namespace android {
namespace fiemap {
-class ImageManager final {
+class IImageManager {
public:
- // 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);
+ virtual ~IImageManager() {}
+ // When linking to libfiemap_binder, the Open() call will use binder.
+ // Otherwise, the Open() call will use the ImageManager implementation
+ // below.
+ static std::unique_ptr<IImageManager> Open(const std::string& dir_prefix,
+ const std::chrono::milliseconds& timeout_ms);
+
+ // Flags for CreateBackingImage().
static constexpr int CREATE_IMAGE_DEFAULT = 0x0;
static constexpr int CREATE_IMAGE_READONLY = 0x1;
static constexpr int CREATE_IMAGE_ZERO_FILL = 0x2;
@@ -44,12 +48,11 @@ class ImageManager final {
// of the image is undefined. If zero-fill is requested, and the operation
// cannot be completed, the image will be deleted and this function will
// return false.
- bool CreateBackingImage(const std::string& name, uint64_t size, int flags,
- std::function<bool(uint64_t, uint64_t)>&& on_progress);
+ virtual bool CreateBackingImage(const std::string& name, uint64_t size, int flags) = 0;
// Delete an image created with CreateBackingImage. Its entry will be
// removed from the associated lp_metadata file.
- bool DeleteBackingImage(const std::string& name);
+ virtual bool DeleteBackingImage(const std::string& name) = 0;
// Create a block device for an image previously created with
// CreateBackingImage. This will wait for at most |timeout_ms| milliseconds
@@ -60,11 +63,38 @@ class ImageManager final {
// Note that snapshots created with a readonly flag are always mapped
// writable. The flag is persisted in the lp_metadata file however, so if
// fs_mgr::CreateLogicalPartition(s) is used, the flag will be respected.
- bool MapImageDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms,
- std::string* path);
+ virtual bool MapImageDevice(const std::string& name,
+ const std::chrono::milliseconds& timeout_ms, std::string* path) = 0;
// Unmap a block device previously mapped with mapBackingImage.
- bool UnmapImageDevice(const std::string& name);
+ virtual bool UnmapImageDevice(const std::string& name) = 0;
+
+ // Returns true whether the named backing image exists.
+ virtual bool BackingImageExists(const std::string& name) = 0;
+};
+
+class ImageManager final : public IImageManager {
+ public:
+ // 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);
+
+ // Helper function that derives the metadata and data dirs given a single
+ // prefix.
+ static std::unique_ptr<ImageManager> Open(const std::string& dir_prefix);
+
+ // Methods that must be implemented from IImageManager.
+ bool CreateBackingImage(const std::string& name, uint64_t size, int flags) override;
+ bool DeleteBackingImage(const std::string& name) override;
+ bool MapImageDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms,
+ std::string* path) override;
+ bool UnmapImageDevice(const std::string& name) override;
+ bool BackingImageExists(const std::string& name) override;
+
+ // Same as CreateBackingImage, but provides a progress notification.
+ bool CreateBackingImage(const std::string& name, uint64_t size, int flags,
+ std::function<bool(uint64_t, uint64_t)>&& on_progress);
// Returns true if the specified image is mapped to a device.
bool IsImageMapped(const std::string& name);
@@ -72,9 +102,6 @@ class ImageManager final {
// Find and remove all images and metadata for a given image dir.
bool RemoveAllImages();
- // Returns true whether the named backing image exists.
- bool BackingImageExists(const std::string& name);
-
// Returns true if the named partition exists. This does not check the
// consistency of the backing image/data file.
bool PartitionExists(const std::string& name);
@@ -108,7 +135,7 @@ class ImageManager final {
// RAII helper class for mapping and opening devices with an ImageManager.
class MappedDevice final {
public:
- static std::unique_ptr<MappedDevice> Open(ImageManager* manager,
+ static std::unique_ptr<MappedDevice> Open(IImageManager* manager,
const std::chrono::milliseconds& timeout_ms,
const std::string& name);
@@ -118,9 +145,9 @@ class MappedDevice final {
const std::string& path() const { return path_; }
protected:
- MappedDevice(ImageManager* manager, const std::string& name, const std::string& path);
+ MappedDevice(IImageManager* manager, const std::string& name, const std::string& path);
- ImageManager* manager_;
+ IImageManager* manager_;
std::string name_;
std::string path_;
android::base::unique_fd fd_;