Merge "Add ScreenRecoveryUI::ShowMenu()."
am: cac3ec3513
Change-Id: Iaad9bc980d8db3a02dbae77af234cf1aefccdbd1
This commit is contained in:
80
recovery.cpp
80
recovery.cpp
@@ -37,6 +37,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -495,57 +496,6 @@ static bool erase_volume(const char* volume) {
|
|||||||
return (result == 0);
|
return (result == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display a menu with the specified 'headers' and 'items'. Device specific HandleMenuKey() may
|
|
||||||
// return a positive number beyond the given range. Caller sets 'menu_only' to true to ensure only
|
|
||||||
// a menu item gets selected. 'initial_selection' controls the initial cursor location. Returns the
|
|
||||||
// (non-negative) chosen item number, or -1 if timed out waiting for input.
|
|
||||||
static int get_menu_selection(const char* const* headers, const char* const* items, bool menu_only,
|
|
||||||
int initial_selection, Device* device) {
|
|
||||||
// Throw away keys pressed previously, so user doesn't accidentally trigger menu items.
|
|
||||||
ui->FlushKeys();
|
|
||||||
|
|
||||||
ui->StartMenu(headers, items, initial_selection);
|
|
||||||
|
|
||||||
int selected = initial_selection;
|
|
||||||
int chosen_item = -1;
|
|
||||||
while (chosen_item < 0) {
|
|
||||||
int key = ui->WaitKey();
|
|
||||||
if (key == -1) { // WaitKey() timed out.
|
|
||||||
if (ui->WasTextEverVisible()) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
LOG(INFO) << "Timed out waiting for key input; rebooting.";
|
|
||||||
ui->EndMenu();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool visible = ui->IsTextVisible();
|
|
||||||
int action = device->HandleMenuKey(key, visible);
|
|
||||||
|
|
||||||
if (action < 0) {
|
|
||||||
switch (action) {
|
|
||||||
case Device::kHighlightUp:
|
|
||||||
selected = ui->SelectMenu(--selected);
|
|
||||||
break;
|
|
||||||
case Device::kHighlightDown:
|
|
||||||
selected = ui->SelectMenu(++selected);
|
|
||||||
break;
|
|
||||||
case Device::kInvokeItem:
|
|
||||||
chosen_item = selected;
|
|
||||||
break;
|
|
||||||
case Device::kNoAction:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (!menu_only) {
|
|
||||||
chosen_item = action;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ui->EndMenu();
|
|
||||||
return chosen_item;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the selected filename, or an empty string.
|
// Returns the selected filename, or an empty string.
|
||||||
static std::string browse_directory(const std::string& path, Device* device) {
|
static std::string browse_directory(const std::string& path, Device* device) {
|
||||||
ensure_path_mounted(path.c_str());
|
ensure_path_mounted(path.c_str());
|
||||||
@@ -588,7 +538,9 @@ static std::string browse_directory(const std::string& path, Device* device) {
|
|||||||
|
|
||||||
int chosen_item = 0;
|
int chosen_item = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
chosen_item = get_menu_selection(headers, entries, true, chosen_item, device);
|
chosen_item = ui->ShowMenu(
|
||||||
|
headers, entries, chosen_item, true,
|
||||||
|
std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));
|
||||||
|
|
||||||
const std::string& item = zips[chosen_item];
|
const std::string& item = zips[chosen_item];
|
||||||
if (chosen_item == 0) {
|
if (chosen_item == 0) {
|
||||||
@@ -612,15 +564,17 @@ static std::string browse_directory(const std::string& path, Device* device) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool yes_no(Device* device, const char* question1, const char* question2) {
|
static bool yes_no(Device* device, const char* question1, const char* question2) {
|
||||||
const char* headers[] = { question1, question2, NULL };
|
const char* headers[] = { question1, question2, NULL };
|
||||||
const char* items[] = { " No", " Yes", NULL };
|
const char* items[] = { " No", " Yes", NULL };
|
||||||
|
|
||||||
int chosen_item = get_menu_selection(headers, items, true, 0, device);
|
int chosen_item = ui->ShowMenu(
|
||||||
return (chosen_item == 1);
|
headers, items, 0, true,
|
||||||
|
std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));
|
||||||
|
return (chosen_item == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ask_to_wipe_data(Device* device) {
|
static bool ask_to_wipe_data(Device* device) {
|
||||||
return yes_no(device, "Wipe all user data?", " THIS CAN NOT BE UNDONE!");
|
return yes_no(device, "Wipe all user data?", " THIS CAN NOT BE UNDONE!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true on success.
|
// Return true on success.
|
||||||
@@ -660,7 +614,9 @@ static bool prompt_and_wipe_data(Device* device) {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int chosen_item = get_menu_selection(headers, items, true, 0, device);
|
int chosen_item = ui->ShowMenu(
|
||||||
|
headers, items, 0, true,
|
||||||
|
std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));
|
||||||
if (chosen_item != 1) {
|
if (chosen_item != 1) {
|
||||||
return true; // Just reboot, no wipe; not a failure, user asked for it
|
return true; // Just reboot, no wipe; not a failure, user asked for it
|
||||||
}
|
}
|
||||||
@@ -859,7 +815,9 @@ static void choose_recovery_file(Device* device) {
|
|||||||
|
|
||||||
int chosen_item = 0;
|
int chosen_item = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
chosen_item = get_menu_selection(headers, menu_entries.data(), true, chosen_item, device);
|
chosen_item = ui->ShowMenu(
|
||||||
|
headers, menu_entries.data(), chosen_item, true,
|
||||||
|
std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));
|
||||||
if (entries[chosen_item] == "Back") break;
|
if (entries[chosen_item] == "Back") break;
|
||||||
|
|
||||||
ui->ShowFile(entries[chosen_item].c_str());
|
ui->ShowFile(entries[chosen_item].c_str());
|
||||||
@@ -1005,7 +963,9 @@ static Device::BuiltinAction prompt_and_wait(Device* device, int status) {
|
|||||||
}
|
}
|
||||||
ui->SetProgressType(RecoveryUI::EMPTY);
|
ui->SetProgressType(RecoveryUI::EMPTY);
|
||||||
|
|
||||||
int chosen_item = get_menu_selection(nullptr, device->GetMenuItems(), false, 0, device);
|
int chosen_item = ui->ShowMenu(
|
||||||
|
nullptr, device->GetMenuItems(), 0, false,
|
||||||
|
std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));
|
||||||
|
|
||||||
// Device-specific code may take some action here. It may return one of the core actions
|
// Device-specific code may take some action here. It may return one of the core actions
|
||||||
// handled in the switch statement below.
|
// handled in the switch statement below.
|
||||||
|
|||||||
@@ -1009,6 +1009,53 @@ void ScreenRecoveryUI::EndMenu() {
|
|||||||
pthread_mutex_unlock(&updateMutex);
|
pthread_mutex_unlock(&updateMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ScreenRecoveryUI::ShowMenu(const char* const* headers, const char* const* items,
|
||||||
|
int initial_selection, bool menu_only,
|
||||||
|
const std::function<int(int, bool)>& key_handler) {
|
||||||
|
// Throw away keys pressed previously, so user doesn't accidentally trigger menu items.
|
||||||
|
FlushKeys();
|
||||||
|
|
||||||
|
StartMenu(headers, items, initial_selection);
|
||||||
|
|
||||||
|
int selected = initial_selection;
|
||||||
|
int chosen_item = -1;
|
||||||
|
while (chosen_item < 0) {
|
||||||
|
int key = WaitKey();
|
||||||
|
if (key == -1) { // WaitKey() timed out.
|
||||||
|
if (WasTextEverVisible()) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
LOG(INFO) << "Timed out waiting for key input; rebooting.";
|
||||||
|
EndMenu();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool visible = IsTextVisible();
|
||||||
|
int action = key_handler(key, visible);
|
||||||
|
if (action < 0) {
|
||||||
|
switch (action) {
|
||||||
|
case Device::kHighlightUp:
|
||||||
|
selected = SelectMenu(--selected);
|
||||||
|
break;
|
||||||
|
case Device::kHighlightDown:
|
||||||
|
selected = SelectMenu(++selected);
|
||||||
|
break;
|
||||||
|
case Device::kInvokeItem:
|
||||||
|
chosen_item = selected;
|
||||||
|
break;
|
||||||
|
case Device::kNoAction:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (!menu_only) {
|
||||||
|
chosen_item = action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EndMenu();
|
||||||
|
return chosen_item;
|
||||||
|
}
|
||||||
|
|
||||||
bool ScreenRecoveryUI::IsTextVisible() {
|
bool ScreenRecoveryUI::IsTextVisible() {
|
||||||
pthread_mutex_lock(&updateMutex);
|
pthread_mutex_lock(&updateMutex);
|
||||||
int visible = show_text;
|
int visible = show_text;
|
||||||
|
|||||||
19
screen_ui.h
19
screen_ui.h
@@ -20,6 +20,7 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -135,10 +136,8 @@ class ScreenRecoveryUI : public RecoveryUI {
|
|||||||
void ShowFile(const char* filename) override;
|
void ShowFile(const char* filename) override;
|
||||||
|
|
||||||
// menu display
|
// menu display
|
||||||
void StartMenu(const char* const* headers, const char* const* items,
|
int ShowMenu(const char* const* headers, const char* const* items, int initial_selection,
|
||||||
int initial_selection) override;
|
bool menu_only, const std::function<int(int, bool)>& key_handler) override;
|
||||||
int SelectMenu(int sel) override;
|
|
||||||
void EndMenu() override;
|
|
||||||
|
|
||||||
void KeyLongPress(int) override;
|
void KeyLongPress(int) override;
|
||||||
|
|
||||||
@@ -164,6 +163,18 @@ class ScreenRecoveryUI : public RecoveryUI {
|
|||||||
|
|
||||||
virtual bool InitTextParams();
|
virtual bool InitTextParams();
|
||||||
|
|
||||||
|
// Displays some header text followed by a menu of items, which appears at the top of the screen
|
||||||
|
// (in place of any scrolling ui_print() output, if necessary).
|
||||||
|
virtual void StartMenu(const char* const* headers, const char* const* items,
|
||||||
|
int initial_selection);
|
||||||
|
|
||||||
|
// Sets the menu highlight to the given index, wrapping if necessary. Returns the actual item
|
||||||
|
// selected.
|
||||||
|
virtual int SelectMenu(int sel);
|
||||||
|
|
||||||
|
// Ends menu mode, resetting the text overlay so that ui_print() statements will be displayed.
|
||||||
|
virtual void EndMenu();
|
||||||
|
|
||||||
virtual void draw_background_locked();
|
virtual void draw_background_locked();
|
||||||
virtual void draw_foreground_locked();
|
virtual void draw_foreground_locked();
|
||||||
virtual void draw_screen_locked();
|
virtual void draw_screen_locked();
|
||||||
|
|||||||
@@ -54,12 +54,11 @@ class StubRecoveryUI : public RecoveryUI {
|
|||||||
void ShowFile(const char* /* filename */) override {}
|
void ShowFile(const char* /* filename */) override {}
|
||||||
|
|
||||||
// menu display
|
// menu display
|
||||||
void StartMenu(const char* const* /* headers */, const char* const* /* items */,
|
int ShowMenu(const char* const* /* headers */, const char* const* /* items */,
|
||||||
int /* initial_selection */) override {}
|
int initial_selection, bool /* menu_only */,
|
||||||
int SelectMenu(int sel) override {
|
const std::function<int(int, bool)>& /* key_handler */) override {
|
||||||
return sel;
|
return initial_selection;
|
||||||
}
|
}
|
||||||
void EndMenu() override {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // RECOVERY_STUB_UI_H
|
#endif // RECOVERY_STUB_UI_H
|
||||||
|
|||||||
24
ui.h
24
ui.h
@@ -21,6 +21,7 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
// Abstract class for controlling the user interface during recovery.
|
// Abstract class for controlling the user interface during recovery.
|
||||||
@@ -128,17 +129,18 @@ class RecoveryUI {
|
|||||||
|
|
||||||
// --- menu display ---
|
// --- menu display ---
|
||||||
|
|
||||||
// Display some header text followed by a menu of items, which appears at the top of the screen
|
// Displays a menu with the given 'headers' and 'items'. The supplied 'key_handler' callback,
|
||||||
// (in place of any scrolling ui_print() output, if necessary).
|
// which is typically bound to Device::HandleMenuKey(), should return the expected action for the
|
||||||
virtual void StartMenu(const char* const* headers, const char* const* items,
|
// given key code and menu visibility (e.g. to move the cursor or to select an item). Caller sets
|
||||||
int initial_selection) = 0;
|
// 'menu_only' to true to ensure only a menu item gets selected and returned. Otherwise if
|
||||||
|
// 'menu_only' is false, ShowMenu() will forward any non-negative value returned from the
|
||||||
// Sets the menu highlight to the given index, wrapping if necessary. Returns the actual item
|
// key_handler, which may be beyond the range of menu items. This could be used to trigger a
|
||||||
// selected.
|
// device-specific action, even without that being listed in the menu. Caller needs to handle
|
||||||
virtual int SelectMenu(int sel) = 0;
|
// such a case accordingly (e.g. by calling Device::InvokeMenuItem() to process the action).
|
||||||
|
// Returns a non-negative value (the chosen item number or device-specific action code), or -1 if
|
||||||
// Ends menu mode, resetting the text overlay so that ui_print() statements will be displayed.
|
// timed out waiting for input.
|
||||||
virtual void EndMenu() = 0;
|
virtual int ShowMenu(const char* const* headers, const char* const* items, int initial_selection,
|
||||||
|
bool menu_only, const std::function<int(int, bool)>& key_handler) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void EnqueueKey(int key_code);
|
void EnqueueKey(int key_code);
|
||||||
|
|||||||
@@ -25,9 +25,6 @@ class WearRecoveryUI : public ScreenRecoveryUI {
|
|||||||
|
|
||||||
void SetStage(int current, int max) override;
|
void SetStage(int current, int max) override;
|
||||||
|
|
||||||
void StartMenu(const char* const* headers, const char* const* items,
|
|
||||||
int initial_selection) override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// progress bar vertical position, it's centered horizontally
|
// progress bar vertical position, it's centered horizontally
|
||||||
const int kProgressBarBaseline;
|
const int kProgressBarBaseline;
|
||||||
@@ -36,6 +33,9 @@ class WearRecoveryUI : public ScreenRecoveryUI {
|
|||||||
// Recovery, build id and etc) and the bottom lines that may otherwise go out of the screen.
|
// Recovery, build id and etc) and the bottom lines that may otherwise go out of the screen.
|
||||||
const int kMenuUnusableRows;
|
const int kMenuUnusableRows;
|
||||||
|
|
||||||
|
void StartMenu(const char* const* headers, const char* const* items,
|
||||||
|
int initial_selection) override;
|
||||||
|
|
||||||
int GetProgressBaseline() const override;
|
int GetProgressBaseline() const override;
|
||||||
|
|
||||||
void update_progress_locked() override;
|
void update_progress_locked() override;
|
||||||
|
|||||||
Reference in New Issue
Block a user