Merge "Add a new option in recovery menu to test the background texts"

This commit is contained in:
Tianjie Xu
2017-09-27 17:39:05 +00:00
committed by Gerrit Code Review
7 changed files with 153 additions and 21 deletions

View File

@@ -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]) ==

View File

@@ -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

View File

@@ -21,6 +21,7 @@
#include <functional>
#include <string>
#include <vector>
//
// 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<std::string> 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);

View File

@@ -396,6 +396,41 @@ bool matches_locale(const std::string& prefix, const std::string& locale) {
return std::regex_match(locale, loc_regex);
}
std::vector<std::string> 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<std::string> result;
std::vector<unsigned char> 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<char*>(&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) {

View File

@@ -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<ScreenRecoveryUI*>(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

View File

@@ -31,7 +31,9 @@
#include <time.h>
#include <unistd.h>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include <android-base/logging.h>
@@ -258,6 +260,81 @@ void ScreenRecoveryUI::SetColor(UIElement e) const {
}
}
void ScreenRecoveryUI::SelectAndShowBackgroundText(const std::vector<std::string>& locales_entries,
size_t sel) {
SetLocale(locales_entries[sel]);
std::vector<std::string> text_name = { "erasing_text", "error_text", "installing_text",
"installing_security_text", "no_command_text" };
std::unordered_map<std::string, std::unique_ptr<GRSurface, decltype(&free)>> 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<GRSurface, decltype(&free)>(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<std::string> 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;

View File

@@ -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<std::string>& locales_entries, size_t sel);
};
#endif // RECOVERY_UI_H