recovery: split in submenus
Co-authored-by: aleasto <ales.astone@gmail.com>
Change-Id: I4426689634ca477955b67d2264999f450f02067f
diff --git a/recovery.cpp b/recovery.cpp
index 8d85ef6..f3a78cc 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -506,16 +506,18 @@
}
ui->SetProgressType(RecoveryUI::EMPTY);
+change_menu:
size_t chosen_item = ui->ShowMenu(
- {}, device->GetMenuItems(), 0, false,
+ device->GetMenuHeaders(), device->GetMenuItems(), 0, false,
std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));
// Handle Interrupt key
if (chosen_item == static_cast<size_t>(RecoveryUI::KeyError::INTERRUPTED)) {
return Device::KEY_INTERRUPTED;
}
- // We are already in the main menu
+
if (chosen_item == Device::kGoBack || chosen_item == Device::kGoHome) {
- continue;
+ device->GoHome();
+ goto change_menu;
}
// Device-specific code may take some action here. It may return one of the core actions
@@ -526,6 +528,12 @@
: device->InvokeMenuItem(chosen_item);
switch (chosen_action) {
+ case Device::MENU_BASE:
+ case Device::MENU_UPDATE:
+ case Device::MENU_WIPE:
+ case Device::MENU_ADVANCED:
+ goto change_menu;
+
case Device::NO_ACTION:
break;
diff --git a/recovery_main.cpp b/recovery_main.cpp
index 5b00f40..3b56947 100644
--- a/recovery_main.cpp
+++ b/recovery_main.cpp
@@ -560,6 +560,7 @@
case Device::ENTER_RECOVERY:
LOG(INFO) << "Entering recovery";
fastboot = false;
+ device->GoHome();
break;
default:
diff --git a/recovery_ui/device.cpp b/recovery_ui/device.cpp
index d205f77..0952952 100644
--- a/recovery_ui/device.cpp
+++ b/recovery_ui/device.cpp
@@ -26,16 +26,21 @@
#include "recovery_ui/ui.h"
-static std::vector<std::pair<std::string, Device::BuiltinAction>> g_menu_actions{
+typedef std::pair<std::string, Device::BuiltinAction> menu_action_t;
+
+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 },
+ { "Factory reset", Device::MENU_WIPE },
+ { "Advanced", Device::MENU_ADVANCED },
+};
+
+static std::vector<std::string> g_advanced_header{ "Advanced options" };
+static std::vector<menu_action_t> g_advanced_actions{
+ { "Enter fastboot", Device::ENTER_FASTBOOT },
{ "Reboot to bootloader", Device::REBOOT_BOOTLOADER },
{ "Reboot to recovery", Device::REBOOT_RECOVERY },
- { "Enter fastboot", Device::ENTER_FASTBOOT },
- { "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 },
- { "Wipe system partition", Device::WIPE_SYSTEM },
{ "Mount /system", Device::MOUNT_SYSTEM },
{ "View recovery logs", Device::VIEW_RECOVERY_LOGS },
{ "Run graphics test", Device::RUN_GRAPHICS_TEST },
@@ -44,11 +49,25 @@
{ "Power off", Device::SHUTDOWN },
};
+static std::vector<std::string> g_wipe_header{ "Factory reset" };
+static std::vector<menu_action_t> g_wipe_actions{
+ { "Wipe data/factory reset", Device::WIPE_DATA },
+ { "Wipe cache partition", Device::WIPE_CACHE },
+ { "Wipe 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;
static void PopulateMenuItems() {
g_menu_items.clear();
- std::transform(g_menu_actions.cbegin(), g_menu_actions.cend(), std::back_inserter(g_menu_items),
+ std::transform(current_menu_->cbegin(), current_menu_->cend(), std::back_inserter(g_menu_items),
[](const auto& entry) { return entry.first; });
}
@@ -56,22 +75,59 @@
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.
+void Device::GoHome() {
+ current_menu_ = &g_main_actions;
PopulateMenuItems();
}
+static void RemoveMenuItemForAction(std::vector<menu_action_t>& menu, Device::BuiltinAction action) {
+ menu.erase(
+ std::remove_if(menu.begin(), menu.end(),
+ [action](const auto& entry) { return entry.second == action; }), menu.end());
+ CHECK(!menu.empty());
+}
+
+void Device::RemoveMenuItemForAction(Device::BuiltinAction action) {
+ ::RemoveMenuItemForAction(g_update_actions, action);
+ ::RemoveMenuItemForAction(g_wipe_actions, action);
+ ::RemoveMenuItemForAction(g_advanced_actions, action);
+}
+
const std::vector<std::string>& Device::GetMenuItems() {
return g_menu_items;
}
+const std::vector<std::string>& Device::GetMenuHeaders() {
+ if (current_menu_ == &g_update_actions)
+ return g_update_header;
+ else if (current_menu_ == &g_wipe_actions)
+ return g_wipe_header;
+ else if (current_menu_ == &g_advanced_actions)
+ return g_advanced_header;
+ return g_main_header;
+}
+
Device::BuiltinAction Device::InvokeMenuItem(size_t menu_position) {
- return g_menu_actions[menu_position].second;
+ Device::BuiltinAction action = (*current_menu_)[menu_position].second;
+
+ 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;
+ case Device::BuiltinAction::MENU_ADVANCED:
+ current_menu_ = &g_advanced_actions;
+ break;
+ default:
+ break;
+ }
+ action = Device::BuiltinAction::NO_ACTION;
+ PopulateMenuItems();
+ }
+ return action;
}
int Device::HandleMenuKey(int key, bool visible) {
diff --git a/recovery_ui/include/recovery_ui/device.h b/recovery_ui/include/recovery_ui/device.h
index 73b4b89..74e2dc1 100644
--- a/recovery_ui/include/recovery_ui/device.h
+++ b/recovery_ui/include/recovery_ui/device.h
@@ -65,6 +65,10 @@
REBOOT_RECOVERY = 18,
REBOOT_RESCUE = 19,
WIPE_SYSTEM = 100,
+ MENU_BASE = 200,
+ MENU_UPDATE = 201,
+ MENU_WIPE = 202,
+ MENU_ADVANCED = 203,
};
explicit Device(RecoveryUI* ui);
@@ -102,10 +106,16 @@
// - invoke a specific action (a menu position: non-negative value)
virtual int HandleMenuKey(int key, bool visible);
- // Returns the list of menu items (a vector of strings). The menu_position passed to
- // InvokeMenuItem() will correspond to the indexes into this array.
+ // Returns the list of the currently visible menu items (a vector of strings).
+ // The menu_position passed to InvokeMenuItem() will correspond to the indexes into this array.
virtual const std::vector<std::string>& GetMenuItems();
+ // Returns headers for the currently visible menu. Can be empty vector.
+ virtual const std::vector<std::string>& GetMenuHeaders();
+
+ // Return to the main menu
+ virtual void GoHome();
+
// Performs a recovery action selected from the menu. 'menu_position' will be the index of the
// selected menu item, or a non-negative value returned from HandleMenuKey(). The menu will be
// hidden when this is called; implementations can call GetUI()->Print() to print information to