diff options
-rw-r--r-- | Android.mk | 115 | ||||
-rw-r--r-- | device.cpp | 80 | ||||
-rw-r--r-- | device.h | 6 | ||||
-rw-r--r-- | minui/include/private/resources.h | 3 | ||||
-rw-r--r-- | minui/resources.cpp | 9 | ||||
-rw-r--r-- | otautil/include/otautil/paths.h | 10 | ||||
-rw-r--r-- | otautil/paths.cpp | 2 | ||||
-rw-r--r-- | recovery.cpp | 4 | ||||
-rw-r--r-- | screen_ui.cpp | 12 | ||||
-rw-r--r-- | tests/Android.mk | 100 | ||||
-rw-r--r-- | tests/testdata/font.png | bin | 0 -> 24437 bytes | |||
-rw-r--r-- | tests/testdata/loop00000.png | bin | 0 -> 5900 bytes | |||
-rw-r--r-- | tests/unit/screen_ui_test.cpp | 167 |
13 files changed, 377 insertions, 131 deletions
diff --git a/Android.mk b/Android.mk index dbd2eb788..09feba289 100644 --- a/Android.mk +++ b/Android.mk @@ -23,44 +23,21 @@ RECOVERY_FSTAB_VERSION := 2 # librecovery_ui_default, which uses ScreenRecoveryUI. TARGET_RECOVERY_UI_LIB ?= librecovery_ui_default -# librecovery (static library) -# =============================== -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - install.cpp - -LOCAL_CFLAGS := -Wall -Werror -LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION) - -ifeq ($(AB_OTA_UPDATER),true) - LOCAL_CFLAGS += -DAB_OTA_UPDATER=1 -endif - -LOCAL_MODULE := librecovery - -LOCAL_STATIC_LIBRARIES := \ - libminui \ - libotautil \ - libvintf_recovery \ - libcrypto_utils \ - libcrypto \ - libbase \ - libziparchive \ - -include $(BUILD_STATIC_LIBRARY) +recovery_common_cflags := \ + -Wall \ + -Werror \ + -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION) # librecovery_ui (static library) # =============================== include $(CLEAR_VARS) LOCAL_SRC_FILES := \ + device.cpp \ screen_ui.cpp \ ui.cpp \ vr_ui.cpp \ wear_ui.cpp -LOCAL_CFLAGS := -Wall -Werror - LOCAL_MODULE := librecovery_ui LOCAL_STATIC_LIBRARIES := \ @@ -68,6 +45,8 @@ LOCAL_STATIC_LIBRARIES := \ libotautil \ libbase +LOCAL_CFLAGS := $(recovery_common_cflags) + ifneq ($(TARGET_RECOVERY_UI_MARGIN_HEIGHT),) LOCAL_CFLAGS += -DRECOVERY_UI_MARGIN_HEIGHT=$(TARGET_RECOVERY_UI_MARGIN_HEIGHT) else @@ -118,13 +97,38 @@ endif include $(BUILD_STATIC_LIBRARY) +# librecovery (static library) +# =============================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + install.cpp + +LOCAL_CFLAGS := $(recovery_common_cflags) + +ifeq ($(AB_OTA_UPDATER),true) + LOCAL_CFLAGS += -DAB_OTA_UPDATER=1 +endif + +LOCAL_MODULE := librecovery + +LOCAL_STATIC_LIBRARIES := \ + libminui \ + libotautil \ + libvintf_recovery \ + libcrypto_utils \ + libcrypto \ + libbase \ + libziparchive \ + +include $(BUILD_STATIC_LIBRARY) + # recovery (static executable) # =============================== include $(CLEAR_VARS) LOCAL_SRC_FILES := \ adb_install.cpp \ - device.cpp \ fuse_sdcard_provider.cpp \ logging.cpp \ recovery.cpp \ @@ -135,20 +139,13 @@ LOCAL_MODULE := recovery LOCAL_FORCE_STATIC_EXECUTABLE := true +LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin + # Cannot link with LLD: undefined symbol: UsbNoPermissionsLongHelpText # http://b/77543887, lld does not handle -Wl,--gc-sections as well as ld. LOCAL_USE_CLANG_LLD := false -LOCAL_REQUIRED_MODULES := e2fsdroid_static mke2fs_static mke2fs.conf - -ifeq ($(TARGET_USERIMAGES_USE_F2FS),true) -ifeq ($(HOST_OS),linux) -LOCAL_REQUIRED_MODULES += sload.f2fs mkfs.f2fs -endif -endif - -LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION) -LOCAL_CFLAGS += -Wall -Werror +LOCAL_CFLAGS := $(recovery_common_cflags) LOCAL_C_INCLUDES += \ system/vold \ @@ -169,42 +166,52 @@ LOCAL_STATIC_LIBRARIES := \ LOCAL_STATIC_LIBRARIES += \ librecovery \ $(TARGET_RECOVERY_UI_LIB) \ - libverifier \ libbootloader_message \ - libfs_mgr \ - libext4_utils \ - libsparse \ - libziparchive \ - libotautil \ - libminadbd \ - libasyncio \ libfusesideload \ + libminadbd \ librecovery_ui \ libminui \ - libpng \ + libverifier \ + libotautil \ + libasyncio \ + libbatterymonitor \ libcrypto_utils \ libcrypto \ + libext4_utils \ + libfs_mgr \ + libpng \ + libsparse \ libvintf_recovery \ libvintf \ libhidl-gen-utils \ libtinyxml2 \ + libziparchive \ libbase \ libutils \ libcutils \ liblog \ libselinux \ - libz + libz \ LOCAL_HAL_STATIC_LIBRARIES := libhealthd -ifeq ($(AB_OTA_UPDATER),true) - LOCAL_CFLAGS += -DAB_OTA_UPDATER=1 -endif +LOCAL_REQUIRED_MODULES := \ + e2fsdroid_static \ + mke2fs_static \ + mke2fs.conf -LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin +ifeq ($(TARGET_USERIMAGES_USE_F2FS),true) +ifeq ($(HOST_OS),linux) +LOCAL_REQUIRED_MODULES += \ + sload.f2fs \ + mkfs.f2fs +endif +endif ifeq ($(BOARD_CACHEIMAGE_PARTITION_SIZE),) -LOCAL_REQUIRED_MODULES += recovery-persist recovery-refresh +LOCAL_REQUIRED_MODULES += \ + recovery-persist \ + recovery-refresh endif include $(BUILD_EXECUTABLE) diff --git a/device.cpp b/device.cpp index 5cf9cc242..3c6334e5c 100644 --- a/device.cpp +++ b/device.cpp @@ -16,59 +16,57 @@ #include "device.h" +#include <algorithm> +#include <string> +#include <utility> +#include <vector> + #include <android-base/logging.h> -#include <android-base/macros.h> #include "ui.h" -// clang-format off -static constexpr const char* kItems[]{ - "Reboot system now", - "Reboot to bootloader", - "Apply update from ADB", - "Apply update from SD card", - "Wipe data/factory reset", -#ifndef AB_OTA_UPDATER - "Wipe cache partition", -#endif // !AB_OTA_UPDATER - "Mount /system", - "View recovery logs", - "Run graphics test", - "Run locale test", - "Power off", -}; -// clang-format on - -// clang-format off -static constexpr Device::BuiltinAction kMenuActions[] { - Device::REBOOT, - Device::REBOOT_BOOTLOADER, - Device::APPLY_ADB_SIDELOAD, - Device::APPLY_SDCARD, - Device::WIPE_DATA, -#ifndef AB_OTA_UPDATER - Device::WIPE_CACHE, -#endif // !AB_OTA_UPDATER - Device::MOUNT_SYSTEM, - Device::VIEW_RECOVERY_LOGS, - Device::RUN_GRAPHICS_TEST, - Device::RUN_LOCALE_TEST, - Device::SHUTDOWN, +static std::vector<std::pair<std::string, Device::BuiltinAction>> g_menu_actions{ + { "Reboot system now", Device::REBOOT }, + { "Reboot to bootloader", Device::REBOOT_BOOTLOADER }, + { "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 }, + { "Mount /system", Device::MOUNT_SYSTEM }, + { "View recovery logs", Device::VIEW_RECOVERY_LOGS }, + { "Run graphics test", Device::RUN_GRAPHICS_TEST }, + { "Run locale test", Device::RUN_LOCALE_TEST }, + { "Power off", Device::SHUTDOWN }, }; -// clang-format on -static_assert(arraysize(kItems) == arraysize(kMenuActions), - "kItems and kMenuActions should have the same length."); +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), + [](const auto& entry) { return entry.first; }); +} + +Device::Device(RecoveryUI* ui) : ui_(ui) { + 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()); -static const std::vector<std::string> kMenuItems(kItems, kItems + arraysize(kItems)); + // Re-populate the menu items. + PopulateMenuItems(); +} const std::vector<std::string>& Device::GetMenuItems() { - return kMenuItems; + return g_menu_items; } Device::BuiltinAction Device::InvokeMenuItem(size_t menu_position) { - // CHECK_LT(menu_position, ); - return kMenuActions[menu_position]; + return g_menu_actions[menu_position].second; } int Device::HandleMenuKey(int key, bool visible) { @@ -49,7 +49,7 @@ class Device { RUN_LOCALE_TEST = 12, }; - explicit Device(RecoveryUI* ui) : ui_(ui) {} + explicit Device(RecoveryUI* ui); virtual ~Device() {} // Returns a raw pointer to the RecoveryUI object. @@ -96,6 +96,10 @@ class Device { // here and return NO_ACTION. virtual BuiltinAction InvokeMenuItem(size_t menu_position); + // Removes the menu item for the given action. This allows tailoring the menu based on the + // runtime info, such as the availability of /cache or /sdcard. + virtual void RemoveMenuItemForAction(Device::BuiltinAction action); + // 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 // selects the option from the menu, to perform whatever device-specific wiping actions as needed. diff --git a/minui/include/private/resources.h b/minui/include/private/resources.h index 2a83a1028..047ebe2e3 100644 --- a/minui/include/private/resources.h +++ b/minui/include/private/resources.h @@ -82,3 +82,6 @@ class PngHandler { // After initialization, we'll keep the file pointer open before destruction of PngHandler. std::unique_ptr<FILE, decltype(&fclose)> png_fp_{ nullptr, fclose }; }; + +// Overrides the default resource dir, for testing purpose. +void res_set_resource_dir(const std::string&); diff --git a/minui/resources.cpp b/minui/resources.cpp index 9f67cf844..c018d9b8c 100644 --- a/minui/resources.cpp +++ b/minui/resources.cpp @@ -32,7 +32,6 @@ #include <string> #include <vector> -#include <android-base/stringprintf.h> #include <android-base/strings.h> #include <png.h> @@ -40,6 +39,8 @@ #define SURFACE_DATA_ALIGNMENT 8 +static std::string g_resource_dir{ "/res/images" }; + static GRSurface* malloc_surface(size_t data_size) { size_t size = sizeof(GRSurface) + data_size + SURFACE_DATA_ALIGNMENT; unsigned char* temp = static_cast<unsigned char*>(malloc(size)); @@ -51,7 +52,7 @@ static GRSurface* malloc_surface(size_t data_size) { } PngHandler::PngHandler(const std::string& name) { - std::string res_path = android::base::StringPrintf("/res/images/%s.png", name.c_str()); + std::string res_path = g_resource_dir + "/" + name + ".png"; png_fp_.reset(fopen(res_path.c_str(), "rbe")); // Try to read from |name| if the resource path does not work. if (!png_fp_) { @@ -340,6 +341,10 @@ int res_create_alpha_surface(const char* name, GRSurface** pSurface) { return 0; } +void res_set_resource_dir(const std::string& dirname) { + g_resource_dir = dirname; +} + // This function tests if a locale string stored in PNG (prefix) matches // the locale string provided by the system (locale). bool matches_locale(const std::string& prefix, const std::string& locale) { diff --git a/otautil/include/otautil/paths.h b/otautil/include/otautil/paths.h index 788c3de33..39088f100 100644 --- a/otautil/include/otautil/paths.h +++ b/otautil/include/otautil/paths.h @@ -48,6 +48,13 @@ class Paths { last_command_file_ = last_command_file; } + std::string resource_dir() const { + return resource_dir_; + } + void set_resource_dir(const std::string& resource_dir) { + resource_dir_ = resource_dir; + } + std::string stash_directory_base() const { return stash_directory_base_; } @@ -85,6 +92,9 @@ class Paths { // Path to the last command file. std::string last_command_file_; + // Path to the resource dir; + std::string resource_dir_; + // Path to the base directory to write stashes during update. std::string stash_directory_base_; diff --git a/otautil/paths.cpp b/otautil/paths.cpp index ad9ec1145..f08e51c7a 100644 --- a/otautil/paths.cpp +++ b/otautil/paths.cpp @@ -19,6 +19,7 @@ constexpr const char kDefaultCacheLogDirectory[] = "/cache/recovery"; constexpr const char kDefaultCacheTempSource[] = "/cache/saved.file"; constexpr const char kDefaultLastCommandFile[] = "/cache/recovery/last_command"; +constexpr const char kDefaultResourceDirectory[] = "/res/images"; constexpr const char kDefaultStashDirectoryBase[] = "/cache/recovery"; constexpr const char kDefaultTemporaryInstallFile[] = "/tmp/last_install"; constexpr const char kDefaultTemporaryLogFile[] = "/tmp/recovery.log"; @@ -32,6 +33,7 @@ Paths::Paths() : cache_log_directory_(kDefaultCacheLogDirectory), cache_temp_source_(kDefaultCacheTempSource), last_command_file_(kDefaultLastCommandFile), + resource_dir_(kDefaultResourceDirectory), stash_directory_base_(kDefaultStashDirectoryBase), temporary_install_file_(kDefaultTemporaryInstallFile), temporary_log_file_(kDefaultTemporaryLogFile) {} diff --git a/recovery.cpp b/recovery.cpp index 38784b0b3..f03cec3fe 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -1202,6 +1202,10 @@ int start_recovery(int argc, char** argv) { } ui = device->GetUI(); + if (!has_cache) { + device->RemoveMenuItemForAction(Device::WIPE_CACHE); + } + // Set background string to "installing security update" for security update, // otherwise set it to "installing system update". ui->SetSystemUpdateText(security_update); diff --git a/screen_ui.cpp b/screen_ui.cpp index f5dadf7f0..fd7a1bea5 100644 --- a/screen_ui.cpp +++ b/screen_ui.cpp @@ -41,9 +41,10 @@ #include <android-base/properties.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> -#include <minui/minui.h> #include "device.h" +#include "minui/minui.h" +#include "otautil/paths.h" #include "ui.h" // Return the current time as a double (including fractions of a second). @@ -756,7 +757,8 @@ std::string ScreenRecoveryUI::GetLocale() const { } void ScreenRecoveryUI::LoadAnimation() { - std::unique_ptr<DIR, decltype(&closedir)> dir(opendir("/res/images"), closedir); + std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(Paths::Get().resource_dir().c_str()), + closedir); dirent* de; std::vector<std::string> intro_frame_names; std::vector<std::string> loop_frame_names; @@ -1099,9 +1101,9 @@ void ScreenRecoveryUI::SetLocale(const std::string& new_locale) { rtl_locale_ = false; if (!new_locale.empty()) { - size_t underscore = new_locale.find('_'); - // lang has the language prefix prior to '_', or full string if '_' doesn't exist. - std::string lang = new_locale.substr(0, underscore); + size_t separator = new_locale.find('-'); + // lang has the language prefix prior to the separator, or full string if none exists. + std::string lang = new_locale.substr(0, separator); // A bit cheesy: keep an explicit list of supported RTL languages. if (lang == "ar" || // Arabic diff --git a/tests/Android.mk b/tests/Android.mk index 538ae63e2..cdc5b523a 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -27,6 +27,7 @@ LOCAL_STATIC_LIBRARIES := \ libminui \ libotautil \ libupdater \ + libpng \ libziparchive \ libutils \ libz \ @@ -93,6 +94,26 @@ LOCAL_SRC_FILES := \ LOCAL_SHARED_LIBRARIES := \ libhidlbase +# libapplypatch, libapplypatch_modes, libimgdiff, libimgpatch. +libapplypatch_static_libraries := \ + libapplypatch_modes \ + libapplypatch \ + libedify \ + libimgdiff \ + libimgpatch \ + libotafault \ + libotautil \ + libbsdiff \ + libbspatch \ + libdivsufsort \ + libdivsufsort64 \ + libutils \ + libbase \ + libbz \ + libcrypto \ + libz \ + libziparchive \ + tune2fs_static_libraries := \ libext2_com_err \ libext2_blkid \ @@ -101,50 +122,73 @@ tune2fs_static_libraries := \ libext2_e2p \ libext2fs -LOCAL_STATIC_LIBRARIES := \ - libapplypatch_modes \ +libupdater_static_libraries := \ + libupdater \ libapplypatch \ - libedify \ - libimgdiff \ - libimgpatch \ - libbsdiff \ libbspatch \ - libfusesideload \ - libminui \ + libedify \ + libziparchive \ + libotautil \ + libbootloader_message \ + libutils \ libotafault \ + libext4_utils \ + libfec \ + libfec_rs \ + libfs_mgr \ + liblog \ + libselinux \ + libsparse \ + libsquashfs_utils \ + libbz \ + libz \ + libbase \ + libcrypto \ + libcrypto_utils \ + libcutils \ + libtune2fs \ + libbrotli \ + $(tune2fs_static_libraries) + +librecovery_static_libraries := \ librecovery \ - libupdater \ + $(TARGET_RECOVERY_UI_LIB) \ libbootloader_message \ + libfusesideload \ + libminadbd \ + librecovery_ui \ + libminui \ libverifier \ libotautil \ - libupdate_verifier \ - libdivsufsort \ - libdivsufsort64 \ + libasyncio \ + libbatterymonitor \ + libcrypto_utils \ + libcrypto \ + libext4_utils \ libfs_mgr \ libpng \ + libsparse \ libvintf_recovery \ libvintf \ libhidl-gen-utils \ libtinyxml2 \ - libselinux \ - libext4_utils \ - libsparse \ - libcrypto_utils \ - libcrypto \ - libbz \ libziparchive \ - liblog \ - libutils \ - libz \ libbase \ - libtune2fs \ - libfec \ - libfec_rs \ - libsquashfs_utils \ libcutils \ - libbrotli \ - libBionicGtestMain \ - $(tune2fs_static_libraries) + libutils \ + liblog \ + libselinux \ + libz \ + +libupdate_verifier_static_libraries := \ + libupdate_verifier \ + +LOCAL_STATIC_LIBRARIES := \ + $(libapplypatch_static_libraries) \ + $(librecovery_static_libraries) \ + $(libupdate_verifier_static_libraries) \ + $(libupdater_static_libraries) \ + libBionicGtestMain LOCAL_TEST_DATA := \ $(call find-test-data-in-subdirs, $(LOCAL_PATH), "*", testdata) \ diff --git a/tests/testdata/font.png b/tests/testdata/font.png Binary files differnew file mode 100644 index 000000000..d95408a93 --- /dev/null +++ b/tests/testdata/font.png diff --git a/tests/testdata/loop00000.png b/tests/testdata/loop00000.png Binary files differnew file mode 100644 index 000000000..0e11c0100 --- /dev/null +++ b/tests/testdata/loop00000.png diff --git a/tests/unit/screen_ui_test.cpp b/tests/unit/screen_ui_test.cpp index e47d7054b..03e23ca42 100644 --- a/tests/unit/screen_ui_test.cpp +++ b/tests/unit/screen_ui_test.cpp @@ -16,11 +16,19 @@ #include <stddef.h> +#include <functional> +#include <map> +#include <memory> #include <string> #include <vector> +#include <android-base/logging.h> #include <gtest/gtest.h> +#include "common/test_constants.h" +#include "device.h" +#include "otautil/paths.h" +#include "private/resources.h" #include "screen_ui.h" static const std::vector<std::string> HEADERS{ "header" }; @@ -185,3 +193,162 @@ TEST(ScreenUITest, WearMenuSelectItemsOverflow) { ASSERT_EQ(0u, menu.MenuStart()); ASSERT_EQ(3u, menu.MenuEnd()); } + +static constexpr int kMagicAction = 101; + +enum class KeyCode : int { + TIMEOUT = -1, + NO_OP = 0, + UP = 1, + DOWN = 2, + ENTER = 3, + MAGIC = 1001, + LAST, +}; + +static const std::map<KeyCode, int> kKeyMapping{ + // clang-format off + { KeyCode::NO_OP, Device::kNoAction }, + { KeyCode::UP, Device::kHighlightUp }, + { KeyCode::DOWN, Device::kHighlightDown }, + { KeyCode::ENTER, Device::kInvokeItem }, + { KeyCode::MAGIC, kMagicAction }, + // clang-format on +}; + +class TestableScreenRecoveryUI : public ScreenRecoveryUI { + public: + int WaitKey() override; + + void SetKeyBuffer(const std::vector<KeyCode>& buffer); + + int KeyHandler(int key, bool visible) const; + + bool GetRtlLocale() const { + return rtl_locale_; + } + + private: + std::vector<KeyCode> key_buffer_; + size_t key_buffer_index_; +}; + +void TestableScreenRecoveryUI::SetKeyBuffer(const std::vector<KeyCode>& buffer) { + key_buffer_ = buffer; + key_buffer_index_ = 0; +} + +int TestableScreenRecoveryUI::KeyHandler(int key, bool) const { + KeyCode key_code = static_cast<KeyCode>(key); + if (kKeyMapping.find(key_code) != kKeyMapping.end()) { + return kKeyMapping.at(key_code); + } + return Device::kNoAction; +} + +int TestableScreenRecoveryUI::WaitKey() { + CHECK_LT(key_buffer_index_, key_buffer_.size()); + return static_cast<int>(key_buffer_[key_buffer_index_++]); +} + +class ScreenRecoveryUITest : public ::testing::Test { + protected: + const std::string kTestLocale = "en-US"; + const std::string kTestRtlLocale = "ar"; + const std::string kTestRtlLocaleWithSuffix = "ar-EG"; + + void SetUp() override { + ui_ = std::make_unique<TestableScreenRecoveryUI>(); + + std::string testdata_dir = from_testdata_base(""); + Paths::Get().set_resource_dir(testdata_dir); + res_set_resource_dir(testdata_dir); + + ASSERT_TRUE(ui_->Init(kTestLocale)); + } + + std::unique_ptr<TestableScreenRecoveryUI> ui_; +}; + +TEST_F(ScreenRecoveryUITest, Init) { + ASSERT_EQ(kTestLocale, ui_->GetLocale()); + ASSERT_FALSE(ui_->GetRtlLocale()); + ASSERT_FALSE(ui_->IsTextVisible()); + ASSERT_FALSE(ui_->WasTextEverVisible()); +} + +TEST_F(ScreenRecoveryUITest, ShowText) { + ASSERT_FALSE(ui_->IsTextVisible()); + ui_->ShowText(true); + ASSERT_TRUE(ui_->IsTextVisible()); + ASSERT_TRUE(ui_->WasTextEverVisible()); + + ui_->ShowText(false); + ASSERT_FALSE(ui_->IsTextVisible()); + ASSERT_TRUE(ui_->WasTextEverVisible()); +} + +TEST_F(ScreenRecoveryUITest, RtlLocale) { + ASSERT_TRUE(ui_->Init(kTestRtlLocale)); + ASSERT_TRUE(ui_->GetRtlLocale()); + + ASSERT_TRUE(ui_->Init(kTestRtlLocaleWithSuffix)); + ASSERT_TRUE(ui_->GetRtlLocale()); +} + +TEST_F(ScreenRecoveryUITest, ShowMenu) { + ui_->SetKeyBuffer({ + KeyCode::UP, + KeyCode::DOWN, + KeyCode::UP, + KeyCode::DOWN, + KeyCode::ENTER, + }); + ASSERT_EQ(3u, ui_->ShowMenu(HEADERS, ITEMS, 3, true, + std::bind(&TestableScreenRecoveryUI::KeyHandler, ui_.get(), + std::placeholders::_1, std::placeholders::_2))); + + ui_->SetKeyBuffer({ + KeyCode::UP, + KeyCode::UP, + KeyCode::NO_OP, + KeyCode::NO_OP, + KeyCode::UP, + KeyCode::ENTER, + }); + ASSERT_EQ(2u, ui_->ShowMenu(HEADERS, ITEMS, 0, true, + std::bind(&TestableScreenRecoveryUI::KeyHandler, ui_.get(), + std::placeholders::_1, std::placeholders::_2))); +} + +TEST_F(ScreenRecoveryUITest, ShowMenu_NotMenuOnly) { + ui_->SetKeyBuffer({ + KeyCode::MAGIC, + }); + ASSERT_EQ(static_cast<size_t>(kMagicAction), + ui_->ShowMenu(HEADERS, ITEMS, 3, false, + std::bind(&TestableScreenRecoveryUI::KeyHandler, ui_.get(), + std::placeholders::_1, std::placeholders::_2))); +} + +TEST_F(ScreenRecoveryUITest, ShowMenu_TimedOut) { + ui_->SetKeyBuffer({ + KeyCode::TIMEOUT, + }); + ASSERT_EQ(static_cast<size_t>(-1), ui_->ShowMenu(HEADERS, ITEMS, 3, true, nullptr)); +} + +TEST_F(ScreenRecoveryUITest, ShowMenu_TimedOut_TextWasEverVisible) { + ui_->ShowText(true); + ui_->ShowText(false); + ASSERT_TRUE(ui_->WasTextEverVisible()); + + ui_->SetKeyBuffer({ + KeyCode::TIMEOUT, + KeyCode::DOWN, + KeyCode::ENTER, + }); + ASSERT_EQ(4u, ui_->ShowMenu(HEADERS, ITEMS, 3, true, + std::bind(&TestableScreenRecoveryUI::KeyHandler, ui_.get(), + std::placeholders::_1, std::placeholders::_2))); +} |