Merge "recovery: Configure device menu based on runtime info."
am: e498ef2f03

Change-Id: Ib513582394b796ca64c5e3ce46fc2bd535c621de
diff --git a/Android.mk b/Android.mk
index afbc950..9dfb5f6 100644
--- a/Android.mk
+++ b/Android.mk
@@ -185,10 +185,6 @@
 
 LOCAL_HAL_STATIC_LIBRARIES := libhealthd
 
-ifeq ($(AB_OTA_UPDATER),true)
-    LOCAL_CFLAGS += -DAB_OTA_UPDATER=1
-endif
-
 LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
 
 ifeq ($(BOARD_CACHEIMAGE_PARTITION_SIZE),)
diff --git a/device.cpp b/device.cpp
index 5cf9cc2..3c6334e 100644
--- a/device.cpp
+++ b/device.cpp
@@ -16,59 +16,57 @@
 
 #include "device.h"
 
+#include <algorithm>
+#include <string>
+#include <utility>
+#include <vector>
+
 #include <android-base/logging.h>
-#include <android-base/macros.h>
 
 #include "ui.h"
 
-// clang-format off
-static constexpr const char* kItems[]{
-  "Reboot system now",
-  "Reboot to bootloader",
-  "Apply update from ADB",
-  "Apply update from SD card",
-  "Wipe data/factory reset",
-#ifndef AB_OTA_UPDATER
-  "Wipe cache partition",
-#endif  // !AB_OTA_UPDATER
-  "Mount /system",
-  "View recovery logs",
-  "Run graphics test",
-  "Run locale test",
-  "Power off",
+static std::vector<std::pair<std::string, Device::BuiltinAction>> g_menu_actions{
+  { "Reboot system now", Device::REBOOT },
+  { "Reboot to bootloader", Device::REBOOT_BOOTLOADER },
+  { "Apply update from ADB", Device::APPLY_ADB_SIDELOAD },
+  { "Apply update from SD card", Device::APPLY_SDCARD },
+  { "Wipe data/factory reset", Device::WIPE_DATA },
+  { "Wipe cache partition", Device::WIPE_CACHE },
+  { "Mount /system", Device::MOUNT_SYSTEM },
+  { "View recovery logs", Device::VIEW_RECOVERY_LOGS },
+  { "Run graphics test", Device::RUN_GRAPHICS_TEST },
+  { "Run locale test", Device::RUN_LOCALE_TEST },
+  { "Power off", Device::SHUTDOWN },
 };
-// clang-format on
 
-// clang-format off
-static constexpr Device::BuiltinAction kMenuActions[] {
-  Device::REBOOT,
-  Device::REBOOT_BOOTLOADER,
-  Device::APPLY_ADB_SIDELOAD,
-  Device::APPLY_SDCARD,
-  Device::WIPE_DATA,
-#ifndef AB_OTA_UPDATER
-  Device::WIPE_CACHE,
-#endif  // !AB_OTA_UPDATER
-  Device::MOUNT_SYSTEM,
-  Device::VIEW_RECOVERY_LOGS,
-  Device::RUN_GRAPHICS_TEST,
-  Device::RUN_LOCALE_TEST,
-  Device::SHUTDOWN,
-};
-// clang-format on
+static std::vector<std::string> g_menu_items;
 
-static_assert(arraysize(kItems) == arraysize(kMenuActions),
-              "kItems and kMenuActions should have the same length.");
+static void PopulateMenuItems() {
+  g_menu_items.clear();
+  std::transform(g_menu_actions.cbegin(), g_menu_actions.cend(), std::back_inserter(g_menu_items),
+                 [](const auto& entry) { return entry.first; });
+}
 
-static const std::vector<std::string> kMenuItems(kItems, kItems + arraysize(kItems));
+Device::Device(RecoveryUI* ui) : ui_(ui) {
+  PopulateMenuItems();
+}
+
+void Device::RemoveMenuItemForAction(Device::BuiltinAction action) {
+  g_menu_actions.erase(
+      std::remove_if(g_menu_actions.begin(), g_menu_actions.end(),
+                     [action](const auto& entry) { return entry.second == action; }));
+  CHECK(!g_menu_actions.empty());
+
+  // Re-populate the menu items.
+  PopulateMenuItems();
+}
 
 const std::vector<std::string>& Device::GetMenuItems() {
-  return kMenuItems;
+  return g_menu_items;
 }
 
 Device::BuiltinAction Device::InvokeMenuItem(size_t menu_position) {
-  // CHECK_LT(menu_position, );
-  return kMenuActions[menu_position];
+  return g_menu_actions[menu_position].second;
 }
 
 int Device::HandleMenuKey(int key, bool visible) {
diff --git a/device.h b/device.h
index bf148f5..9c43371 100644
--- a/device.h
+++ b/device.h
@@ -49,7 +49,7 @@
     RUN_LOCALE_TEST = 12,
   };
 
-  explicit Device(RecoveryUI* ui) : ui_(ui) {}
+  explicit Device(RecoveryUI* ui);
   virtual ~Device() {}
 
   // Returns a raw pointer to the RecoveryUI object.
@@ -96,6 +96,10 @@
   // here and return NO_ACTION.
   virtual BuiltinAction InvokeMenuItem(size_t menu_position);
 
+  // Removes the menu item for the given action. This allows tailoring the menu based on the
+  // runtime info, such as the availability of /cache or /sdcard.
+  virtual void RemoveMenuItemForAction(Device::BuiltinAction action);
+
   // Called before and after we do a wipe data/factory reset operation, either via a reboot from the
   // main system with the --wipe_data flag, or when the user boots into recovery image manually and
   // selects the option from the menu, to perform whatever device-specific wiping actions as needed.
diff --git a/recovery.cpp b/recovery.cpp
index b11298f..e427998 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -1182,6 +1182,10 @@
   }
   ui = device->GetUI();
 
+  if (!has_cache) {
+    device->RemoveMenuItemForAction(Device::WIPE_CACHE);
+  }
+
   // Set background string to "installing security update" for security update,
   // otherwise set it to "installing system update".
   ui->SetSystemUpdateText(security_update);