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
diff --git a/recovery_ui/Android.bp b/recovery_ui/Android.bp
index f64b0d1..454947b 100644
--- a/recovery_ui/Android.bp
+++ b/recovery_ui/Android.bp
@@ -51,6 +51,7 @@
         "libbase",
         "libpng",
         "libz",
+        "libvolume_manager",
     ],
 }
 
diff --git a/recovery_ui/device.cpp b/recovery_ui/device.cpp
index 4408c9f..34c4ce9 100644
--- a/recovery_ui/device.cpp
+++ b/recovery_ui/device.cpp
@@ -32,7 +32,7 @@
 static std::vector<std::string> g_main_header{};
 static std::vector<menu_action_t> g_main_actions{
   { "Reboot system now", Device::REBOOT },
-  { "Apply update", Device::MENU_UPDATE },
+  { "Apply update", Device::APPLY_UPDATE },
   { "Factory reset", Device::MENU_WIPE },
   { "Advanced", Device::MENU_ADVANCED },
 };
@@ -58,12 +58,6 @@
   { "Format system partition", Device::WIPE_SYSTEM },
 };
 
-static std::vector<std::string> g_update_header{ "Apply update" };
-static std::vector<menu_action_t> g_update_actions{
-  { "Apply from ADB", Device::APPLY_ADB_SIDELOAD },
-  { "Choose from internal storage", Device::APPLY_SDCARD },
-};
-
 static std::vector<menu_action_t>* current_menu_ = &g_main_actions;
 static std::vector<std::string> g_menu_items;
 
@@ -91,7 +85,6 @@
 }
 
 void Device::RemoveMenuItemForAction(Device::BuiltinAction action) {
-  ::RemoveMenuItemForAction(g_update_actions, action);
   ::RemoveMenuItemForAction(g_wipe_actions, action);
   ::RemoveMenuItemForAction(g_advanced_actions, action);
 }
@@ -101,11 +94,9 @@
 }
 
 const std::vector<std::string>& Device::GetMenuHeaders() {
-  if (current_menu_ == &g_update_actions)
-      return g_update_header;
-  else if (current_menu_ == &g_wipe_actions)
+  if (current_menu_ == &g_wipe_actions)
       return g_wipe_header;
-  else if (current_menu_ == &g_advanced_actions)
+  if (current_menu_ == &g_advanced_actions)
       return g_advanced_header;
   return g_main_header;
 }
