summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--device.cpp120
-rw-r--r--device.h31
-rw-r--r--recovery.cpp18
3 files changed, 126 insertions, 43 deletions
diff --git a/device.cpp b/device.cpp
index 0ac6b3f..4f19f0e 100644
--- a/device.cpp
+++ b/device.cpp
@@ -16,42 +16,119 @@
#include "device.h"
-static const char* MENU_ITEMS[] = {
- "Reboot system now",
+enum menu_action_type {
+ ACTION_NONE,
+ ACTION_SUBMENU,
+ ACTION_INVOKE
+};
+
+struct menu_entry;
+struct menu {
+ const char** names;
+ const menu_entry* entries;
+};
+
+union menu_action {
+ const menu* submenu;
+ Device::BuiltinAction action;
+};
+
+struct menu_entry {
+ menu_action_type action_type;
+ const menu_action action;
+};
+
+static const char* WIPE_MENU_NAMES[] = {
+ "System reset (keep media)",
+ "Full factory reset",
+ "Wipe cache partition",
+ nullptr
+};
+static const menu_entry WIPE_MENU_ENTRIES[] = {
+ { ACTION_INVOKE, { .action = Device::WIPE_DATA } },
+ { ACTION_INVOKE, { .action = Device::WIPE_FULL } },
+ { ACTION_INVOKE, { .action = Device::WIPE_CACHE } },
+ { ACTION_NONE, { .action = Device::NO_ACTION } }
+};
+static const menu WIPE_MENU = {
+ WIPE_MENU_NAMES,
+ WIPE_MENU_ENTRIES
+};
+
+static const char* ADVANCED_MENU_NAMES[] = {
+ "Reboot recovery",
#ifdef DOWNLOAD_MODE
"Reboot to download mode",
#else
"Reboot to bootloader",
#endif
- "Apply update",
- "Wipe data/factory reset",
- "Wipe cache partition",
- "Wipe media",
"Mount /system",
"View recovery logs",
"Power off",
- NULL
+ nullptr
+};
+static const menu_entry ADVANCED_MENU_ENTRIES[] = {
+ { ACTION_INVOKE, { .action = Device::REBOOT_RECOVERY } },
+#ifdef DOWNLOAD_MODE
+ { ACTION_INVOKE, { .action = Device::REBOOT_BOOTLOADER } },
+#else
+ { ACTION_INVOKE, { .action = Device::REBOOT_BOOTLOADER } },
+#endif
+ { ACTION_INVOKE, { .action = Device::MOUNT_SYSTEM } },
+ { ACTION_INVOKE, { .action = Device::VIEW_RECOVERY_LOGS } },
+ { ACTION_INVOKE, { .action = Device::SHUTDOWN } },
+ { ACTION_NONE, { .action = Device::NO_ACTION } }
+};
+static const menu ADVANCED_MENU = {
+ ADVANCED_MENU_NAMES,
+ ADVANCED_MENU_ENTRIES
+};
+
+static const char* MAIN_MENU_NAMES[] = {
+ "Reboot system now",
+ "Apply update",
+ "Factory reset",
+ "Advanced",
+ nullptr
+};
+static const menu_entry MAIN_MENU_ENTRIES[] = {
+ { ACTION_INVOKE, { .action = Device::REBOOT } },
+ { ACTION_INVOKE, { .action = Device::APPLY_UPDATE } },
+ { ACTION_SUBMENU, { .submenu = &WIPE_MENU } },
+ { ACTION_SUBMENU, { .submenu = &ADVANCED_MENU } },
+ { ACTION_NONE, { .action = Device::NO_ACTION } }
+};
+static const menu MAIN_MENU = {
+ MAIN_MENU_NAMES,
+ MAIN_MENU_ENTRIES
};
-extern int ui_root_menu;
+Device::Device(RecoveryUI* ui) :
+ ui_(ui) {
+ menu_stack.push(&MAIN_MENU);
+}
const char* const* Device::GetMenuItems() {
- return MENU_ITEMS;
+ const menu* m = menu_stack.top();
+ return m->names;
}
Device::BuiltinAction Device::InvokeMenuItem(int menu_position) {
- switch (menu_position) {
- case 0: return REBOOT;
- case 1: return REBOOT_BOOTLOADER;
- case 2: return APPLY_UPDATE;
- case 3: return WIPE_DATA;
- case 4: return WIPE_CACHE;
- case 5: return WIPE_MEDIA;
- case 6: return MOUNT_SYSTEM;
- case 7: return VIEW_RECOVERY_LOGS;
- case 8: return SHUTDOWN;
- default: return NO_ACTION;
+ if (menu_position < 0) {
+ if (menu_position == Device::kGoBack) {
+ if (menu_stack.size() > 1) {
+ menu_stack.pop();
+ }
+ }
+ return NO_ACTION;
+ }
+ const menu* m = menu_stack.top();
+ const menu_entry* entry = m->entries + menu_position;
+ if (entry->action_type == ACTION_SUBMENU) {
+ menu_stack.push(entry->action.submenu);
+ return NO_ACTION;
}
+ return entry->action.action;
}
int Device::HandleMenuKey(int key, int visible) {
@@ -86,8 +163,7 @@ int Device::HandleMenuKey(int key, int visible) {
case KEY_BACKSPACE:
case KEY_BACK:
- if (!ui_root_menu)
- return kGoBack;
+ return kGoBack;
default:
// If you have all of the above buttons, any other buttons
diff --git a/device.h b/device.h
index 1241982..dba4ac1 100644
--- a/device.h
+++ b/device.h
@@ -19,11 +19,15 @@
#include "ui.h"
+#include <stack>
+
#define KEY_FLAG_ABS 0x8000
+struct menu;
+
class Device : public VoldWatcher {
public:
- Device(RecoveryUI* ui) : ui_(ui) { }
+ explicit Device(RecoveryUI* ui);
virtual ~Device() { }
// Called to obtain the UI object that should be used to display
@@ -59,18 +63,17 @@ class Device : public VoldWatcher {
virtual int HandleMenuKey(int key, int visible);
enum BuiltinAction {
- NO_ACTION = 0,
- REBOOT = 1,
- APPLY_UPDATE = 2,
- // APPLY_CACHE was 3.
- // APPLY_ADB_SIDELOAD was 4.
- WIPE_DATA = 5,
- WIPE_CACHE = 6,
- WIPE_MEDIA = 7,
- REBOOT_BOOTLOADER = 8,
- SHUTDOWN = 9,
- VIEW_RECOVERY_LOGS = 10,
- MOUNT_SYSTEM = 11,
+ NO_ACTION,
+ REBOOT,
+ APPLY_UPDATE,
+ WIPE_DATA,
+ WIPE_FULL,
+ WIPE_CACHE,
+ REBOOT_RECOVERY,
+ REBOOT_BOOTLOADER,
+ SHUTDOWN,
+ VIEW_RECOVERY_LOGS,
+ MOUNT_SYSTEM,
};
// Return the list of menu items (an array of strings,
@@ -117,6 +120,8 @@ class Device : public VoldWatcher {
private:
RecoveryUI* ui_;
+
+ std::stack<const menu*> menu_stack;
};
// The device-specific library must define this function (or the
diff --git a/recovery.cpp b/recovery.cpp
index 5c9f43f..3ecd5db 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -1025,8 +1025,6 @@ refresh:
return status;
}
-int ui_root_menu = 0;
-
// Return REBOOT, SHUTDOWN, or REBOOT_BOOTLOADER. Returning NO_ACTION
// means to take the default, which is to reboot or shutdown depending
// on if the --shutdown_after flag was passed to recovery.
@@ -1034,7 +1032,6 @@ static Device::BuiltinAction
prompt_and_wait(Device* device, int status) {
for (;;) {
finish_recovery(NULL);
- ui_root_menu = 1;
switch (status) {
case INSTALL_SUCCESS:
case INSTALL_NONE:
@@ -1049,7 +1046,6 @@ prompt_and_wait(Device* device, int status) {
ui->SetProgressType(RecoveryUI::EMPTY);
int chosen_item = get_menu_selection(nullptr, device->GetMenuItems(), 0, 0, device);
- ui_root_menu = 0;
// device-specific code may take some action here. It may
// return one of the core actions handled in the switch
@@ -1064,6 +1060,7 @@ prompt_and_wait(Device* device, int status) {
case Device::REBOOT:
case Device::SHUTDOWN:
+ case Device::REBOOT_RECOVERY:
case Device::REBOOT_BOOTLOADER:
return chosen_action;
@@ -1072,13 +1069,13 @@ prompt_and_wait(Device* device, int status) {
if (!ui->IsTextVisible()) return Device::NO_ACTION;
break;
- case Device::WIPE_CACHE:
- wipe_cache(ui->IsTextVisible(), device);
+ case Device::WIPE_FULL:
+ wipe_data(ui->IsTextVisible(), device, true);
if (!ui->IsTextVisible()) return Device::NO_ACTION;
break;
- case Device::WIPE_MEDIA:
- wipe_media(ui->IsTextVisible(), device);
+ case Device::WIPE_CACHE:
+ wipe_cache(ui->IsTextVisible(), device);
if (!ui->IsTextVisible()) return Device::NO_ACTION;
break;
@@ -1516,6 +1513,11 @@ main(int argc, char **argv) {
property_set(ANDROID_RB_PROPERTY, "shutdown,");
break;
+ case Device::REBOOT_RECOVERY:
+ ui->Print("Rebooting recovery...\n");
+ property_set(ANDROID_RB_PROPERTY, "reboot,recovery");
+ break;
+
case Device::REBOOT_BOOTLOADER:
#ifdef DOWNLOAD_MODE
ui->Print("Rebooting to download mode...\n");