recovery: Implement a volume manager

This is a copy of the pre-binderized vold which has been converted to
use direct calls instead of sockets and stripped down to only what is
needed to support recovery.

Includes:
  * recovery: volmgr: remove unused IsSupported

    Change-Id: If8206658fdfb6108221806c09c99bf0a30f4a586
    Signed-off-by: Jesse Chan <jc@lineageos.org>

  * recovery: volmgr: remove filesystem checks

    Those checks are not strictly necessary and we are
    not building fsck tools for recovery for now.

    Remove those checks so volmgr can be useful.

    Change-Id: I87756c61b933b6cdccd281c6276b686fbd36019f
    Signed-off-by: Jesse Chan <jc@lineageos.org>

  * recovery: fixup `EmulatedVolume creating`

    Avoid dangling pointer. Instead of pointing to FstabEntry create copy.

    Change-Id: I57f76006db09a6add2c173f43175f0f6b848d87b

  * recovery: fix volmgr cleaning up

    Don't reset pointer to netlink manager
    Delete disks in stop() rather then in ~VolumeManager
    Call destroy() before deleting disks cause delete expects the
      disk to be destroyed
    Clear the lists or we would read garbage data on the next scan

    Change-Id: Idadfa1f33b7cb5f2f3c780848a99344a6608420e

  * recovery: handle interrupts in apply update menu

    Change-Id: I1f78f9196634353b77986545332d7d52a5f0c161

Change-Id: Ic82d929e052b5ba70ecf7b475e0a223d77d9687e

recovery: fix applying updates

We need to break after applying from either ADB or Storage to return
the status of the installation.

Otherwise the log is stuck until you press on the back arrow, you
are able to start sideload multiple times and other shenanigans.

Change-Id: I06c9dcf6161dd1a0199417cfed2465914837d795
Signed-off-by: Alexander Martinz <amartinz@shiftphones.com>
diff --git a/install/Android.bp b/install/Android.bp
index 93949ca..b3e366c 100644
--- a/install/Android.bp
+++ b/install/Android.bp
@@ -120,6 +120,7 @@
 
     shared_libs: [
         "librecovery_ui",
+        "libvolume_manager",
     ],
 
     export_include_dirs: [
diff --git a/install/fuse_install.cpp b/install/fuse_install.cpp
index e481f91..727419d 100644
--- a/install/fuse_install.cpp
+++ b/install/fuse_install.cpp
@@ -39,7 +39,9 @@
 #include "install/install.h"
 #include "recovery_utils/roots.h"
 
-static constexpr const char* SDCARD_ROOT = "/data/media/0";
+using android::volmgr::VolumeInfo;
+using android::volmgr::VolumeManager;
+
 // How long (in seconds) we wait for the fuse-provided package file to
 // appear, before timing out.
 static constexpr int SDCARD_INSTALL_TIMEOUT = 10;
@@ -56,8 +58,6 @@
 
 // Returns the selected filename, or an empty string.
 static std::string BrowseDirectory(const std::string& path, Device* device, RecoveryUI* ui) {
-  ensure_path_mounted(path);
-
   std::unique_ptr<DIR, decltype(&closedir)> d(opendir(path.c_str()), closedir);
   if (!d) {
     PLOG(ERROR) << "error opening " << path;
@@ -140,12 +140,6 @@
     return false;
   }
 
-  if (android::base::StartsWith(path, SDCARD_ROOT)) {
-    // The installation process expects to find the sdcard unmounted. Unmount it with MNT_DETACH so
-    // that our open file continues to work but new references see it as unmounted.
-    umount2("/data", MNT_DETACH);
-  }
-
   return run_fuse_sideload(std::move(fuse_data_provider)) == 0;
 }
 
@@ -208,17 +202,15 @@
   return result;
 }
 
-InstallResult ApplyFromSdcard(Device* device) {
+InstallResult ApplyFromStorage(Device* device, VolumeInfo& vi) {
   auto ui = device->GetUI();
-  if (ensure_path_mounted(SDCARD_ROOT) != 0) {
-    LOG(ERROR) << "\n-- Couldn't mount " << SDCARD_ROOT << ".\n";
+  if (!VolumeManager::Instance()->volumeMount(vi.mId)) {
     return INSTALL_NONE;
   }
 
-  std::string path = BrowseDirectory(SDCARD_ROOT, device, ui);
+  std::string path = BrowseDirectory(vi.mPath, device, ui);
   if (path.empty()) {
-    LOG(ERROR) << "\n-- No package file selected.\n";
-    ensure_path_unmounted(SDCARD_ROOT);
+    VolumeManager::Instance()->volumeUnmount(vi.mId);
     return INSTALL_NONE;
   }
 
@@ -231,6 +223,7 @@
   SetSdcardUpdateBootloaderMessage();
 
   auto result = InstallWithFuseFromPath(path, device);
-  ensure_path_unmounted(SDCARD_ROOT);
+
+  VolumeManager::Instance()->volumeUnmount(vi.mId);
   return result;
 }
diff --git a/install/include/install/fuse_install.h b/install/include/install/fuse_install.h
index 29c283f..7c38d0d 100644
--- a/install/include/install/fuse_install.h
+++ b/install/include/install/fuse_install.h
@@ -22,9 +22,13 @@
 #include "recovery_ui/device.h"
 #include "recovery_ui/ui.h"
 
+#include <volume_manager/VolumeManager.h>
+
+using android::volmgr::VolumeInfo;
+
 // Starts FUSE with the package from |path| as the data source. And installs the package from
 // |FUSE_SIDELOAD_HOST_PATHNAME|. The |path| can point to the location of a package zip file or a
 // block map file with the prefix '@'; e.g. /sdcard/package.zip, @/cache/recovery/block.map.
 InstallResult InstallWithFuseFromPath(std::string_view path, Device* device);
 
-InstallResult ApplyFromSdcard(Device* device);
+InstallResult ApplyFromStorage(Device* device, VolumeInfo& vi);