@@ -115,9 +106,6 @@
 
   if (action > MENU_BASE) {
     switch (action) {
-      case Device::BuiltinAction::MENU_UPDATE:
-        current_menu_ = &g_update_actions;
-        break;
       case Device::BuiltinAction::MENU_WIPE:
         current_menu_ = &g_wipe_actions;
         break;
@@ -171,6 +159,9 @@
     case KEY_AGAIN:
       return kDoSideload;
 
+    case KEY_REFRESH:
+      return kRefresh;
+
     default:
       // If you have all of the above buttons, any other buttons
       // are ignored. Otherwise, any button cycles the highlight.
diff --git a/recovery_ui/include/recovery_ui/device.h b/recovery_ui/include/recovery_ui/device.h
index d95d6fd..c2fc38d 100644
--- a/recovery_ui/include/recovery_ui/device.h
+++ b/recovery_ui/include/recovery_ui/device.h
@@ -25,8 +25,7 @@
 #include <string>
 #include <vector>
 
-// Forward declaration to avoid including "ui.h".
-class RecoveryUI;
+#include "ui.h"
 
 class BootState;
 
@@ -41,6 +40,7 @@
   static constexpr const int kDoSideload = -7;
   static constexpr const int kScrollUp = -8;
   static constexpr const int kScrollDown = -9;
+  static constexpr const int kRefresh = -10;
 
   // ENTER vs REBOOT: The latter will trigger a reboot that goes through bootloader, which allows
   // using a new bootloader / recovery image if applicable. For example, REBOOT_RESCUE goes from
@@ -49,9 +49,9 @@
   enum BuiltinAction {
     NO_ACTION = 0,
     REBOOT = 1,
-    APPLY_SDCARD = 2,
+    APPLY_UPDATE = 2,
     // APPLY_CACHE was 3.
-    APPLY_ADB_SIDELOAD = 4,
+    // APPLY_ADB_SIDELOAD was 4.
     WIPE_DATA = 5,
     WIPE_CACHE = 6,
     REBOOT_BOOTLOADER = 7,
@@ -72,7 +72,6 @@
     WIPE_SYSTEM = 100,
     ENABLE_ADB = 101,
     MENU_BASE = 200,
-    MENU_UPDATE = 201,
     MENU_WIPE = 202,
     MENU_ADVANCED = 203,
   };
@@ -165,6 +164,10 @@
   std::optional<std::string> GetReason() const;
   std::optional<std::string> GetStage() const;
 
+  virtual void handleVolumeChanged() {
+    ui_->onVolumeChanged();
+  }
+
  private:
   // The RecoveryUI object that should be used to display the user interface for this device.
   std::unique_ptr<RecoveryUI> ui_;
diff --git a/recovery_ui/include/recovery_ui/screen_ui.h b/recovery_ui/include/recovery_ui/screen_ui.h
index fef3491..ee14c28 100644
--- a/recovery_ui/include/recovery_ui/screen_ui.h
+++ b/recovery_ui/include/recovery_ui/screen_ui.h
@@ -313,7 +313,7 @@
   // menu display
   size_t ShowMenu(const std::vector<std::string>& headers, const std::vector<std::string>& items,
                   size_t initial_selection, bool menu_only,
-                  const std::function<int(int, bool)>& key_handler) override;
+                  const std::function<int(int, bool)>& key_handler, bool refreshable) override;
   void SetTitle(const std::vector<std::string>& lines) override;
 
   void KeyLongPress(int) override;
@@ -379,7 +379,8 @@
 
   // Takes the ownership of |menu| and displays it.
   virtual size_t ShowMenu(std::unique_ptr<Menu>&& menu, bool menu_only,
-                          const std::function<int(int, bool)>& key_handler);
+                          const std::function<int(int, bool)>& key_handler,
+                          bool refreshable = false);
 
   // Sets the menu highlight to the given index, wrapping if necessary. Returns the actual item
   // selected.
diff --git a/recovery_ui/include/recovery_ui/stub_ui.h b/recovery_ui/include/recovery_ui/stub_ui.h
index 49689ba..838f2fa 100644
--- a/recovery_ui/include/recovery_ui/stub_ui.h
+++ b/recovery_ui/include/recovery_ui/stub_ui.h
@@ -64,7 +64,8 @@
   size_t ShowMenu(const std::vector<std::string>& /* headers */,
                   const std::vector<std::string>& /* items */, size_t /* initial_selection */,
                   bool /* menu_only */,
-                  const std::function<int(int, bool)>& /* key_handler */) override;
+                  const std::function<int(int, bool)>& /* key_handler */,
+                  bool /*refreshable*/) override;
 
   size_t ShowPromptWipeDataMenu(const std::vector<std::string>& /* backup_headers */,
                                 const std::vector<std::string>& /* backup_items */,
diff --git a/recovery_ui/include/recovery_ui/ui.h b/recovery_ui/include/recovery_ui/ui.h
index 62ea57b..4703065 100644
--- a/recovery_ui/include/recovery_ui/ui.h
+++ b/recovery_ui/include/recovery_ui/ui.h
@@ -255,7 +255,8 @@
   // static_cast<size_t>(ERR_KEY_INTERTUPT) if interrupted, such as by InterruptKey().
   virtual size_t ShowMenu(const std::vector<std::string>& headers,
                           const std::vector<std::string>& items, size_t initial_selection,
-                          bool menu_only, const std::function<int(int, bool)>& key_handler) = 0;
+                          bool menu_only, const std::function<int(int, bool)>& key_handler,
+                          bool refreshable = false) = 0;
 
   // Displays the localized wipe data menu with pre-generated graphs. If there's an issue
   // with the graphs, falls back to use the backup string headers and items instead. The initial
@@ -291,6 +292,11 @@
 
   virtual bool IsUsbConnected();
 
