Merge "Add function to show localized rescue party menu"
This commit is contained in:
+6
-5
@@ -397,23 +397,22 @@ static bool wipe_data(Device* device) {
|
|||||||
|
|
||||||
static InstallResult prompt_and_wipe_data(Device* device) {
|
static InstallResult prompt_and_wipe_data(Device* device) {
|
||||||
// Use a single string and let ScreenRecoveryUI handles the wrapping.
|
// Use a single string and let ScreenRecoveryUI handles the wrapping.
|
||||||
std::vector<std::string> headers{
|
std::vector<std::string> wipe_data_menu_headers{
|
||||||
"Can't load Android system. Your data may be corrupt. "
|
"Can't load Android system. Your data may be corrupt. "
|
||||||
"If you continue to get this message, you may need to "
|
"If you continue to get this message, you may need to "
|
||||||
"perform a factory data reset and erase all user data "
|
"perform a factory data reset and erase all user data "
|
||||||
"stored on this device.",
|
"stored on this device.",
|
||||||
};
|
};
|
||||||
// clang-format off
|
// clang-format off
|
||||||
std::vector<std::string> items {
|
std::vector<std::string> wipe_data_menu_items {
|
||||||
"Try again",
|
"Try again",
|
||||||
"Factory data reset",
|
"Factory data reset",
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
for (;;) {
|
for (;;) {
|
||||||
size_t chosen_item = ui->ShowMenu(
|
size_t chosen_item = ui->ShowPromptWipeDataMenu(
|
||||||
headers, items, 0, true,
|
wipe_data_menu_headers, wipe_data_menu_items,
|
||||||
std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));
|
std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));
|
||||||
|
|
||||||
// If ShowMenu() returned RecoveryUI::KeyError::INTERRUPTED, WaitKey() was interrupted.
|
// If ShowMenu() returned RecoveryUI::KeyError::INTERRUPTED, WaitKey() was interrupted.
|
||||||
if (chosen_item == static_cast<size_t>(RecoveryUI::KeyError::INTERRUPTED)) {
|
if (chosen_item == static_cast<size_t>(RecoveryUI::KeyError::INTERRUPTED)) {
|
||||||
return INSTALL_KEY_INTERRUPTED;
|
return INSTALL_KEY_INTERRUPTED;
|
||||||
@@ -421,6 +420,8 @@ static InstallResult prompt_and_wipe_data(Device* device) {
|
|||||||
if (chosen_item != 1) {
|
if (chosen_item != 1) {
|
||||||
return INSTALL_SUCCESS; // Just reboot, no wipe; not a failure, user asked for it
|
return INSTALL_SUCCESS; // Just reboot, no wipe; not a failure, user asked for it
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(xunchang) localize the confirmation texts also.
|
||||||
if (ask_to_wipe_data(device)) {
|
if (ask_to_wipe_data(device)) {
|
||||||
if (wipe_data(device)) {
|
if (wipe_data(device)) {
|
||||||
return INSTALL_SUCCESS;
|
return INSTALL_SUCCESS;
|
||||||
|
|||||||
+91
-36
@@ -197,12 +197,9 @@ int TextMenu::DrawItems(int x, int y, int screen_width, bool long_press) const {
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphicMenu::GraphicMenu(size_t max_width, size_t max_height, GRSurface* graphic_headers,
|
GraphicMenu::GraphicMenu(GRSurface* graphic_headers, const std::vector<GRSurface*>& graphic_items,
|
||||||
const std::vector<GRSurface*>& graphic_items, size_t initial_selection,
|
size_t initial_selection, const DrawInterface& draw_funcs)
|
||||||
const DrawInterface& draw_funcs)
|
|
||||||
: Menu(initial_selection, draw_funcs),
|
: Menu(initial_selection, draw_funcs),
|
||||||
max_width_(max_width),
|
|
||||||
max_height_(max_height),
|
|
||||||
graphic_headers_(graphic_headers),
|
graphic_headers_(graphic_headers),
|
||||||
graphic_items_(graphic_items) {}
|
graphic_items_(graphic_items) {}
|
||||||
|
|
||||||
@@ -223,6 +220,7 @@ int GraphicMenu::Select(int sel) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int GraphicMenu::DrawHeader(int x, int y) const {
|
int GraphicMenu::DrawHeader(int x, int y) const {
|
||||||
|
draw_funcs_.SetColor(UIElement::HEADER);
|
||||||
draw_funcs_.DrawTextIcon(x, y, graphic_headers_);
|
draw_funcs_.DrawTextIcon(x, y, graphic_headers_);
|
||||||
return graphic_headers_->height;
|
return graphic_headers_->height;
|
||||||
}
|
}
|
||||||
@@ -253,15 +251,16 @@ int GraphicMenu::DrawItems(int x, int y, int screen_width, bool long_press) cons
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GraphicMenu::Validate() const {
|
bool GraphicMenu::Validate(size_t max_width, size_t max_height, GRSurface* graphic_headers,
|
||||||
|
const std::vector<GRSurface*>& graphic_items) {
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
if (!ValidateGraphicSurface(offset, graphic_headers_)) {
|
if (!ValidateGraphicSurface(max_width, max_height, offset, graphic_headers)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
offset += graphic_headers_->height;
|
offset += graphic_headers->height;
|
||||||
|
|
||||||
for (const auto& item : graphic_items_) {
|
for (const auto& item : graphic_items) {
|
||||||
if (!ValidateGraphicSurface(offset, item)) {
|
if (!ValidateGraphicSurface(max_width, max_height, offset, item)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
offset += item->height;
|
offset += item->height;
|
||||||
@@ -270,7 +269,8 @@ bool GraphicMenu::Validate() const {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GraphicMenu::ValidateGraphicSurface(int y, const GRSurface* surface) const {
|
bool GraphicMenu::ValidateGraphicSurface(size_t max_width, size_t max_height, int y,
|
||||||
|
const GRSurface* surface) {
|
||||||
if (!surface) {
|
if (!surface) {
|
||||||
fprintf(stderr, "Graphic surface can not be null");
|
fprintf(stderr, "Graphic surface can not be null");
|
||||||
return false;
|
return false;
|
||||||
@@ -282,11 +282,11 @@ bool GraphicMenu::ValidateGraphicSurface(int y, const GRSurface* surface) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface->width > max_width_ || surface->height > max_height_ - y) {
|
if (surface->width > max_width || surface->height > max_height - y) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Graphic surface doesn't fit into the screen. width: %d, height: %d, max_width: %zu,"
|
"Graphic surface doesn't fit into the screen. width: %d, height: %d, max_width: %zu,"
|
||||||
" max_height: %zu, vertical offset: %d\n",
|
" max_height: %zu, vertical offset: %d\n",
|
||||||
surface->width, surface->height, max_width_, max_height_, y);
|
surface->width, surface->height, max_width, max_height, y);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -697,7 +697,6 @@ void ScreenRecoveryUI::draw_menu_and_text_buffer_locked(
|
|||||||
const std::vector<std::string>& help_message) {
|
const std::vector<std::string>& help_message) {
|
||||||
int y = margin_height_;
|
int y = margin_height_;
|
||||||
if (menu_) {
|
if (menu_) {
|
||||||
static constexpr int kMenuIndent = 4;
|
|
||||||
int x = margin_width_ + kMenuIndent;
|
int x = margin_width_ + kMenuIndent;
|
||||||
|
|
||||||
SetColor(UIElement::INFO);
|
SetColor(UIElement::INFO);
|
||||||
@@ -836,6 +835,16 @@ bool ScreenRecoveryUI::InitTextParams() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(xunchang) load localized text icons for the menu. (Init for screenRecoveryUI but
|
||||||
|
// not wearRecoveryUI).
|
||||||
|
bool ScreenRecoveryUI::LoadWipeDataMenuText() {
|
||||||
|
wipe_data_menu_header_text_ = nullptr;
|
||||||
|
factory_data_reset_text_ = nullptr;
|
||||||
|
try_again_text_ = nullptr;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ScreenRecoveryUI::Init(const std::string& locale) {
|
bool ScreenRecoveryUI::Init(const std::string& locale) {
|
||||||
RecoveryUI::Init(locale);
|
RecoveryUI::Init(locale);
|
||||||
|
|
||||||
@@ -876,6 +885,8 @@ bool ScreenRecoveryUI::Init(const std::string& locale) {
|
|||||||
LoadLocalizedBitmap("no_command_text", &no_command_text);
|
LoadLocalizedBitmap("no_command_text", &no_command_text);
|
||||||
LoadLocalizedBitmap("error_text", &error_text);
|
LoadLocalizedBitmap("error_text", &error_text);
|
||||||
|
|
||||||
|
LoadWipeDataMenuText();
|
||||||
|
|
||||||
LoadAnimation();
|
LoadAnimation();
|
||||||
|
|
||||||
// Keep the progress bar updated, even when the process is otherwise busy.
|
// Keep the progress bar updated, even when the process is otherwise busy.
|
||||||
@@ -1104,14 +1115,36 @@ void ScreenRecoveryUI::ShowFile(const std::string& filename) {
|
|||||||
text_row_ = old_text_row;
|
text_row_ = old_text_row;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenRecoveryUI::StartMenu(const std::vector<std::string>& headers,
|
std::unique_ptr<Menu> ScreenRecoveryUI::CreateMenu(GRSurface* graphic_header,
|
||||||
const std::vector<std::string>& items, size_t initial_selection) {
|
const std::vector<GRSurface*>& graphic_items,
|
||||||
std::lock_guard<std::mutex> lg(updateMutex);
|
const std::vector<std::string>& text_headers,
|
||||||
if (text_rows_ > 0 && text_cols_ > 1) {
|
const std::vector<std::string>& text_items,
|
||||||
menu_ = std::make_unique<TextMenu>(scrollable_menu_, text_rows_, text_cols_ - 1, headers, items,
|
size_t initial_selection) const {
|
||||||
initial_selection, char_height_, *this);
|
// horizontal unusable area: margin width + menu indent
|
||||||
update_screen_locked();
|
size_t max_width = ScreenWidth() - margin_width_ - kMenuIndent;
|
||||||
|
// vertical unusable area: margin height + title lines + helper message + high light bar.
|
||||||
|
// It is safe to reserve more space.
|
||||||
|
size_t max_height = ScreenHeight() - margin_height_ - char_height_ * (title_lines_.size() + 3);
|
||||||
|
if (GraphicMenu::Validate(max_width, max_height, graphic_header, graphic_items)) {
|
||||||
|
return std::make_unique<GraphicMenu>(graphic_header, graphic_items, initial_selection, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Failed to initialize graphic menu, falling back to use the text menu.\n");
|
||||||
|
|
||||||
|
return CreateMenu(text_headers, text_items, initial_selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Menu> ScreenRecoveryUI::CreateMenu(const std::vector<std::string>& text_headers,
|
||||||
|
const std::vector<std::string>& text_items,
|
||||||
|
size_t initial_selection) const {
|
||||||
|
if (text_rows_ > 0 && text_cols_ > 1) {
|
||||||
|
return std::make_unique<TextMenu>(scrollable_menu_, text_rows_, text_cols_ - 1, text_headers,
|
||||||
|
text_items, initial_selection, char_height_, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Failed to create text menu, text_rows %zu, text_cols %zu.\n", text_rows_,
|
||||||
|
text_cols_);
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ScreenRecoveryUI::SelectMenu(int sel) {
|
int ScreenRecoveryUI::SelectMenu(int sel) {
|
||||||
@@ -1127,17 +1160,7 @@ int ScreenRecoveryUI::SelectMenu(int sel) {
|
|||||||
return sel;
|
return sel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenRecoveryUI::EndMenu() {
|
size_t ScreenRecoveryUI::ShowMenu(std::unique_ptr<Menu>&& menu, bool menu_only,
|
||||||
std::lock_guard<std::mutex> lg(updateMutex);
|
|
||||||
if (menu_) {
|
|
||||||
menu_.reset();
|
|
||||||
update_screen_locked();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
||||||
// Throw away keys pressed previously, so user doesn't accidentally trigger menu items.
|
// Throw away keys pressed previously, so user doesn't accidentally trigger menu items.
|
||||||
FlushKeys();
|
FlushKeys();
|
||||||
@@ -1146,9 +1169,13 @@ size_t ScreenRecoveryUI::ShowMenu(const std::vector<std::string>& headers,
|
|||||||
// menu.
|
// menu.
|
||||||
if (IsKeyInterrupted()) return static_cast<size_t>(KeyError::INTERRUPTED);
|
if (IsKeyInterrupted()) return static_cast<size_t>(KeyError::INTERRUPTED);
|
||||||
|
|
||||||
StartMenu(headers, items, initial_selection);
|
CHECK(menu != nullptr);
|
||||||
|
|
||||||
int selected = initial_selection;
|
// Starts and displays the menu
|
||||||
|
menu_ = std::move(menu);
|
||||||
|
Redraw();
|
||||||
|
|
||||||
|
int selected = menu_->selection();
|
||||||
int chosen_item = -1;
|
int chosen_item = -1;
|
||||||
while (chosen_item < 0) {
|
while (chosen_item < 0) {
|
||||||
int key = WaitKey();
|
int key = WaitKey();
|
||||||
@@ -1160,7 +1187,8 @@ size_t ScreenRecoveryUI::ShowMenu(const std::vector<std::string>& headers,
|
|||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
LOG(INFO) << "Timed out waiting for key input; rebooting.";
|
LOG(INFO) << "Timed out waiting for key input; rebooting.";
|
||||||
EndMenu();
|
menu_.reset();
|
||||||
|
Redraw();
|
||||||
return static_cast<size_t>(KeyError::TIMED_OUT);
|
return static_cast<size_t>(KeyError::TIMED_OUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1186,10 +1214,37 @@ size_t ScreenRecoveryUI::ShowMenu(const std::vector<std::string>& headers,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EndMenu();
|
menu_.reset();
|
||||||
|
Redraw();
|
||||||
|
|
||||||
return chosen_item;
|
return chosen_item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
auto menu = CreateMenu(headers, items, initial_selection);
|
||||||
|
if (menu == nullptr) {
|
||||||
|
return initial_selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ShowMenu(CreateMenu(headers, items, initial_selection), menu_only, key_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ScreenRecoveryUI::ShowPromptWipeDataMenu(const std::vector<std::string>& backup_headers,
|
||||||
|
const std::vector<std::string>& backup_items,
|
||||||
|
const std::function<int(int, bool)>& key_handler) {
|
||||||
|
auto wipe_data_menu =
|
||||||
|
CreateMenu(wipe_data_menu_header_text_, { try_again_text_, factory_data_reset_text_ },
|
||||||
|
backup_headers, backup_items, 0);
|
||||||
|
if (wipe_data_menu == nullptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ShowMenu(std::move(wipe_data_menu), true, key_handler);
|
||||||
|
}
|
||||||
|
|
||||||
bool ScreenRecoveryUI::IsTextVisible() {
|
bool ScreenRecoveryUI::IsTextVisible() {
|
||||||
std::lock_guard<std::mutex> lg(updateMutex);
|
std::lock_guard<std::mutex> lg(updateMutex);
|
||||||
int visible = show_text;
|
int visible = show_text;
|
||||||
|
|||||||
+40
-18
@@ -167,25 +167,23 @@ class GraphicMenu : public Menu {
|
|||||||
public:
|
public:
|
||||||
// Constructs a Menu instance with the given |headers|, |items| and properties. Sets the initial
|
// Constructs a Menu instance with the given |headers|, |items| and properties. Sets the initial
|
||||||
// selection to |initial_selection|.
|
// selection to |initial_selection|.
|
||||||
GraphicMenu(size_t max_width, size_t max_height, GRSurface* graphic_headers,
|
GraphicMenu(GRSurface* graphic_headers, const std::vector<GRSurface*>& graphic_items,
|
||||||
const std::vector<GRSurface*>& graphic_items, size_t initial_selection,
|
size_t initial_selection, const DrawInterface& draw_funcs);
|
||||||
const DrawInterface& draw_funcs);
|
|
||||||
|
|
||||||
int Select(int sel) override;
|
int Select(int sel) override;
|
||||||
int DrawHeader(int x, int y) const override;
|
int DrawHeader(int x, int y) const override;
|
||||||
int DrawItems(int x, int y, int screen_width, bool long_press) const override;
|
int DrawItems(int x, int y, int screen_width, bool long_press) const override;
|
||||||
|
|
||||||
// Checks if all the header and items are valid GRSurfaces; and that they can fit in the area
|
// Checks if all the header and items are valid GRSurfaces; and that they can fit in the area
|
||||||
// defined by |max_width_| and |max_height_|.
|
// defined by |max_width| and |max_height|.
|
||||||
bool Validate() const;
|
static bool Validate(size_t max_width, size_t max_height, GRSurface* graphic_headers,
|
||||||
|
const std::vector<GRSurface*>& graphic_items);
|
||||||
|
|
||||||
|
// Returns true if |surface| fits on the screen with a vertical offset |y|.
|
||||||
|
static bool ValidateGraphicSurface(size_t max_width, size_t max_height, int y,
|
||||||
|
const GRSurface* surface);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Returns true if |surface| fits on the screen with a vertical offset |y|.
|
|
||||||
bool ValidateGraphicSurface(int y, const GRSurface* surface) const;
|
|
||||||
|
|
||||||
const size_t max_width_;
|
|
||||||
const size_t max_height_;
|
|
||||||
|
|
||||||
// Pointers to the menu headers and items in graphic icons. This class does not have the ownership
|
// Pointers to the menu headers and items in graphic icons. This class does not have the ownership
|
||||||
// of the these objects.
|
// of the these objects.
|
||||||
GRSurface* graphic_headers_;
|
GRSurface* graphic_headers_;
|
||||||
@@ -238,7 +236,13 @@ class ScreenRecoveryUI : public RecoveryUI, public DrawInterface {
|
|||||||
// the on-device resource files and shows the localized text, for manual inspection.
|
// the on-device resource files and shows the localized text, for manual inspection.
|
||||||
void CheckBackgroundTextImages();
|
void CheckBackgroundTextImages();
|
||||||
|
|
||||||
|
// Displays the localized wipe data menu.
|
||||||
|
size_t ShowPromptWipeDataMenu(const std::vector<std::string>& backup_headers,
|
||||||
|
const std::vector<std::string>& backup_items,
|
||||||
|
const std::function<int(int, bool)>& key_handler) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static constexpr int kMenuIndent = 4;
|
||||||
// The margin that we don't want to use for showing texts (e.g. round screen, or screen with
|
// The margin that we don't want to use for showing texts (e.g. round screen, or screen with
|
||||||
// rounded corners).
|
// rounded corners).
|
||||||
const int margin_width_;
|
const int margin_width_;
|
||||||
@@ -252,18 +256,31 @@ class ScreenRecoveryUI : public RecoveryUI, public DrawInterface {
|
|||||||
|
|
||||||
virtual bool InitTextParams();
|
virtual bool InitTextParams();
|
||||||
|
|
||||||
// Displays some header text followed by a menu of items, which appears at the top of the screen
|
virtual bool LoadWipeDataMenuText();
|
||||||
// (in place of any scrolling ui_print() output, if necessary).
|
|
||||||
virtual void StartMenu(const std::vector<std::string>& headers,
|
// Creates a GraphicMenu with |graphic_header| and |graphic_items|. If the GraphicMenu isn't
|
||||||
const std::vector<std::string>& items, size_t initial_selection);
|
// valid or it doesn't fit on the screen; falls back to create a TextMenu instead. If succeeds,
|
||||||
|
// returns a unique pointer to the created menu; otherwise returns nullptr.
|
||||||
|
virtual std::unique_ptr<Menu> CreateMenu(GRSurface* graphic_header,
|
||||||
|
const std::vector<GRSurface*>& graphic_items,
|
||||||
|
const std::vector<std::string>& text_headers,
|
||||||
|
const std::vector<std::string>& text_items,
|
||||||
|
size_t initial_selection) const;
|
||||||
|
|
||||||
|
// Creates a TextMenu with |text_headers| and |text_items|; and sets the menu selection to
|
||||||
|
// |initial_selection|.
|
||||||
|
virtual std::unique_ptr<Menu> CreateMenu(const std::vector<std::string>& text_headers,
|
||||||
|
const std::vector<std::string>& text_items,
|
||||||
|
size_t initial_selection) const;
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
// Sets the menu highlight to the given index, wrapping if necessary. Returns the actual item
|
// Sets the menu highlight to the given index, wrapping if necessary. Returns the actual item
|
||||||
// selected.
|
// selected.
|
||||||
virtual int SelectMenu(int sel);
|
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();
|
||||||
@@ -318,6 +335,11 @@ class ScreenRecoveryUI : public RecoveryUI, public DrawInterface {
|
|||||||
GRSurface* installing_text;
|
GRSurface* installing_text;
|
||||||
GRSurface* no_command_text;
|
GRSurface* no_command_text;
|
||||||
|
|
||||||
|
// Graphs for the wipe data menu
|
||||||
|
GRSurface* wipe_data_menu_header_text_;
|
||||||
|
GRSurface* try_again_text_;
|
||||||
|
GRSurface* factory_data_reset_text_;
|
||||||
|
|
||||||
GRSurface** introFrames;
|
GRSurface** introFrames;
|
||||||
GRSurface** loopFrames;
|
GRSurface** loopFrames;
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,12 @@ class StubRecoveryUI : public RecoveryUI {
|
|||||||
return initial_selection;
|
return initial_selection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ShowPromptWipeDataMenu(const std::vector<std::string>& /* backup_headers */,
|
||||||
|
const std::vector<std::string>& /* backup_items */,
|
||||||
|
const std::function<int(int, bool)>& /* key_handle */) override {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void SetTitle(const std::vector<std::string>& /* lines */) override {}
|
void SetTitle(const std::vector<std::string>& /* lines */) override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -229,6 +229,43 @@ TEST_F(ScreenUITest, WearMenuSelectItemsOverflow) {
|
|||||||
ASSERT_EQ(3u, menu.MenuEnd());
|
ASSERT_EQ(3u, menu.MenuEnd());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ScreenUITest, GraphicMenuSelection) {
|
||||||
|
GRSurface fake_surface = GRSurface{ 50, 50, 50, 1, nullptr };
|
||||||
|
std::vector<GRSurface*> items = { &fake_surface, &fake_surface, &fake_surface };
|
||||||
|
GraphicMenu menu(&fake_surface, items, 0, draw_funcs_);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, menu.selection());
|
||||||
|
|
||||||
|
int sel = 0;
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
sel = menu.Select(++sel);
|
||||||
|
ASSERT_EQ((i + 1) % 3, sel);
|
||||||
|
ASSERT_EQ(sel, menu.selection());
|
||||||
|
}
|
||||||
|
|
||||||
|
sel = 0;
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
sel = menu.Select(--sel);
|
||||||
|
ASSERT_EQ(2 - i, sel);
|
||||||
|
ASSERT_EQ(sel, menu.selection());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ScreenUITest, GraphicMenuValidate) {
|
||||||
|
auto fake_surface = GRSurface{ 50, 50, 50, 1, nullptr };
|
||||||
|
std::vector<GRSurface*> items = { &fake_surface, &fake_surface, &fake_surface };
|
||||||
|
|
||||||
|
ASSERT_TRUE(GraphicMenu::Validate(200, 200, &fake_surface, items));
|
||||||
|
|
||||||
|
// Menu exceeds the horizontal boundary.
|
||||||
|
auto wide_surface = GRSurface{ 300, 50, 300, 1, nullptr };
|
||||||
|
ASSERT_FALSE(GraphicMenu::Validate(299, 200, &wide_surface, items));
|
||||||
|
|
||||||
|
// Menu exceeds the vertical boundary.
|
||||||
|
items.push_back(&fake_surface);
|
||||||
|
ASSERT_FALSE(GraphicMenu::Validate(200, 249, &fake_surface, items));
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr int kMagicAction = 101;
|
static constexpr int kMagicAction = 101;
|
||||||
|
|
||||||
enum class KeyCode : int {
|
enum class KeyCode : int {
|
||||||
|
|||||||
@@ -162,6 +162,13 @@ class RecoveryUI {
|
|||||||
const std::vector<std::string>& items, size_t initial_selection,
|
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) = 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
|
||||||
|
// selection is the 0th item in the menu, which is expected to reboot the device without a wipe.
|
||||||
|
virtual size_t ShowPromptWipeDataMenu(const std::vector<std::string>& backup_headers,
|
||||||
|
const std::vector<std::string>& backup_items,
|
||||||
|
const std::function<int(int, bool)>& key_handler) = 0;
|
||||||
|
|
||||||
// Resets the key interrupt status.
|
// Resets the key interrupt status.
|
||||||
void ResetKeyInterruptStatus() {
|
void ResetKeyInterruptStatus() {
|
||||||
key_interrupted_ = false;
|
key_interrupted_ = false;
|
||||||
|
|||||||
+8
-7
@@ -95,13 +95,14 @@ void WearRecoveryUI::update_progress_locked() {
|
|||||||
|
|
||||||
void WearRecoveryUI::SetStage(int /* current */, int /* max */) {}
|
void WearRecoveryUI::SetStage(int /* current */, int /* max */) {}
|
||||||
|
|
||||||
void WearRecoveryUI::StartMenu(const std::vector<std::string>& headers,
|
std::unique_ptr<Menu> WearRecoveryUI::CreateMenu(const std::vector<std::string>& text_headers,
|
||||||
const std::vector<std::string>& items, size_t initial_selection) {
|
const std::vector<std::string>& text_items,
|
||||||
std::lock_guard<std::mutex> lg(updateMutex);
|
size_t initial_selection) const {
|
||||||
if (text_rows_ > 0 && text_cols_ > 0) {
|
if (text_rows_ > 0 && text_cols_ > 0) {
|
||||||
menu_ = std::make_unique<TextMenu>(scrollable_menu_, text_rows_ - menu_unusable_rows_ - 1,
|
return std::make_unique<TextMenu>(scrollable_menu_, text_rows_ - menu_unusable_rows_ - 1,
|
||||||
text_cols_ - 1, headers, items, initial_selection,
|
text_cols_ - 1, text_headers, text_items, initial_selection,
|
||||||
char_height_, *this);
|
char_height_, *this);
|
||||||
update_screen_locked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,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 menu_unusable_rows_;
|
const int menu_unusable_rows_;
|
||||||
|
|
||||||
void StartMenu(const std::vector<std::string>& headers, const std::vector<std::string>& items,
|
std::unique_ptr<Menu> CreateMenu(const std::vector<std::string>& text_headers,
|
||||||
size_t initial_selection) override;
|
const std::vector<std::string>& text_items,
|
||||||
|
size_t initial_selection) const override;
|
||||||
|
|
||||||
int GetProgressBaseline() const override;
|
int GetProgressBaseline() const override;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user