aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--device.cpp44
-rw-r--r--device.h1
-rw-r--r--minui/include/minui/minui.h4
-rw-r--r--minui/resources.cpp35
-rw-r--r--recovery.cpp5
-rw-r--r--screen_ui.cpp77
-rw-r--r--screen_ui.h8
7 files changed, 153 insertions, 21 deletions
diff --git a/device.cpp b/device.cpp
index 61501869..f881daff 100644
--- a/device.cpp
+++ b/device.cpp
@@ -17,34 +17,36 @@
17#include "device.h" 17#include "device.h"
18 18
19static const char* MENU_ITEMS[] = { 19static const char* MENU_ITEMS[] = {
20 "Reboot system now", 20 "Reboot system now",
21 "Reboot to bootloader", 21 "Reboot to bootloader",
22 "Apply update from ADB", 22 "Apply update from ADB",
23 "Apply update from SD card", 23 "Apply update from SD card",
24 "Wipe data/factory reset", 24 "Wipe data/factory reset",
25#ifndef AB_OTA_UPDATER 25#ifndef AB_OTA_UPDATER
26 "Wipe cache partition", 26 "Wipe cache partition",
27#endif // !AB_OTA_UPDATER 27#endif // !AB_OTA_UPDATER
28 "Mount /system", 28 "Mount /system",
29 "View recovery logs", 29 "View recovery logs",
30 "Run graphics test", 30 "Run graphics test",
31 "Power off", 31 "Run locale test",
32 NULL, 32 "Power off",
33 nullptr,
33}; 34};
34 35
35static const Device::BuiltinAction MENU_ACTIONS[] = { 36static const Device::BuiltinAction MENU_ACTIONS[] = {
36 Device::REBOOT, 37 Device::REBOOT,
37 Device::REBOOT_BOOTLOADER, 38 Device::REBOOT_BOOTLOADER,
38 Device::APPLY_ADB_SIDELOAD, 39 Device::APPLY_ADB_SIDELOAD,
39 Device::APPLY_SDCARD, 40 Device::APPLY_SDCARD,
40 Device::WIPE_DATA, 41 Device::WIPE_DATA,
41#ifndef AB_OTA_UPDATER 42#ifndef AB_OTA_UPDATER
42 Device::WIPE_CACHE, 43 Device::WIPE_CACHE,
43#endif // !AB_OTA_UPDATER 44#endif // !AB_OTA_UPDATER
44 Device::MOUNT_SYSTEM, 45 Device::MOUNT_SYSTEM,
45 Device::VIEW_RECOVERY_LOGS, 46 Device::VIEW_RECOVERY_LOGS,
46 Device::RUN_GRAPHICS_TEST, 47 Device::RUN_GRAPHICS_TEST,
47 Device::SHUTDOWN, 48 Device::RUN_LOCALE_TEST,
49 Device::SHUTDOWN,
48}; 50};
49 51
50static_assert(sizeof(MENU_ITEMS) / sizeof(MENU_ITEMS[0]) == 52static_assert(sizeof(MENU_ITEMS) / sizeof(MENU_ITEMS[0]) ==
diff --git a/device.h b/device.h
index 639e2bf5..74745b36 100644
--- a/device.h
+++ b/device.h
@@ -66,6 +66,7 @@ class Device {
66 VIEW_RECOVERY_LOGS = 9, 66 VIEW_RECOVERY_LOGS = 9,
67 MOUNT_SYSTEM = 10, 67 MOUNT_SYSTEM = 10,
68 RUN_GRAPHICS_TEST = 11, 68 RUN_GRAPHICS_TEST = 11,
69 RUN_LOCALE_TEST = 12,
69 }; 70 };
70 71
71 // Return the list of menu items (an array of strings, NULL-terminated). The menu_position passed 72 // 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 017ddde7..27e60313 100644
--- a/minui/include/minui/minui.h
+++ b/minui/include/minui/minui.h
@@ -21,6 +21,7 @@
21 21
22#include <functional> 22#include <functional>
23#include <string> 23#include <string>
24#include <vector>
24 25
25// 26//
26// Graphics. 27// Graphics.
@@ -129,6 +130,9 @@ int res_create_alpha_surface(const char* name, GRSurface** pSurface);
129int res_create_localized_alpha_surface(const char* name, const char* locale, 130int res_create_localized_alpha_surface(const char* name, const char* locale,
130 GRSurface** pSurface); 131 GRSurface** pSurface);
131 132
133// Return a list of locale strings embedded in |png_name|. Return a empty list in case of failure.
134std::vector<std::string> get_locales_in_png(const std::string& png_name);
135
132// Free a surface allocated by any of the res_create_*_surface() 136// Free a surface allocated by any of the res_create_*_surface()
133// functions. 137// functions.
134void res_free_surface(GRSurface* surface); 138void res_free_surface(GRSurface* surface);
diff --git a/minui/resources.cpp b/minui/resources.cpp
index 8f8d36d2..756f29d2 100644
--- a/minui/resources.cpp
+++ b/minui/resources.cpp
@@ -396,6 +396,41 @@ bool matches_locale(const std::string& prefix, const std::string& locale) {
396 return std::regex_match(locale, loc_regex); 396 return std::regex_match(locale, loc_regex);
397} 397}
398 398
399std::vector<std::string> get_locales_in_png(const std::string& png_name) {
400 png_structp png_ptr = nullptr;
401 png_infop info_ptr = nullptr;
402 png_uint_32 width, height;
403 png_byte channels;
404
405 int status = open_png(png_name.c_str(), &png_ptr, &info_ptr, &width, &height, &channels);
406 if (status < 0) {
407 printf("Failed to open %s\n", png_name.c_str());
408 return {};
409 }
410 if (channels != 1) {
411 printf("Expect input png to have 1 data channel, this file has %d\n", channels);
412 png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
413 return {};
414 }
415
416 std::vector<std::string> result;
417 std::vector<unsigned char> row(width);
418 for (png_uint_32 y = 0; y < height; ++y) {
419 png_read_row(png_ptr, row.data(), nullptr);
420 int h = (row[3] << 8) | row[2];
421 std::string loc(reinterpret_cast<char*>(&row[5]));
422 if (!loc.empty()) {
423 result.push_back(loc);
424 }
425 for (int i = 0; i < h; ++i, ++y) {
426 png_read_row(png_ptr, row.data(), NULL);
427 }
428 }
429
430 png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
431 return result;
432}
433
399int res_create_localized_alpha_surface(const char* name, 434int res_create_localized_alpha_surface(const char* name,
400 const char* locale, 435 const char* locale,
401 GRSurface** pSurface) { 436 GRSurface** pSurface) {
diff --git a/recovery.cpp b/recovery.cpp
index d037b797..076b4492 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -1191,6 +1191,11 @@ static Device::BuiltinAction prompt_and_wait(Device* device, int status) {
1191 run_graphics_test(); 1191 run_graphics_test();
1192 break; 1192 break;
1193 1193
1194 case Device::RUN_LOCALE_TEST: {
1195 ScreenRecoveryUI* screen_ui = static_cast<ScreenRecoveryUI*>(ui);
1196 screen_ui->CheckBackgroundTextImages(locale);
1197 break;
1198 }
1194 case Device::MOUNT_SYSTEM: 1199 case Device::MOUNT_SYSTEM:
1195 // For a system image built with the root directory (i.e. system_root_image == "true"), we 1200 // For a system image built with the root directory (i.e. system_root_image == "true"), we
1196 // mount it to /system_root, and symlink /system to /system_root/system to make adb shell 1201 // 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 d65d656b..bc5c5c31 100644
--- a/screen_ui.cpp
+++ b/screen_ui.cpp
@@ -31,7 +31,9 @@
31#include <time.h> 31#include <time.h>
32#include <unistd.h> 32#include <unistd.h>
33 33
34#include <memory>
34#include <string> 35#include <string>
36#include <unordered_map>
35#include <vector> 37#include <vector>
36 38
37#include <android-base/logging.h> 39#include <android-base/logging.h>
@@ -258,6 +260,81 @@ void ScreenRecoveryUI::SetColor(UIElement e) const {
258 } 260 }
259} 261}
260 262
263void ScreenRecoveryUI::SelectAndShowBackgroundText(const std::vector<std::string>& locales_entries,
264 size_t sel) {
265 SetLocale(locales_entries[sel]);
266 std::vector<std::string> text_name = { "erasing_text", "error_text", "installing_text",
267 "installing_security_text", "no_command_text" };
268 std::unordered_map<std::string, std::unique_ptr<GRSurface, decltype(&free)>> surfaces;
269 for (const auto& name : text_name) {
270 GRSurface* text_image = nullptr;
271 LoadLocalizedBitmap(name.c_str(), &text_image);
272 if (!text_image) {
273 Print("Failed to load %s\n", name.c_str());
274 return;
275 }
276 surfaces.emplace(name, std::unique_ptr<GRSurface, decltype(&free)>(text_image, &free));
277 }
278
279 pthread_mutex_lock(&updateMutex);
280 gr_color(0, 0, 0, 255);
281 gr_clear();
282
283 int text_y = kMarginHeight;
284 int text_x = kMarginWidth;
285 int line_spacing = gr_sys_font()->char_height; // Put some extra space between images.
286 // Write the header and descriptive texts.
287 SetColor(INFO);
288 std::string header = "Show background text image";
289 text_y += DrawTextLine(text_x, text_y, header.c_str(), true);
290 std::string locale_selection = android::base::StringPrintf(
291 "Current locale: %s, %zu/%zu", locales_entries[sel].c_str(), sel, locales_entries.size());
292 const char* instruction[] = { locale_selection.c_str(),
293 "Use volume up/down to switch locales and power to exit.",
294 nullptr };
295 text_y += DrawWrappedTextLines(text_x, text_y, instruction);
296
297 // Iterate through the text images and display them in order for the current locale.
298 for (const auto& p : surfaces) {
299 text_y += line_spacing;
300 SetColor(LOG);
301 text_y += DrawTextLine(text_x, text_y, p.first.c_str(), false);
302 gr_color(255, 255, 255, 255);
303 gr_texticon(text_x, text_y, p.second.get());
304 text_y += gr_get_height(p.second.get());
305 }
306 // Update the whole screen.
307 gr_flip();
308 pthread_mutex_unlock(&updateMutex);
309}
310
311void ScreenRecoveryUI::CheckBackgroundTextImages(const std::string& saved_locale) {
312 // Load a list of locales embedded in one of the resource files.
313 std::vector<std::string> locales_entries = get_locales_in_png("installing_text");
314 if (locales_entries.empty()) {
315 Print("Failed to load locales from the resource files\n");
316 return;
317 }
318 size_t selected = 0;
319 SelectAndShowBackgroundText(locales_entries, selected);
320
321 FlushKeys();
322 while (true) {
323 int key = WaitKey();
324 if (key == KEY_POWER || key == KEY_ENTER) {
325 break;
326 } else if (key == KEY_UP || key == KEY_VOLUMEUP) {
327 selected = (selected == 0) ? locales_entries.size() - 1 : selected - 1;
328 SelectAndShowBackgroundText(locales_entries, selected);
329 } else if (key == KEY_DOWN || key == KEY_VOLUMEDOWN) {
330 selected = (selected == locales_entries.size() - 1) ? 0 : selected + 1;
331 SelectAndShowBackgroundText(locales_entries, selected);
332 }
333 }
334
335 SetLocale(saved_locale);
336}
337
261int ScreenRecoveryUI::DrawHorizontalRule(int y) const { 338int ScreenRecoveryUI::DrawHorizontalRule(int y) const {
262 gr_fill(0, y + 4, gr_fb_width(), y + 6); 339 gr_fill(0, y + 4, gr_fb_width(), y + 6);
263 return 8; 340 return 8;
diff --git a/screen_ui.h b/screen_ui.h
index eaac2a6e..3a28a09d 100644
--- a/screen_ui.h
+++ b/screen_ui.h
@@ -80,6 +80,10 @@ class ScreenRecoveryUI : public RecoveryUI {
80 80
81 void SetColor(UIElement e) const; 81 void SetColor(UIElement e) const;
82 82
83 // Check the background text image. Use volume up/down button to cycle through the locales
84 // embedded in the png file, and power button to go back to recovery main menu.
85 void CheckBackgroundTextImages(const std::string& saved_locale);
86
83 protected: 87 protected:
84 // The margin that we don't want to use for showing texts (e.g. round screen, or screen with 88 // The margin that we don't want to use for showing texts (e.g. round screen, or screen with
85 // rounded corners). 89 // rounded corners).
@@ -199,6 +203,10 @@ class ScreenRecoveryUI : public RecoveryUI {
199 203
200 private: 204 private:
201 void SetLocale(const std::string&); 205 void SetLocale(const std::string&);
206
207 // Display the background texts for "erasing", "error", "no_command" and "installing" for the
208 // selected locale.
209 void SelectAndShowBackgroundText(const std::vector<std::string>& locales_entries, size_t sel);
202}; 210};
203 211
204#endif // RECOVERY_UI_H 212#endif // RECOVERY_UI_H