Merge "Add a new option in recovery menu to test the background texts"
This commit is contained in:
44
device.cpp
44
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]) ==
|
||||
|
||||
1
device.h
1
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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user