From 29d5575fa877770f6387420294d9dc184a84a115 Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Wed, 20 Sep 2017 17:53:46 -0700 Subject: Add a new option in recovery menu to test the background texts Add a new option "Run locale test" to check the background text images (i.e. texts for "erasing", "error", "no_command" and "installing" with different locales.) Use volume up/down button to cycle through all the locales embedded in the png file, and power button to go back to recovery main menu. Test: Run locale test with bullhead. Change-Id: Ib16e119f372110cdb5e611ef497b0f9b9b418f51 --- device.cpp | 44 +++++++++++++------------- device.h | 1 + minui/include/minui/minui.h | 4 +++ minui/resources.cpp | 35 +++++++++++++++++++++ recovery.cpp | 5 +++ screen_ui.cpp | 77 +++++++++++++++++++++++++++++++++++++++++++++ screen_ui.h | 8 +++++ 7 files changed, 153 insertions(+), 21 deletions(-) diff --git a/device.cpp b/device.cpp index 61501869e..f881daff6 100644 --- a/device.cpp +++ b/device.cpp @@ -17,34 +17,36 @@ #include "device.h" static const char* MENU_ITEMS[] = { - "Reboot system now", - "Reboot to bootloader", - "Apply update from ADB", - "Apply update from SD card", - "Wipe data/factory reset", + "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", + "Wipe cache partition", #endif // !AB_OTA_UPDATER - "Mount /system", - "View recovery logs", - "Run graphics test", - "Power off", - NULL, + "Mount /system", + "View recovery logs", + "Run graphics test", + "Run locale test", + "Power off", + nullptr, }; static const Device::BuiltinAction MENU_ACTIONS[] = { - Device::REBOOT, - Device::REBOOT_BOOTLOADER, - Device::APPLY_ADB_SIDELOAD, - Device::APPLY_SDCARD, - Device::WIPE_DATA, + Device::REBOOT, + Device::REBOOT_BOOTLOADER, + Device::APPLY_ADB_SIDELOAD, + Device::APPLY_SDCARD, + Device::WIPE_DATA, #ifndef AB_OTA_UPDATER - Device::WIPE_CACHE, + Device::WIPE_CACHE, #endif // !AB_OTA_UPDATER - Device::MOUNT_SYSTEM, - Device::VIEW_RECOVERY_LOGS, - Device::RUN_GRAPHICS_TEST, - Device::SHUTDOWN, + Device::MOUNT_SYSTEM, + Device::VIEW_RECOVERY_LOGS, + Device::RUN_GRAPHICS_TEST, + Device::RUN_LOCALE_TEST, + Device::SHUTDOWN, }; static_assert(sizeof(MENU_ITEMS) / sizeof(MENU_ITEMS[0]) == diff --git a/device.h b/device.h index 639e2bf57..74745b36c 100644 --- a/device.h +++ b/device.h @@ -66,6 +66,7 @@ class Device { VIEW_RECOVERY_LOGS = 9, MOUNT_SYSTEM = 10, RUN_GRAPHICS_TEST = 11, + RUN_LOCALE_TEST = 12, }; // Return the list of menu items (an array of strings, NULL-terminated). The menu_position passed diff --git a/minui/include/minui/minui.h b/minui/include/minui/minui.h index 017ddde75..27e603136 100644 --- a/minui/include/minui/minui.h +++ b/minui/include/minui/minui.h @@ -21,6 +21,7 @@ #include #include +#include // // Graphics. @@ -129,6 +130,9 @@ int res_create_alpha_surface(const char* name, GRSurface** pSurface); int res_create_localized_alpha_surface(const char* name, const char* locale, GRSurface** pSurface); +// Return a list of locale strings embedded in |png_name|. Return a empty list in case of failure. +std::vector get_locales_in_png(const std::string& png_name); + // Free a surface allocated by any of the res_create_*_surface() // functions. void res_free_surface(GRSurface* surface); diff --git a/minui/resources.cpp b/minui/resources.cpp index 8f8d36d27..756f29d21 100644 --- a/minui/resources.cpp +++ b/minui/resources.cpp @@ -396,6 +396,41 @@ bool matches_locale(const std::string& prefix, const std::string& locale) { return std::regex_match(locale, loc_regex); } +std::vector get_locales_in_png(const std::string& png_name) { + png_structp png_ptr = nullptr; + png_infop info_ptr = nullptr; + png_uint_32 width, height; + png_byte channels; + + int status = open_png(png_name.c_str(), &png_ptr, &info_ptr, &width, &height, &channels); + if (status < 0) { + printf("Failed to open %s\n", png_name.c_str()); + return {}; + } + if (channels != 1) { + printf("Expect input png to have 1 data channel, this file has %d\n", channels); + png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); + return {}; + } + + std::vector result; + std::vector row(width); + for (png_uint_32 y = 0; y < height; ++y) { + png_read_row(png_ptr, row.data(), nullptr); + int h = (row[3] << 8) | row[2]; + std::string loc(reinterpret_cast(&row[5])); + if (!loc.empty()) { + result.push_back(loc); + } + for (int i = 0; i < h; ++i, ++y) { + png_read_row(png_ptr, row.data(), NULL); + } + } + + png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); + return result; +} + int res_create_localized_alpha_surface(const char* name, const char* locale, GRSurface** pSurface) { diff --git a/recovery.cpp b/recovery.cpp index d037b7971..076b4492e 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -1191,6 +1191,11 @@ static Device::BuiltinAction prompt_and_wait(Device* device, int status) { run_graphics_test(); break; + case Device::RUN_LOCALE_TEST: { + ScreenRecoveryUI* screen_ui = static_cast(ui); + screen_ui->CheckBackgroundTextImages(locale); + break; + } case Device::MOUNT_SYSTEM: // For a system image built with the root directory (i.e. system_root_image == "true"), we // mount it to /system_root, and symlink /system to /system_root/system to make adb shell diff --git a/screen_ui.cpp b/screen_ui.cpp index d65d656bd..bc5c5c31f 100644 --- a/screen_ui.cpp +++ b/screen_ui.cpp @@ -31,7 +31,9 @@ #include #include +#include #include +#include #include #include @@ -258,6 +260,81 @@ void ScreenRecoveryUI::SetColor(UIElement e) const { } } +void ScreenRecoveryUI::SelectAndShowBackgroundText(const std::vector& locales_entries, + size_t sel) { + SetLocale(locales_entries[sel]); + std::vector text_name = { "erasing_text", "error_text", "installing_text", + "installing_security_text", "no_command_text" }; + std::unordered_map> surfaces; + for (const auto& name : text_name) { + GRSurface* text_image = nullptr; + LoadLocalizedBitmap(name.c_str(), &text_image); + if (!text_image) { + Print("Failed to load %s\n", name.c_str()); + return; + } + surfaces.emplace(name, std::unique_ptr(text_image, &free)); + } + + pthread_mutex_lock(&updateMutex); + gr_color(0, 0, 0, 255); + gr_clear(); + + int text_y = kMarginHeight; + int text_x = kMarginWidth; + int line_spacing = gr_sys_font()->char_height; // Put some extra space between images. + // Write the header and descriptive texts. + SetColor(INFO); + std::string header = "Show background text image"; + text_y += DrawTextLine(text_x, text_y, header.c_str(), true); + std::string locale_selection = android::base::StringPrintf( + "Current locale: %s, %zu/%zu", locales_entries[sel].c_str(), sel, locales_entries.size()); + const char* instruction[] = { locale_selection.c_str(), + "Use volume up/down to switch locales and power to exit.", + nullptr }; + text_y += DrawWrappedTextLines(text_x, text_y, instruction); + + // Iterate through the text images and display them in order for the current locale. + for (const auto& p : surfaces) { + text_y += line_spacing; + SetColor(LOG); + text_y += DrawTextLine(text_x, text_y, p.first.c_str(), false); + gr_color(255, 255, 255, 255); + gr_texticon(text_x, text_y, p.second.get()); + text_y += gr_get_height(p.second.get()); + } + // Update the whole screen. + gr_flip(); + pthread_mutex_unlock(&updateMutex); +} + +void ScreenRecoveryUI::CheckBackgroundTextImages(const std::string& saved_locale) { + // Load a list of locales embedded in one of the resource files. + std::vector locales_entries = get_locales_in_png("installing_text"); + if (locales_entries.empty()) { + Print("Failed to load locales from the resource files\n"); + return; + } + size_t selected = 0; + SelectAndShowBackgroundText(locales_entries, selected); + + FlushKeys(); + while (true) { + int key = WaitKey(); + if (key == KEY_POWER || key == KEY_ENTER) { + break; + } else if (key == KEY_UP || key == KEY_VOLUMEUP) { + selected = (selected == 0) ? locales_entries.size() - 1 : selected - 1; + SelectAndShowBackgroundText(locales_entries, selected); + } else if (key == KEY_DOWN || key == KEY_VOLUMEDOWN) { + selected = (selected == locales_entries.size() - 1) ? 0 : selected + 1; + SelectAndShowBackgroundText(locales_entries, selected); + } + } + + SetLocale(saved_locale); +} + int ScreenRecoveryUI::DrawHorizontalRule(int y) const { gr_fill(0, y + 4, gr_fb_width(), y + 6); return 8; diff --git a/screen_ui.h b/screen_ui.h index eaac2a6e8..3a28a09de 100644 --- a/screen_ui.h +++ b/screen_ui.h @@ -80,6 +80,10 @@ class ScreenRecoveryUI : public RecoveryUI { void SetColor(UIElement e) const; + // Check the background text image. Use volume up/down button to cycle through the locales + // embedded in the png file, and power button to go back to recovery main menu. + void CheckBackgroundTextImages(const std::string& saved_locale); + protected: // The margin that we don't want to use for showing texts (e.g. round screen, or screen with // rounded corners). @@ -199,6 +203,10 @@ class ScreenRecoveryUI : public RecoveryUI { private: void SetLocale(const std::string&); + + // Display the background texts for "erasing", "error", "no_command" and "installing" for the + // selected locale. + void SelectAndShowBackgroundText(const std::vector& locales_entries, size_t sel); }; #endif // RECOVERY_UI_H -- cgit v1.2.3