Merge "Move menu headers/items to std::vector<std::string>." am: fb86bb2a07
am: 0d9ed29541
Change-Id: I7428f86e9bc3e46c5bcf0afeb3cf5608be31e470
This commit is contained in:
commit
3777c4b859
10 changed files with 147 additions and 141 deletions
29
device.cpp
29
device.cpp
|
@ -16,9 +16,13 @@
|
|||
|
||||
#include "device.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/macros.h>
|
||||
|
||||
#include "ui.h"
|
||||
|
||||
static const char* MENU_ITEMS[] = {
|
||||
// clang-format off
|
||||
static constexpr const char* kItems[]{
|
||||
"Reboot system now",
|
||||
"Reboot to bootloader",
|
||||
"Apply update from ADB",
|
||||
|
@ -32,10 +36,11 @@ static const char* MENU_ITEMS[] = {
|
|||
"Run graphics test",
|
||||
"Run locale test",
|
||||
"Power off",
|
||||
nullptr,
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
static const Device::BuiltinAction MENU_ACTIONS[] = {
|
||||
// clang-format off
|
||||
static constexpr Device::BuiltinAction kMenuActions[] {
|
||||
Device::REBOOT,
|
||||
Device::REBOOT_BOOTLOADER,
|
||||
Device::APPLY_ADB_SIDELOAD,
|
||||
|
@ -50,18 +55,20 @@ static const Device::BuiltinAction MENU_ACTIONS[] = {
|
|||
Device::RUN_LOCALE_TEST,
|
||||
Device::SHUTDOWN,
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
static_assert(sizeof(MENU_ITEMS) / sizeof(MENU_ITEMS[0]) ==
|
||||
sizeof(MENU_ACTIONS) / sizeof(MENU_ACTIONS[0]) + 1,
|
||||
"MENU_ITEMS and MENU_ACTIONS should have the same length, "
|
||||
"except for the extra NULL entry in MENU_ITEMS.");
|
||||
static_assert(arraysize(kItems) == arraysize(kMenuActions),
|
||||
"kItems and kMenuActions should have the same length.");
|
||||
|
||||
const char* const* Device::GetMenuItems() {
|
||||
return MENU_ITEMS;
|
||||
static const std::vector<std::string> kMenuItems(kItems, kItems + arraysize(kItems));
|
||||
|
||||
const std::vector<std::string>& Device::GetMenuItems() {
|
||||
return kMenuItems;
|
||||
}
|
||||
|
||||
Device::BuiltinAction Device::InvokeMenuItem(int menu_position) {
|
||||
return menu_position < 0 ? NO_ACTION : MENU_ACTIONS[menu_position];
|
||||
Device::BuiltinAction Device::InvokeMenuItem(size_t menu_position) {
|
||||
// CHECK_LT(menu_position, );
|
||||
return kMenuActions[menu_position];
|
||||
}
|
||||
|
||||
int Device::HandleMenuKey(int key, bool visible) {
|
||||
|
|
69
device.h
69
device.h
|
@ -17,11 +17,37 @@
|
|||
#ifndef _RECOVERY_DEVICE_H
|
||||
#define _RECOVERY_DEVICE_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Forward declaration to avoid including "ui.h".
|
||||
class RecoveryUI;
|
||||
|
||||
class Device {
|
||||
public:
|
||||
static constexpr const int kNoAction = -1;
|
||||
static constexpr const int kHighlightUp = -2;
|
||||
static constexpr const int kHighlightDown = -3;
|
||||
static constexpr const int kInvokeItem = -4;
|
||||
|
||||
enum BuiltinAction {
|
||||
NO_ACTION = 0,
|
||||
REBOOT = 1,
|
||||
APPLY_SDCARD = 2,
|
||||
// APPLY_CACHE was 3.
|
||||
APPLY_ADB_SIDELOAD = 4,
|
||||
WIPE_DATA = 5,
|
||||
WIPE_CACHE = 6,
|
||||
REBOOT_BOOTLOADER = 7,
|
||||
SHUTDOWN = 8,
|
||||
VIEW_RECOVERY_LOGS = 9,
|
||||
MOUNT_SYSTEM = 10,
|
||||
RUN_GRAPHICS_TEST = 11,
|
||||
RUN_LOCALE_TEST = 12,
|
||||
};
|
||||
|
||||
explicit Device(RecoveryUI* ui) : ui_(ui) {}
|
||||
virtual ~Device() {}
|
||||
|
||||
|
@ -48,44 +74,23 @@ class Device {
|
|||
//
|
||||
// Returns one of the defined constants below in order to:
|
||||
//
|
||||
// - move the menu highlight (kHighlight{Up,Down})
|
||||
// - invoke the highlighted item (kInvokeItem)
|
||||
// - do nothing (kNoAction)
|
||||
// - invoke a specific action (a menu position: any non-negative number)
|
||||
// - move the menu highlight (kHighlight{Up,Down}: negative value)
|
||||
// - invoke the highlighted item (kInvokeItem: negative value)
|
||||
// - do nothing (kNoAction: negative value)
|
||||
// - invoke a specific action (a menu position: non-negative value)
|
||||
virtual int HandleMenuKey(int key, bool visible);
|
||||
|
||||
enum BuiltinAction {
|
||||
NO_ACTION = 0,
|
||||
REBOOT = 1,
|
||||
APPLY_SDCARD = 2,
|
||||
// APPLY_CACHE was 3.
|
||||
APPLY_ADB_SIDELOAD = 4,
|
||||
WIPE_DATA = 5,
|
||||
WIPE_CACHE = 6,
|
||||
REBOOT_BOOTLOADER = 7,
|
||||
SHUTDOWN = 8,
|
||||
VIEW_RECOVERY_LOGS = 9,
|
||||
MOUNT_SYSTEM = 10,
|
||||
RUN_GRAPHICS_TEST = 11,
|
||||
RUN_LOCALE_TEST = 12,
|
||||
};
|
||||
// Returns the list of 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();
|
||||
|
||||
// Return the list of menu items (an array of strings, NULL-terminated). The menu_position passed
|
||||
// to InvokeMenuItem will correspond to the indexes into this array.
|
||||
virtual const char* const* GetMenuItems();
|
||||
|
||||
// Perform a recovery action selected from the menu. 'menu_position' will be the item number of
|
||||
// the selected menu item, or a non-negative number returned from HandleMenuKey(). The menu will
|
||||
// be hidden when this is called; implementations can call ui_print() to print information to the
|
||||
// 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 ui_print() to print information to the
|
||||
// screen. If the menu position is one of the builtin actions, you can just return the
|
||||
// corresponding enum value. If it is an action specific to your device, you actually perform it
|
||||
// here and return NO_ACTION.
|
||||
virtual BuiltinAction InvokeMenuItem(int menu_position);
|
||||
|
||||
static const int kNoAction = -1;
|
||||
static const int kHighlightUp = -2;
|
||||
static const int kHighlightDown = -3;
|
||||
static const int kInvokeItem = -4;
|
||||
virtual BuiltinAction InvokeMenuItem(size_t menu_position);
|
||||
|
||||
// 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
|
||||
|
|
58
recovery.cpp
58
recovery.cpp
|
@ -507,7 +507,7 @@ static std::string browse_directory(const std::string& path, Device* device) {
|
|||
}
|
||||
|
||||
std::vector<std::string> dirs;
|
||||
std::vector<std::string> zips = { "../" }; // "../" is always the first entry.
|
||||
std::vector<std::string> entries{ "../" }; // "../" is always the first entry.
|
||||
|
||||
dirent* de;
|
||||
while ((de = readdir(d.get())) != nullptr) {
|
||||
|
@ -518,31 +518,25 @@ static std::string browse_directory(const std::string& path, Device* device) {
|
|||
if (name == "." || name == "..") continue;
|
||||
dirs.push_back(name + "/");
|
||||
} else if (de->d_type == DT_REG && android::base::EndsWithIgnoreCase(name, ".zip")) {
|
||||
zips.push_back(name);
|
||||
entries.push_back(name);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(dirs.begin(), dirs.end());
|
||||
std::sort(zips.begin(), zips.end());
|
||||
std::sort(entries.begin(), entries.end());
|
||||
|
||||
// Append dirs to the zips list.
|
||||
zips.insert(zips.end(), dirs.begin(), dirs.end());
|
||||
// Append dirs to the entries list.
|
||||
entries.insert(entries.end(), dirs.begin(), dirs.end());
|
||||
|
||||
const char* entries[zips.size() + 1];
|
||||
entries[zips.size()] = nullptr;
|
||||
for (size_t i = 0; i < zips.size(); i++) {
|
||||
entries[i] = zips[i].c_str();
|
||||
}
|
||||
std::vector<std::string> headers{ "Choose a package to install:", path };
|
||||
|
||||
const char* headers[] = { "Choose a package to install:", path.c_str(), nullptr };
|
||||
|
||||
int chosen_item = 0;
|
||||
size_t chosen_item = 0;
|
||||
while (true) {
|
||||
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 = entries[chosen_item];
|
||||
if (chosen_item == 0) {
|
||||
// Go up but continue browsing (if the caller is browse_directory).
|
||||
return "";
|
||||
|
@ -564,10 +558,10 @@ static std::string browse_directory(const std::string& path, Device* device) {
|
|||
}
|
||||
|
||||
static bool yes_no(Device* device, const char* question1, const char* question2) {
|
||||
const char* headers[] = { question1, question2, NULL };
|
||||
const char* items[] = { " No", " Yes", NULL };
|
||||
std::vector<std::string> headers{ question1, question2 };
|
||||
std::vector<std::string> items{ " No", " Yes" };
|
||||
|
||||
int chosen_item = ui->ShowMenu(
|
||||
size_t chosen_item = ui->ShowMenu(
|
||||
headers, items, 0, true,
|
||||
std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));
|
||||
return (chosen_item == 1);
|
||||
|
@ -601,20 +595,20 @@ static bool wipe_data(Device* device) {
|
|||
|
||||
static bool prompt_and_wipe_data(Device* device) {
|
||||
// Use a single string and let ScreenRecoveryUI handles the wrapping.
|
||||
const char* const headers[] = {
|
||||
std::vector<std::string> headers{
|
||||
"Can't load Android system. Your data may be corrupt. "
|
||||
"If you continue to get this message, you may need to "
|
||||
"perform a factory data reset and erase all user data "
|
||||
"stored on this device.",
|
||||
nullptr
|
||||
};
|
||||
const char* const items[] = {
|
||||
// clang-format off
|
||||
std::vector<std::string> items {
|
||||
"Try again",
|
||||
"Factory data reset",
|
||||
NULL
|
||||
};
|
||||
// clang-format on
|
||||
for (;;) {
|
||||
int chosen_item = ui->ShowMenu(
|
||||
size_t chosen_item = ui->ShowMenu(
|
||||
headers, items, 0, true,
|
||||
std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));
|
||||
if (chosen_item != 1) {
|
||||
|
@ -806,17 +800,12 @@ static void choose_recovery_file(Device* device) {
|
|||
|
||||
entries.push_back("Back");
|
||||
|
||||
std::vector<const char*> menu_entries(entries.size());
|
||||
std::transform(entries.cbegin(), entries.cend(), menu_entries.begin(),
|
||||
[](const std::string& entry) { return entry.c_str(); });
|
||||
menu_entries.push_back(nullptr);
|
||||
std::vector<std::string> headers{ "Select file to view" };
|
||||
|
||||
const char* headers[] = { "Select file to view", nullptr };
|
||||
|
||||
int chosen_item = 0;
|
||||
size_t chosen_item = 0;
|
||||
while (true) {
|
||||
chosen_item = ui->ShowMenu(
|
||||
headers, menu_entries.data(), chosen_item, true,
|
||||
headers, entries, chosen_item, true,
|
||||
std::bind(&Device::HandleMenuKey, device, std::placeholders::_1, std::placeholders::_2));
|
||||
if (entries[chosen_item] == "Back") break;
|
||||
|
||||
|
@ -963,14 +952,15 @@ static Device::BuiltinAction prompt_and_wait(Device* device, int status) {
|
|||
}
|
||||
ui->SetProgressType(RecoveryUI::EMPTY);
|
||||
|
||||
int chosen_item = ui->ShowMenu(
|
||||
nullptr, device->GetMenuItems(), 0, false,
|
||||
size_t chosen_item = ui->ShowMenu(
|
||||
{}, 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
|
||||
// handled in the switch statement below.
|
||||
Device::BuiltinAction chosen_action =
|
||||
(chosen_item == -1) ? Device::REBOOT : device->InvokeMenuItem(chosen_item);
|
||||
Device::BuiltinAction chosen_action = (chosen_item == static_cast<size_t>(-1))
|
||||
? Device::REBOOT
|
||||
: device->InvokeMenuItem(chosen_item);
|
||||
|
||||
bool should_wipe_cache = false;
|
||||
switch (chosen_action) {
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
@ -52,8 +53,9 @@ static double now() {
|
|||
return tv.tv_sec + tv.tv_usec / 1000000.0;
|
||||
}
|
||||
|
||||
Menu::Menu(bool scrollable, size_t max_items, size_t max_length, const char* const* headers,
|
||||
const char* const* items, int initial_selection)
|
||||
Menu::Menu(bool scrollable, size_t max_items, size_t max_length,
|
||||
const std::vector<std::string>& headers, const std::vector<std::string>& items,
|
||||
size_t initial_selection)
|
||||
: scrollable_(scrollable),
|
||||
max_display_items_(max_items),
|
||||
max_item_length_(max_length),
|
||||
|
@ -63,15 +65,15 @@ Menu::Menu(bool scrollable, size_t max_items, size_t max_length, const char* con
|
|||
CHECK_LE(max_items, static_cast<size_t>(std::numeric_limits<int>::max()));
|
||||
|
||||
// It's fine to have more entries than text_rows_ if scrollable menu is supported.
|
||||
size_t max_items_count = scrollable_ ? std::numeric_limits<int>::max() : max_display_items_;
|
||||
for (size_t i = 0; i < max_items_count && items[i] != nullptr; ++i) {
|
||||
text_items_.emplace_back(items[i], strnlen(items[i], max_item_length_));
|
||||
size_t items_count = scrollable_ ? items.size() : std::min(items.size(), max_display_items_);
|
||||
for (size_t i = 0; i < items_count; ++i) {
|
||||
text_items_.emplace_back(items[i].substr(0, max_item_length_));
|
||||
}
|
||||
|
||||
CHECK(!text_items_.empty());
|
||||
}
|
||||
|
||||
const char* const* Menu::text_headers() const {
|
||||
const std::vector<std::string>& Menu::text_headers() const {
|
||||
return text_headers_;
|
||||
}
|
||||
|
||||
|
@ -99,7 +101,7 @@ bool Menu::ItemsOverflow(std::string* cur_selection_str) const {
|
|||
}
|
||||
|
||||
*cur_selection_str =
|
||||
android::base::StringPrintf("Current item: %d/%zu", selection_ + 1, ItemsCount());
|
||||
android::base::StringPrintf("Current item: %zu/%zu", selection_ + 1, ItemsCount());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -503,10 +505,10 @@ void ScreenRecoveryUI::draw_screen_locked() {
|
|||
gr_clear();
|
||||
|
||||
// clang-format off
|
||||
static std::vector<std::string> REGULAR_HELP = {
|
||||
static std::vector<std::string> REGULAR_HELP{
|
||||
"Use volume up/down and power.",
|
||||
};
|
||||
static std::vector<std::string> LONG_PRESS_HELP = {
|
||||
static std::vector<std::string> LONG_PRESS_HELP{
|
||||
"Any button cycles highlight.",
|
||||
"Long-press activates.",
|
||||
};
|
||||
|
@ -532,22 +534,12 @@ void ScreenRecoveryUI::draw_menu_and_text_buffer_locked(
|
|||
|
||||
y += DrawTextLines(x, y, help_message);
|
||||
|
||||
auto convert_to_vector = [](const char* const* items) -> std::vector<std::string> {
|
||||
if (items == nullptr) return {};
|
||||
|
||||
std::vector<std::string> result;
|
||||
for (size_t i = 0; items[i] != nullptr; ++i) {
|
||||
result.emplace_back(items[i]);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
// Draw menu header.
|
||||
SetColor(HEADER);
|
||||
if (!menu_->scrollable()) {
|
||||
y += DrawWrappedTextLines(x, y, convert_to_vector(menu_->text_headers()));
|
||||
y += DrawWrappedTextLines(x, y, menu_->text_headers());
|
||||
} else {
|
||||
y += DrawTextLines(x, y, convert_to_vector(menu_->text_headers()));
|
||||
y += DrawTextLines(x, y, menu_->text_headers());
|
||||
// Show the current menu item number in relation to total number if items don't fit on the
|
||||
// screen.
|
||||
std::string cur_selection_str;
|
||||
|
@ -979,8 +971,8 @@ void ScreenRecoveryUI::ShowFile(const std::string& filename) {
|
|||
text_row_ = old_text_row;
|
||||
}
|
||||
|
||||
void ScreenRecoveryUI::StartMenu(const char* const* headers, const char* const* items,
|
||||
int initial_selection) {
|
||||
void ScreenRecoveryUI::StartMenu(const std::vector<std::string>& headers,
|
||||
const std::vector<std::string>& items, size_t initial_selection) {
|
||||
pthread_mutex_lock(&updateMutex);
|
||||
if (text_rows_ > 0 && text_cols_ > 1) {
|
||||
menu_ = std::make_unique<Menu>(scrollable_menu_, text_rows_, text_cols_ - 1, headers, items,
|
||||
|
@ -1013,9 +1005,10 @@ void ScreenRecoveryUI::EndMenu() {
|
|||
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) {
|
||||
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) {
|
||||
// Throw away keys pressed previously, so user doesn't accidentally trigger menu items.
|
||||
FlushKeys();
|
||||
|
||||
|
@ -1031,7 +1024,7 @@ int ScreenRecoveryUI::ShowMenu(const char* const* headers, const char* const* it
|
|||
} else {
|
||||
LOG(INFO) << "Timed out waiting for key input; rebooting.";
|
||||
EndMenu();
|
||||
return -1;
|
||||
return static_cast<size_t>(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
27
screen_ui.h
27
screen_ui.h
|
@ -35,14 +35,15 @@ class Menu {
|
|||
public:
|
||||
// Constructs a Menu instance with the given |headers|, |items| and properties. Sets the initial
|
||||
// selection to |initial_selection|.
|
||||
Menu(bool scrollable, size_t max_items, size_t max_length, const char* const* headers,
|
||||
const char* const* items, int initial_selection);
|
||||
Menu(bool scrollable, size_t max_items, size_t max_length,
|
||||
const std::vector<std::string>& headers, const std::vector<std::string>& items,
|
||||
size_t initial_selection);
|
||||
|
||||
bool scrollable() const {
|
||||
return scrollable_;
|
||||
}
|
||||
|
||||
int selection() const {
|
||||
size_t selection() const {
|
||||
return selection_;
|
||||
}
|
||||
|
||||
|
@ -66,7 +67,7 @@ class Menu {
|
|||
// /cache/recovery/last_log.1
|
||||
// /cache/recovery/last_log.2
|
||||
// ...
|
||||
const char* const* text_headers() const;
|
||||
const std::vector<std::string>& text_headers() const;
|
||||
std::string TextItem(size_t index) const;
|
||||
|
||||
// Checks if the menu items fit vertically on the screen. Returns true and set the
|
||||
|
@ -84,15 +85,14 @@ class Menu {
|
|||
const size_t max_display_items_;
|
||||
// The length of each item to fit horizontally on a screen.
|
||||
const size_t max_item_length_;
|
||||
|
||||
// Internal storage for the menu headers and items in text.
|
||||
const char* const* text_headers_;
|
||||
// The menu headers.
|
||||
std::vector<std::string> text_headers_;
|
||||
// The actual menu items trimmed to fit the given properties.
|
||||
std::vector<std::string> text_items_;
|
||||
|
||||
// The first item to display on the screen.
|
||||
size_t menu_start_;
|
||||
// Current menu selection.
|
||||
int selection_;
|
||||
size_t selection_;
|
||||
};
|
||||
|
||||
// Implementation of RecoveryUI appropriate for devices with a screen
|
||||
|
@ -137,8 +137,9 @@ class ScreenRecoveryUI : public RecoveryUI {
|
|||
void ShowFile(const std::string& filename) override;
|
||||
|
||||
// menu display
|
||||
int ShowMenu(const char* const* headers, const char* const* items, int initial_selection,
|
||||
bool menu_only, const std::function<int(int, bool)>& key_handler) override;
|
||||
size_t 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) override;
|
||||
|
||||
void KeyLongPress(int) override;
|
||||
|
||||
|
@ -166,8 +167,8 @@ class ScreenRecoveryUI : public RecoveryUI {
|
|||
|
||||
// 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);
|
||||
virtual void StartMenu(const std::vector<std::string>& headers,
|
||||
const std::vector<std::string>& items, size_t initial_selection);
|
||||
|
||||
// Sets the menu highlight to the given index, wrapping if necessary. Returns the actual item
|
||||
// selected.
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "ui.h"
|
||||
|
||||
|
@ -57,9 +58,10 @@ class StubRecoveryUI : public RecoveryUI {
|
|||
void ShowFile(const std::string& /* filename */) override {}
|
||||
|
||||
// menu display
|
||||
int ShowMenu(const char* const* /* headers */, const char* const* /* items */,
|
||||
int initial_selection, bool /* menu_only */,
|
||||
const std::function<int(int, bool)>& /* key_handler */) override {
|
||||
size_t 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 */) override {
|
||||
return initial_selection;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -14,19 +14,22 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "screen_ui.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
constexpr const char* HEADER[] = { "header", nullptr };
|
||||
constexpr const char* ITEMS[] = { "items1", "items2", "items3", "items4", "1234567890", nullptr };
|
||||
#include "screen_ui.h"
|
||||
|
||||
static const std::vector<std::string> HEADERS{ "header" };
|
||||
static const std::vector<std::string> ITEMS{ "item1", "item2", "item3", "item4", "1234567890" };
|
||||
|
||||
TEST(ScreenUITest, StartPhoneMenuSmoke) {
|
||||
Menu menu(false, 10, 20, HEADER, ITEMS, 0);
|
||||
Menu menu(false, 10, 20, HEADERS, ITEMS, 0);
|
||||
ASSERT_FALSE(menu.scrollable());
|
||||
ASSERT_EQ(HEADER[0], menu.text_headers()[0]);
|
||||
ASSERT_EQ(HEADERS[0], menu.text_headers()[0]);
|
||||
ASSERT_EQ(5u, menu.ItemsCount());
|
||||
|
||||
std::string message;
|
||||
|
@ -39,9 +42,9 @@ TEST(ScreenUITest, StartPhoneMenuSmoke) {
|
|||
}
|
||||
|
||||
TEST(ScreenUITest, StartWearMenuSmoke) {
|
||||
Menu menu(true, 10, 8, HEADER, ITEMS, 1);
|
||||
Menu menu(true, 10, 8, HEADERS, ITEMS, 1);
|
||||
ASSERT_TRUE(menu.scrollable());
|
||||
ASSERT_EQ(HEADER[0], menu.text_headers()[0]);
|
||||
ASSERT_EQ(HEADERS[0], menu.text_headers()[0]);
|
||||
ASSERT_EQ(5u, menu.ItemsCount());
|
||||
|
||||
std::string message;
|
||||
|
@ -55,7 +58,7 @@ TEST(ScreenUITest, StartWearMenuSmoke) {
|
|||
}
|
||||
|
||||
TEST(ScreenUITest, StartPhoneMenuItemsOverflow) {
|
||||
Menu menu(false, 1, 20, HEADER, ITEMS, 0);
|
||||
Menu menu(false, 1, 20, HEADERS, ITEMS, 0);
|
||||
ASSERT_FALSE(menu.scrollable());
|
||||
ASSERT_EQ(1u, menu.ItemsCount());
|
||||
|
||||
|
@ -70,7 +73,7 @@ TEST(ScreenUITest, StartPhoneMenuItemsOverflow) {
|
|||
}
|
||||
|
||||
TEST(ScreenUITest, StartWearMenuItemsOverflow) {
|
||||
Menu menu(true, 1, 20, HEADER, ITEMS, 0);
|
||||
Menu menu(true, 1, 20, HEADERS, ITEMS, 0);
|
||||
ASSERT_TRUE(menu.scrollable());
|
||||
ASSERT_EQ(5u, menu.ItemsCount());
|
||||
|
||||
|
@ -88,7 +91,7 @@ TEST(ScreenUITest, StartWearMenuItemsOverflow) {
|
|||
|
||||
TEST(ScreenUITest, PhoneMenuSelectSmoke) {
|
||||
int sel = 0;
|
||||
Menu menu(false, 10, 20, HEADER, ITEMS, sel);
|
||||
Menu menu(false, 10, 20, HEADERS, ITEMS, sel);
|
||||
// Mimic down button 10 times (2 * items size)
|
||||
for (int i = 0; i < 10; i++) {
|
||||
sel = menu.Select(++sel);
|
||||
|
@ -117,7 +120,7 @@ TEST(ScreenUITest, PhoneMenuSelectSmoke) {
|
|||
|
||||
TEST(ScreenUITest, WearMenuSelectSmoke) {
|
||||
int sel = 0;
|
||||
Menu menu(true, 10, 20, HEADER, ITEMS, sel);
|
||||
Menu menu(true, 10, 20, HEADERS, ITEMS, sel);
|
||||
// Mimic pressing down button 10 times (2 * items size)
|
||||
for (int i = 0; i < 10; i++) {
|
||||
sel = menu.Select(++sel);
|
||||
|
@ -146,7 +149,7 @@ TEST(ScreenUITest, WearMenuSelectSmoke) {
|
|||
|
||||
TEST(ScreenUITest, WearMenuSelectItemsOverflow) {
|
||||
int sel = 1;
|
||||
Menu menu(true, 3, 20, HEADER, ITEMS, sel);
|
||||
Menu menu(true, 3, 20, HEADERS, ITEMS, sel);
|
||||
ASSERT_EQ(5u, menu.ItemsCount());
|
||||
|
||||
// Scroll the menu to the end, and check the start & end of menu.
|
||||
|
|
10
ui.h
10
ui.h
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Abstract class for controlling the user interface during recovery.
|
||||
class RecoveryUI {
|
||||
|
@ -139,10 +140,11 @@ class RecoveryUI {
|
|||
// key_handler, which may be beyond the range of menu items. This could be used to trigger a
|
||||
// device-specific action, even without that being listed in the menu. Caller needs to handle
|
||||
// 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
|
||||
// timed out waiting for input.
|
||||
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;
|
||||
// Returns a non-negative value (the chosen item number or device-specific action code), or
|
||||
// static_cast<size_t>(-1) if timed out waiting for input.
|
||||
virtual size_t 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) = 0;
|
||||
|
||||
protected:
|
||||
void EnqueueKey(int key_code);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/properties.h>
|
||||
#include <android-base/strings.h>
|
||||
|
@ -88,13 +89,12 @@ void WearRecoveryUI::update_progress_locked() {
|
|||
|
||||
void WearRecoveryUI::SetStage(int /* current */, int /* max */) {}
|
||||
|
||||
void WearRecoveryUI::StartMenu(const char* const* headers, const char* const* items,
|
||||
int initial_selection) {
|
||||
void WearRecoveryUI::StartMenu(const std::vector<std::string>& headers,
|
||||
const std::vector<std::string>& items, size_t initial_selection) {
|
||||
pthread_mutex_lock(&updateMutex);
|
||||
if (text_rows_ > 0 && text_cols_ > 0) {
|
||||
menu_ = std::make_unique<Menu>(scrollable_menu_, text_rows_ - kMenuUnusableRows - 1,
|
||||
text_cols_ - 1, headers, items, initial_selection);
|
||||
|
||||
update_screen_locked();
|
||||
}
|
||||
pthread_mutex_unlock(&updateMutex);
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
#ifndef RECOVERY_WEAR_UI_H
|
||||
#define RECOVERY_WEAR_UI_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "screen_ui.h"
|
||||
|
||||
class WearRecoveryUI : public ScreenRecoveryUI {
|
||||
|
@ -33,8 +36,8 @@ class WearRecoveryUI : public ScreenRecoveryUI {
|
|||
// Recovery, build id and etc) and the bottom lines that may otherwise go out of the screen.
|
||||
const int kMenuUnusableRows;
|
||||
|
||||
void StartMenu(const char* const* headers, const char* const* items,
|
||||
int initial_selection) override;
|
||||
void StartMenu(const std::vector<std::string>& headers, const std::vector<std::string>& items,
|
||||
size_t initial_selection) override;
|
||||
|
||||
int GetProgressBaseline() const override;
|
||||
|
||||
|
|
Loading…
Reference in a new issue