+  // Notify of volume state change
+  void onVolumeChanged() {
+    EnqueueKey(KEY_REFRESH);
+  }
+
  protected:
   void EnqueueKey(int key_code);
   void EnqueueTouch(const Point& pos);
diff --git a/recovery_ui/screen_ui.cpp b/recovery_ui/screen_ui.cpp
index 43121fd..76e6d76 100644
--- a/recovery_ui/screen_ui.cpp
+++ b/recovery_ui/screen_ui.cpp
@@ -1407,7 +1407,8 @@
 }
 
 size_t ScreenRecoveryUI::ShowMenu(std::unique_ptr<Menu>&& menu, bool menu_only,
-                                  const std::function<int(int, bool)>& key_handler) {
+                                  const std::function<int(int, bool)>& key_handler,
+                                  bool refreshable) {
   // Throw away keys pressed previously, so user doesn't accidentally trigger menu items.
   FlushKeys();
 
@@ -1455,6 +1456,7 @@
       bool visible = IsTextVisible();
       action = key_handler(evt.key(), visible);
     }
+
     if (action < 0) {
       switch (action) {
         case Device::kHighlightUp:
@@ -1487,13 +1489,18 @@
         case Device::kDoSideload:
           chosen_item = Device::kDoSideload;
           break;
+        case Device::kRefresh:
+          if (refreshable) {
+            chosen_item = Device::kRefresh;
+          }
+          break;
       }
     } else if (!menu_only) {
       chosen_item = action;
     }
 
     if (chosen_item == Device::kGoBack || chosen_item == Device::kGoHome ||
-        chosen_item == Device::kDoSideload) {
+        chosen_item == Device::kDoSideload || chosen_item == Device::kRefresh) {
       break;
     }
   }
@@ -1506,13 +1513,14 @@
 size_t ScreenRecoveryUI::ShowMenu(const std::vector<std::string>& headers,
                                   const std::vector<std::string>& items, size_t initial_selection,
                                   bool menu_only,
-                                  const std::function<int(int, bool)>& key_handler) {
+                                  const std::function<int(int, bool)>& key_handler,
+                                  bool refreshable) {
   auto menu = CreateMenu(headers, items, initial_selection);
   if (menu == nullptr) {
     return initial_selection;
   }
 
-  return ShowMenu(std::move(menu), menu_only, key_handler);
+  return ShowMenu(std::move(menu), menu_only, key_handler, refreshable);
 }
 
 size_t ScreenRecoveryUI::ShowPromptWipeDataMenu(const std::vector<std::string>& backup_headers,
diff --git a/recovery_ui/stub_ui.cpp b/recovery_ui/stub_ui.cpp
index 87605cf..cabbd5f 100644
--- a/recovery_ui/stub_ui.cpp
+++ b/recovery_ui/stub_ui.cpp
@@ -23,7 +23,8 @@
 size_t StubRecoveryUI::ShowMenu(const std::vector<std::string>& /* headers */,
                                 const std::vector<std::string>& /* items */,
                                 size_t /* initial_selection */, bool /* menu_only */,
-                                const std::function<int(int, bool)>& /*key_handler*/) {
+                                const std::function<int(int, bool)>& /*key_handler*/,
+                                bool /* refreshable */) {
   while (true) {
     // Exit the loop in the case of interruption or time out.
     InputEvent evt = WaitInputEvent();
diff --git a/recovery_ui/ui.cpp b/recovery_ui/ui.cpp
index 6fc2dde..6aa08f1 100644
--- a/recovery_ui/ui.cpp
+++ b/recovery_ui/ui.cpp
@@ -36,6 +36,7 @@
 #include <android-base/parseint.h>
 #include <android-base/properties.h>
 #include <android-base/strings.h>
+#include <volume_manager/VolumeManager.h>
 
 #include "minui/minui.h"
 #include "otautil/sysutil.h"
@@ -471,6 +472,7 @@
 
       case RecoveryUI::REBOOT:
         if (reboot_enabled) {
+          android::volmgr::VolumeManager::Instance()->unmountAll();
           Reboot("userrequested,recovery,ui");
         }
         break;