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.

Change-Id: Ic82d929e052b5ba70ecf7b475e0a223d77d9687e
diff --git a/recovery.cpp b/recovery.cpp
index ff04b49..7b8e32b 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -46,6 +46,7 @@
 #include <bootloader_message/bootloader_message.h>
 #include <cutils/properties.h> /* for property_list */
 #include <healthhalutils/HealthHalUtils.h>
+#include <volume_manager/VolumeManager.h>
 #include <ziparchive/zip_archive.h>
 
 #include "common.h"
@@ -62,6 +63,10 @@
 #include "otautil/sysutil.h"
 #include "recovery_ui/screen_ui.h"
 #include "recovery_ui/ui.h"
+#include "volclient.h"
+
+using android::volmgr::VolumeManager;
+using android::volmgr::VolumeInfo;
 
 static constexpr const char* COMMAND_FILE = "/cache/recovery/command";
 static constexpr const char* LAST_KMSG_FILE = "/cache/recovery/last_kmsg";
@@ -206,6 +211,42 @@
   return (chosen_item == 1);
 }
 
+static int apply_update_menu(Device* device, RecoveryUI* ui, Device::BuiltinAction* reboot_action){
+  std::vector<std::string> headers{ "Apply update" };
+  std::vector<std::string> items;
+
+  const int item_sideload = 0;
+  std::vector<VolumeInfo> volumes;
+
+  int status = INSTALL_ERROR;
+
+  for (;;) {
+    items.clear();
+    items.push_back("Apply from ADB");
+    VolumeManager::Instance()->getVolumeInfo(volumes);
+    for (auto& vitr : volumes) {
+      items.push_back("Choose from " + vitr.mLabel);
+    }
+
+    int chosen = ui->ShowMenu(
+      headers, items, 0, false,
+      std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2),
+      true /* refreshable */);
+    if (chosen == Device::kRefresh) {
+      continue;
+    }
+    if (chosen == Device::kGoBack) {
+      break;
+    }
+    if (chosen == item_sideload) {
+      status = ApplyFromAdb(device, false /* rescue_mode */, reboot_action);
+    } else {
+      status = ApplyFromStorage(device, volumes[chosen - 1], ui);
+    }
+  }
+  return status;
+}
+
 static InstallResult prompt_and_wipe_data(Device* device) {
   // Use a single string and let ScreenRecoveryUI handles the wrapping.
   std::vector<std::string> wipe_data_menu_headers{
@@ -538,7 +579,6 @@
 
     switch (chosen_action) {
       case Device::MENU_BASE:
-      case Device::MENU_UPDATE:
       case Device::MENU_WIPE:
       case Device::MENU_ADVANCED:
         goto change_menu;
@@ -588,29 +628,24 @@
         break;
       }
 
-      case Device::APPLY_ADB_SIDELOAD:
-      case Device::APPLY_SDCARD:
+      case Device::APPLY_UPDATE:
       case Device::ENTER_RESCUE: {
         save_current_log = true;
 
-        bool adb = true;
         Device::BuiltinAction reboot_action;
         if (chosen_action == Device::ENTER_RESCUE) {
           // Switch to graphics screen.
           ui->ShowText(false);
           status = ApplyFromAdb(device, true /* rescue_mode */, &reboot_action);
-        } else if (chosen_action == Device::APPLY_ADB_SIDELOAD) {
-          status = ApplyFromAdb(device, false /* rescue_mode */, &reboot_action);
-        } else {
-          adb = false;
-          status = ApplyFromSdcard(device, ui);
+        } else if (chosen_action == Device::APPLY_UPDATE) {
+          status = apply_update_menu(device, ui, &reboot_action);
         }
 
-        ui->Print("\nInstall from %s completed with status %d.\n", adb ? "ADB" : "SD card", status);
         if (status == INSTALL_REBOOT) {
           return reboot_action;
         }
 
+        ui->Print("\nInstall completed with status %d.\n", status);
         if (status != INSTALL_SUCCESS) {
           ui->SetBackground(RecoveryUI::ERROR);
           ui->Print("Installation aborted.\n");
@@ -870,6 +905,12 @@
   printf("stage is [%s]\n", stage.c_str());
   printf("reason is [%s]\n", reason);
 
+  VolumeClient* volclient = new VolumeClient(device);
+  VolumeManager* volmgr = VolumeManager::Instance();
+  if (!volmgr->start(volclient, sehandle)) {
+    printf("Failed to start volume manager\n");
+  }
+
   // Set background string to "installing security update" for security update,
   // otherwise set it to "installing system update".
   ui->SetSystemUpdateText(security_update);
@@ -1043,5 +1084,11 @@
   // Save logs and clean up before rebooting or shutting down.
   finish_recovery();
 
+  volmgr->unmountAll();
+  volmgr->stop();
+  delete volclient;
+
+  sync();
+
   return next_action;
 }