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
diff --git a/Android.bp b/Android.bp
index 36631b0..da02c78 100644
--- a/Android.bp
+++ b/Android.bp
@@ -99,7 +99,7 @@
     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 @@
 
 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 @@
     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
similarity index 98%
rename from aidl/android/gsi/IImageManager.aidl
rename to 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 @@
 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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
         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 @@
 
   private:
     friend class GsiService;
-    friend class ImageManagerService;
+    friend class ImageService;
 
     std::mutex& lock() { return lock_; }
 
@@ -77,8 +77,8 @@
     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 {
+    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 @@
 
 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 @@
     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 @@
     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 @@
     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 @@
     // 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 @@
     // 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 @@
     // 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 @@
 // 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 @@
     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_;