aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--recovery.cpp3
-rw-r--r--screen_ui.cpp234
-rw-r--r--screen_ui.h8
-rw-r--r--stub_ui.h2
-rw-r--r--tests/component/verifier_test.cpp70
-rw-r--r--ui.cpp67
-rw-r--r--ui.h21
-rw-r--r--wear_ui.cpp71
-rw-r--r--wear_ui.h4
9 files changed, 244 insertions, 236 deletions
diff --git a/recovery.cpp b/recovery.cpp
index b7aeaee1..5888c542 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -1506,11 +1506,10 @@ int main(int argc, char **argv) {
1506 Device* device = make_device(); 1506 Device* device = make_device();
1507 ui = device->GetUI(); 1507 ui = device->GetUI();
1508 1508
1509 if (!ui->Init()) { 1509 if (!ui->Init(locale)) {
1510 printf("Failed to initialize UI, use stub UI instead."); 1510 printf("Failed to initialize UI, use stub UI instead.");
1511 ui = new StubRecoveryUI(); 1511 ui = new StubRecoveryUI();
1512 } 1512 }
1513 ui->SetLocale(locale.c_str());
1514 // Set background string to "installing security update" for security update, 1513 // Set background string to "installing security update" for security update,
1515 // otherwise set it to "installing system update". 1514 // otherwise set it to "installing system update".
1516 ui->SetSystemUpdateText(security_update); 1515 ui->SetSystemUpdateText(security_update);
diff --git a/screen_ui.cpp b/screen_ui.cpp
index 5b9e5a5a..706877b4 100644
--- a/screen_ui.cpp
+++ b/screen_ui.cpp
@@ -29,6 +29,7 @@
29#include <time.h> 29#include <time.h>
30#include <unistd.h> 30#include <unistd.h>
31 31
32#include <string>
32#include <vector> 33#include <vector>
33 34
34#include <android-base/logging.h> 35#include <android-base/logging.h>
@@ -51,37 +52,34 @@ static double now() {
51 return tv.tv_sec + tv.tv_usec / 1000000.0; 52 return tv.tv_sec + tv.tv_usec / 1000000.0;
52} 53}
53 54
54ScreenRecoveryUI::ScreenRecoveryUI() : 55ScreenRecoveryUI::ScreenRecoveryUI()
55 currentIcon(NONE), 56 : currentIcon(NONE),
56 locale(nullptr), 57 progressBarType(EMPTY),
57 progressBarType(EMPTY), 58 progressScopeStart(0),
58 progressScopeStart(0), 59 progressScopeSize(0),
59 progressScopeSize(0), 60 progress(0),
60 progress(0), 61 pagesIdentical(false),
61 pagesIdentical(false), 62 text_cols_(0),
62 text_cols_(0), 63 text_rows_(0),
63 text_rows_(0), 64 text_(nullptr),
64 text_(nullptr), 65 text_col_(0),
65 text_col_(0), 66 text_row_(0),
66 text_row_(0), 67 text_top_(0),
67 text_top_(0), 68 show_text(false),
68 show_text(false), 69 show_text_ever(false),
69 show_text_ever(false), 70 menu_(nullptr),
70 menu_(nullptr), 71 show_menu(false),
71 show_menu(false), 72 menu_items(0),
72 menu_items(0), 73 menu_sel(0),
73 menu_sel(0), 74 file_viewer_text_(nullptr),
74 file_viewer_text_(nullptr), 75 intro_frames(0),
75 intro_frames(0), 76 loop_frames(0),
76 loop_frames(0), 77 current_frame(0),
77 current_frame(0), 78 intro_done(false),
78 intro_done(false), 79 animation_fps(30), // TODO: there's currently no way to infer this.
79 animation_fps(30), // TODO: there's currently no way to infer this. 80 stage(-1),
80 stage(-1), 81 max_stage(-1),
81 max_stage(-1), 82 updateMutex(PTHREAD_MUTEX_INITIALIZER) {}
82 updateMutex(PTHREAD_MUTEX_INITIALIZER),
83 rtl_locale(false) {
84}
85 83
86GRSurface* ScreenRecoveryUI::GetCurrentFrame() { 84GRSurface* ScreenRecoveryUI::GetCurrentFrame() {
87 if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) { 85 if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) {
@@ -175,51 +173,50 @@ void ScreenRecoveryUI::draw_background_locked() {
175// Does not flip pages. 173// Does not flip pages.
176// Should only be called with updateMutex locked. 174// Should only be called with updateMutex locked.
177void ScreenRecoveryUI::draw_foreground_locked() { 175void ScreenRecoveryUI::draw_foreground_locked() {
178 if (currentIcon != NONE) { 176 if (currentIcon != NONE) {
179 GRSurface* frame = GetCurrentFrame(); 177 GRSurface* frame = GetCurrentFrame();
180 int frame_width = gr_get_width(frame); 178 int frame_width = gr_get_width(frame);
181 int frame_height = gr_get_height(frame); 179 int frame_height = gr_get_height(frame);
182 int frame_x = (gr_fb_width() - frame_width) / 2; 180 int frame_x = (gr_fb_width() - frame_width) / 2;
183 int frame_y = GetAnimationBaseline(); 181 int frame_y = GetAnimationBaseline();
184 gr_blit(frame, 0, 0, frame_width, frame_height, frame_x, frame_y); 182 gr_blit(frame, 0, 0, frame_width, frame_height, frame_x, frame_y);
185 } 183 }
186 184
187 if (progressBarType != EMPTY) { 185 if (progressBarType != EMPTY) {
188 int width = gr_get_width(progressBarEmpty); 186 int width = gr_get_width(progressBarEmpty);
189 int height = gr_get_height(progressBarEmpty); 187 int height = gr_get_height(progressBarEmpty);
190 188
191 int progress_x = (gr_fb_width() - width)/2; 189 int progress_x = (gr_fb_width() - width) / 2;
192 int progress_y = GetProgressBaseline(); 190 int progress_y = GetProgressBaseline();
193 191
194 // Erase behind the progress bar (in case this was a progress-only update) 192 // Erase behind the progress bar (in case this was a progress-only update)
195 gr_color(0, 0, 0, 255); 193 gr_color(0, 0, 0, 255);
196 gr_fill(progress_x, progress_y, width, height); 194 gr_fill(progress_x, progress_y, width, height);
197 195
198 if (progressBarType == DETERMINATE) { 196 if (progressBarType == DETERMINATE) {
199 float p = progressScopeStart + progress * progressScopeSize; 197 float p = progressScopeStart + progress * progressScopeSize;
200 int pos = (int) (p * width); 198 int pos = static_cast<int>(p * width);
201 199
202 if (rtl_locale) { 200 if (rtl_locale_) {
203 // Fill the progress bar from right to left. 201 // Fill the progress bar from right to left.
204 if (pos > 0) { 202 if (pos > 0) {
205 gr_blit(progressBarFill, width-pos, 0, pos, height, 203 gr_blit(progressBarFill, width - pos, 0, pos, height, progress_x + width - pos,
206 progress_x+width-pos, progress_y); 204 progress_y);
207 } 205 }
208 if (pos < width-1) { 206 if (pos < width - 1) {
209 gr_blit(progressBarEmpty, 0, 0, width-pos, height, progress_x, progress_y); 207 gr_blit(progressBarEmpty, 0, 0, width - pos, height, progress_x, progress_y);
210 } 208 }
211 } else { 209 } else {
212 // Fill the progress bar from left to right. 210 // Fill the progress bar from left to right.
213 if (pos > 0) { 211 if (pos > 0) {
214 gr_blit(progressBarFill, 0, 0, pos, height, progress_x, progress_y); 212 gr_blit(progressBarFill, 0, 0, pos, height, progress_x, progress_y);
215 }
216 if (pos < width-1) {
217 gr_blit(progressBarEmpty, pos, 0, width-pos, height,
218 progress_x+pos, progress_y);
219 }
220 }
221 } 213 }
214 if (pos < width - 1) {
215 gr_blit(progressBarEmpty, pos, 0, width - pos, height, progress_x + pos, progress_y);
216 }
217 }
222 } 218 }
219 }
223} 220}
224 221
225void ScreenRecoveryUI::SetColor(UIElement e) { 222void ScreenRecoveryUI::SetColor(UIElement e) {
@@ -423,10 +420,10 @@ void ScreenRecoveryUI::LoadBitmap(const char* filename, GRSurface** surface) {
423} 420}
424 421
425void ScreenRecoveryUI::LoadLocalizedBitmap(const char* filename, GRSurface** surface) { 422void ScreenRecoveryUI::LoadLocalizedBitmap(const char* filename, GRSurface** surface) {
426 int result = res_create_localized_alpha_surface(filename, locale, surface); 423 int result = res_create_localized_alpha_surface(filename, locale_.c_str(), surface);
427 if (result < 0) { 424 if (result < 0) {
428 LOG(ERROR) << "couldn't load bitmap " << filename << " (error " << result << ")"; 425 LOG(ERROR) << "couldn't load bitmap " << filename << " (error " << result << ")";
429 } 426 }
430} 427}
431 428
432static char** Alloc2d(size_t rows, size_t cols) { 429static char** Alloc2d(size_t rows, size_t cols) {
@@ -459,47 +456,47 @@ bool ScreenRecoveryUI::InitTextParams() {
459 return true; 456 return true;
460} 457}
461 458
462bool ScreenRecoveryUI::Init() { 459bool ScreenRecoveryUI::Init(const std::string& locale) {
463 RecoveryUI::Init(); 460 RecoveryUI::Init(locale);
464 if (!InitTextParams()) { 461 if (!InitTextParams()) {
465 return false; 462 return false;
466 } 463 }
467 464
468 density_ = static_cast<float>(android::base::GetIntProperty("ro.sf.lcd_density", 160)) / 160.f; 465 density_ = static_cast<float>(android::base::GetIntProperty("ro.sf.lcd_density", 160)) / 160.f;
469 466
470 // Are we portrait or landscape? 467 // Are we portrait or landscape?
471 layout_ = (gr_fb_width() > gr_fb_height()) ? LANDSCAPE : PORTRAIT; 468 layout_ = (gr_fb_width() > gr_fb_height()) ? LANDSCAPE : PORTRAIT;
472 // Are we the large variant of our base layout? 469 // Are we the large variant of our base layout?
473 if (gr_fb_height() > PixelsFromDp(800)) ++layout_; 470 if (gr_fb_height() > PixelsFromDp(800)) ++layout_;
474 471
475 text_ = Alloc2d(text_rows_, text_cols_ + 1); 472 text_ = Alloc2d(text_rows_, text_cols_ + 1);
476 file_viewer_text_ = Alloc2d(text_rows_, text_cols_ + 1); 473 file_viewer_text_ = Alloc2d(text_rows_, text_cols_ + 1);
477 menu_ = Alloc2d(text_rows_, text_cols_ + 1); 474 menu_ = Alloc2d(text_rows_, text_cols_ + 1);
478 475
479 text_col_ = text_row_ = 0; 476 text_col_ = text_row_ = 0;
480 text_top_ = 1; 477 text_top_ = 1;
481 478
482 LoadBitmap("icon_error", &error_icon); 479 LoadBitmap("icon_error", &error_icon);
483 480
484 LoadBitmap("progress_empty", &progressBarEmpty); 481 LoadBitmap("progress_empty", &progressBarEmpty);
485 LoadBitmap("progress_fill", &progressBarFill); 482 LoadBitmap("progress_fill", &progressBarFill);
486 483
487 LoadBitmap("stage_empty", &stageMarkerEmpty); 484 LoadBitmap("stage_empty", &stageMarkerEmpty);
488 LoadBitmap("stage_fill", &stageMarkerFill); 485 LoadBitmap("stage_fill", &stageMarkerFill);
489 486
490 // Background text for "installing_update" could be "installing update" 487 // Background text for "installing_update" could be "installing update"
491 // or "installing security update". It will be set after UI init according 488 // or "installing security update". It will be set after UI init according
492 // to commands in BCB. 489 // to commands in BCB.
493 installing_text = nullptr; 490 installing_text = nullptr;
494 LoadLocalizedBitmap("erasing_text", &erasing_text); 491 LoadLocalizedBitmap("erasing_text", &erasing_text);
495 LoadLocalizedBitmap("no_command_text", &no_command_text); 492 LoadLocalizedBitmap("no_command_text", &no_command_text);
496 LoadLocalizedBitmap("error_text", &error_text); 493 LoadLocalizedBitmap("error_text", &error_text);
497 494
498 LoadAnimation(); 495 LoadAnimation();
499 496
500 pthread_create(&progress_thread_, nullptr, ProgressThreadStartRoutine, this); 497 pthread_create(&progress_thread_, nullptr, ProgressThreadStartRoutine, this);
501 498
502 return true; 499 return true;
503} 500}
504 501
505void ScreenRecoveryUI::LoadAnimation() { 502void ScreenRecoveryUI::LoadAnimation() {
@@ -539,31 +536,6 @@ void ScreenRecoveryUI::LoadAnimation() {
539 } 536 }
540} 537}
541 538
542void ScreenRecoveryUI::SetLocale(const char* new_locale) {
543 this->locale = new_locale;
544 this->rtl_locale = false;
545
546 if (locale) {
547 char* lang = strdup(locale);
548 for (char* p = lang; *p; ++p) {
549 if (*p == '_') {
550 *p = '\0';
551 break;
552 }
553 }
554
555 // A bit cheesy: keep an explicit list of supported RTL languages.
556 if (strcmp(lang, "ar") == 0 || // Arabic
557 strcmp(lang, "fa") == 0 || // Persian (Farsi)
558 strcmp(lang, "he") == 0 || // Hebrew (new language code)
559 strcmp(lang, "iw") == 0 || // Hebrew (old language code)
560 strcmp(lang, "ur") == 0) { // Urdu
561 rtl_locale = true;
562 }
563 free(lang);
564 }
565}
566
567void ScreenRecoveryUI::SetBackground(Icon icon) { 539void ScreenRecoveryUI::SetBackground(Icon icon) {
568 pthread_mutex_lock(&updateMutex); 540 pthread_mutex_lock(&updateMutex);
569 541
diff --git a/screen_ui.h b/screen_ui.h
index 38e2f072..3ad64907 100644
--- a/screen_ui.h
+++ b/screen_ui.h
@@ -20,6 +20,8 @@
20#include <pthread.h> 20#include <pthread.h>
21#include <stdio.h> 21#include <stdio.h>
22 22
23#include <string>
24
23#include "ui.h" 25#include "ui.h"
24#include "minui/minui.h" 26#include "minui/minui.h"
25 27
@@ -29,8 +31,7 @@ class ScreenRecoveryUI : public RecoveryUI {
29 public: 31 public:
30 ScreenRecoveryUI(); 32 ScreenRecoveryUI();
31 33
32 bool Init() override; 34 bool Init(const std::string& locale) override;
33 void SetLocale(const char* locale);
34 35
35 // overall recovery state ("background image") 36 // overall recovery state ("background image")
36 void SetBackground(Icon icon); 37 void SetBackground(Icon icon);
@@ -71,8 +72,6 @@ class ScreenRecoveryUI : public RecoveryUI {
71 protected: 72 protected:
72 Icon currentIcon; 73 Icon currentIcon;
73 74
74 const char* locale;
75
76 // The scale factor from dp to pixels. 1.0 for mdpi, 4.0 for xxxhdpi. 75 // The scale factor from dp to pixels. 1.0 for mdpi, 4.0 for xxxhdpi.
77 float density_; 76 float density_;
78 // The layout to use. 77 // The layout to use.
@@ -135,7 +134,6 @@ class ScreenRecoveryUI : public RecoveryUI {
135 int char_width_; 134 int char_width_;
136 int char_height_; 135 int char_height_;
137 pthread_mutex_t updateMutex; 136 pthread_mutex_t updateMutex;
138 bool rtl_locale;
139 137
140 virtual bool InitTextParams(); 138 virtual bool InitTextParams();
141 139
diff --git a/stub_ui.h b/stub_ui.h
index 1219b284..85dbcfd8 100644
--- a/stub_ui.h
+++ b/stub_ui.h
@@ -24,8 +24,6 @@ class StubRecoveryUI : public RecoveryUI {
24 public: 24 public:
25 StubRecoveryUI() = default; 25 StubRecoveryUI() = default;
26 26
27 void SetLocale(const char* locale) override {}
28
29 void SetBackground(Icon icon) override {} 27 void SetBackground(Icon icon) override {}
30 void SetSystemUpdateText(bool security_update) override {} 28 void SetSystemUpdateText(bool security_update) override {}
31 29
diff --git a/tests/component/verifier_test.cpp b/tests/component/verifier_test.cpp
index 33aadb3f..b740af96 100644
--- a/tests/component/verifier_test.cpp
+++ b/tests/component/verifier_test.cpp
@@ -40,38 +40,44 @@
40RecoveryUI* ui = NULL; 40RecoveryUI* ui = NULL;
41 41
42class MockUI : public RecoveryUI { 42class MockUI : public RecoveryUI {
43 bool Init() { return true; } 43 bool Init(const std::string&) override {
44 void SetStage(int, int) { } 44 return true;
45 void SetLocale(const char*) { } 45 }
46 void SetBackground(Icon /*icon*/) { } 46 void SetStage(int, int) override {}
47 void SetSystemUpdateText(bool /*security_update*/) { } 47 void SetBackground(Icon /*icon*/) override {}
48 48 void SetSystemUpdateText(bool /*security_update*/) override {}
49 void SetProgressType(ProgressType /*determinate*/) { } 49
50 void ShowProgress(float /*portion*/, float /*seconds*/) { } 50 void SetProgressType(ProgressType /*determinate*/) override {}
51 void SetProgress(float /*fraction*/) { } 51 void ShowProgress(float /*portion*/, float /*seconds*/) override {}
52 52 void SetProgress(float /*fraction*/) override {}
53 void ShowText(bool /*visible*/) { } 53
54 bool IsTextVisible() { return false; } 54 void ShowText(bool /*visible*/) override {}
55 bool WasTextEverVisible() { return false; } 55 bool IsTextVisible() override {
56 void Print(const char* fmt, ...) { 56 return false;
57 va_list ap; 57 }
58 va_start(ap, fmt); 58 bool WasTextEverVisible() override {
59 vfprintf(stderr, fmt, ap); 59 return false;
60 va_end(ap); 60 }
61 } 61 void Print(const char* fmt, ...) override {
62 void PrintOnScreenOnly(const char* fmt, ...) { 62 va_list ap;
63 va_list ap; 63 va_start(ap, fmt);
64 va_start(ap, fmt); 64 vfprintf(stderr, fmt, ap);
65 vfprintf(stderr, fmt, ap); 65 va_end(ap);
66 va_end(ap); 66 }
67 } 67 void PrintOnScreenOnly(const char* fmt, ...) override {
68 void ShowFile(const char*) { } 68 va_list ap;
69 69 va_start(ap, fmt);
70 void StartMenu(const char* const* /*headers*/, 70 vfprintf(stderr, fmt, ap);
71 const char* const* /*items*/, 71 va_end(ap);
72 int /*initial_selection*/) { } 72 }
73 int SelectMenu(int /*sel*/) { return 0; } 73 void ShowFile(const char*) override {}
74 void EndMenu() { } 74
75 void StartMenu(const char* const* /*headers*/, const char* const* /*items*/,
76 int /*initial_selection*/) override {}
77 int SelectMenu(int /*sel*/) override {
78 return 0;
79 }
80 void EndMenu() override {}
75}; 81};
76 82
77void 83void
diff --git a/ui.cpp b/ui.cpp
index 2d80c382..f31660db 100644
--- a/ui.cpp
+++ b/ui.cpp
@@ -14,6 +14,8 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#include "ui.h"
18
17#include <errno.h> 19#include <errno.h>
18#include <fcntl.h> 20#include <fcntl.h>
19#include <linux/input.h> 21#include <linux/input.h>
@@ -28,6 +30,8 @@
28#include <time.h> 30#include <time.h>
29#include <unistd.h> 31#include <unistd.h>
30 32
33#include <string>
34
31#include <android-base/properties.h> 35#include <android-base/properties.h>
32#include <cutils/android_reboot.h> 36#include <cutils/android_reboot.h>
33 37
@@ -35,25 +39,25 @@
35#include "roots.h" 39#include "roots.h"
36#include "device.h" 40#include "device.h"
37#include "minui/minui.h" 41#include "minui/minui.h"
38#include "screen_ui.h"
39#include "ui.h"
40 42
41#define UI_WAIT_KEY_TIMEOUT_SEC 120 43#define UI_WAIT_KEY_TIMEOUT_SEC 120
42 44
43RecoveryUI::RecoveryUI() 45RecoveryUI::RecoveryUI()
44 : key_queue_len(0), 46 : locale_(""),
45 key_last_down(-1), 47 rtl_locale_(false),
46 key_long_press(false), 48 key_queue_len(0),
47 key_down_count(0), 49 key_last_down(-1),
48 enable_reboot(true), 50 key_long_press(false),
49 consecutive_power_keys(0), 51 key_down_count(0),
50 last_key(-1), 52 enable_reboot(true),
51 has_power_key(false), 53 consecutive_power_keys(0),
52 has_up_key(false), 54 last_key(-1),
53 has_down_key(false) { 55 has_power_key(false),
54 pthread_mutex_init(&key_queue_mutex, nullptr); 56 has_up_key(false),
55 pthread_cond_init(&key_queue_cond, nullptr); 57 has_down_key(false) {
56 memset(key_pressed, 0, sizeof(key_pressed)); 58 pthread_mutex_init(&key_queue_mutex, nullptr);
59 pthread_cond_init(&key_queue_cond, nullptr);
60 memset(key_pressed, 0, sizeof(key_pressed));
57} 61}
58 62
59void RecoveryUI::OnKeyDetected(int key_code) { 63void RecoveryUI::OnKeyDetected(int key_code) {
@@ -80,13 +84,16 @@ static void* InputThreadLoop(void*) {
80 return nullptr; 84 return nullptr;
81} 85}
82 86
83bool RecoveryUI::Init() { 87bool RecoveryUI::Init(const std::string& locale) {
84 ev_init(InputCallback, this); 88 // Set up the locale info.
89 SetLocale(locale);
85 90
86 ev_iterate_available_keys(std::bind(&RecoveryUI::OnKeyDetected, this, std::placeholders::_1)); 91 ev_init(InputCallback, this);
87 92
88 pthread_create(&input_thread_, nullptr, InputThreadLoop, nullptr); 93 ev_iterate_available_keys(std::bind(&RecoveryUI::OnKeyDetected, this, std::placeholders::_1));
89 return true; 94
95 pthread_create(&input_thread_, nullptr, InputThreadLoop, nullptr);
96 return true;
90} 97}
91 98
92int RecoveryUI::OnInputEvent(int fd, uint32_t epevents) { 99int RecoveryUI::OnInputEvent(int fd, uint32_t epevents) {
@@ -338,3 +345,23 @@ void RecoveryUI::SetEnableReboot(bool enabled) {
338 enable_reboot = enabled; 345 enable_reboot = enabled;
339 pthread_mutex_unlock(&key_queue_mutex); 346 pthread_mutex_unlock(&key_queue_mutex);
340} 347}
348
349void RecoveryUI::SetLocale(const std::string& new_locale) {
350 this->locale_ = new_locale;
351 this->rtl_locale_ = false;
352
353 if (!new_locale.empty()) {
354 size_t underscore = new_locale.find('_');
355 // lang has the language prefix prior to '_', or full string if '_' doesn't exist.
356 std::string lang = new_locale.substr(0, underscore);
357
358 // A bit cheesy: keep an explicit list of supported RTL languages.
359 if (lang == "ar" || // Arabic
360 lang == "fa" || // Persian (Farsi)
361 lang == "he" || // Hebrew (new language code)
362 lang == "iw" || // Hebrew (old language code)
363 lang == "ur") { // Urdu
364 rtl_locale_ = true;
365 }
366 }
367}
diff --git a/ui.h b/ui.h
index be95a4e2..8493c6f0 100644
--- a/ui.h
+++ b/ui.h
@@ -21,6 +21,8 @@
21#include <pthread.h> 21#include <pthread.h>
22#include <time.h> 22#include <time.h>
23 23
24#include <string>
25
24// Abstract class for controlling the user interface during recovery. 26// Abstract class for controlling the user interface during recovery.
25class RecoveryUI { 27class RecoveryUI {
26 public: 28 public:
@@ -28,14 +30,13 @@ class RecoveryUI {
28 30
29 virtual ~RecoveryUI() { } 31 virtual ~RecoveryUI() { }
30 32
31 // Initialize the object; called before anything else. Returns true on success. 33 // Initialize the object; called before anything else. UI texts will be
32 virtual bool Init(); 34 // initialized according to the given locale. Returns true on success.
35 virtual bool Init(const std::string& locale);
36
33 // Show a stage indicator. Call immediately after Init(). 37 // Show a stage indicator. Call immediately after Init().
34 virtual void SetStage(int current, int max) = 0; 38 virtual void SetStage(int current, int max) = 0;
35 39
36 // After calling Init(), you can tell the UI what locale it is operating in.
37 virtual void SetLocale(const char* locale) = 0;
38
39 // Set the overall recovery state ("background image"). 40 // Set the overall recovery state ("background image").
40 enum Icon { NONE, INSTALLING_UPDATE, ERASING, NO_COMMAND, ERROR }; 41 enum Icon { NONE, INSTALLING_UPDATE, ERASING, NO_COMMAND, ERROR };
41 virtual void SetBackground(Icon icon) = 0; 42 virtual void SetBackground(Icon icon) = 0;
@@ -122,10 +123,14 @@ class RecoveryUI {
122 // statements will be displayed. 123 // statements will be displayed.
123 virtual void EndMenu() = 0; 124 virtual void EndMenu() = 0;
124 125
125protected: 126 protected:
126 void EnqueueKey(int key_code); 127 void EnqueueKey(int key_code);
127 128
128private: 129 // The locale that's used to show the rendered texts.
130 std::string locale_;
131 bool rtl_locale_;
132
133 private:
129 // Key event input queue 134 // Key event input queue
130 pthread_mutex_t key_queue_mutex; 135 pthread_mutex_t key_queue_mutex;
131 pthread_cond_t key_queue_cond; 136 pthread_cond_t key_queue_cond;
@@ -162,6 +167,8 @@ private:
162 167
163 static void* time_key_helper(void* cookie); 168 static void* time_key_helper(void* cookie);
164 void time_key(int key_code, int count); 169 void time_key(int key_code, int count);
170
171 void SetLocale(const std::string&);
165}; 172};
166 173
167#endif // RECOVERY_UI_H 174#endif // RECOVERY_UI_H
diff --git a/wear_ui.cpp b/wear_ui.cpp
index bdb0ef00..b4c63a5a 100644
--- a/wear_ui.cpp
+++ b/wear_ui.cpp
@@ -14,6 +14,8 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#include "wear_ui.h"
18
17#include <errno.h> 19#include <errno.h>
18#include <fcntl.h> 20#include <fcntl.h>
19#include <stdarg.h> 21#include <stdarg.h>
@@ -25,11 +27,11 @@
25#include <time.h> 27#include <time.h>
26#include <unistd.h> 28#include <unistd.h>
27 29
30#include <string>
28#include <vector> 31#include <vector>
29 32
30#include "common.h" 33#include "common.h"
31#include "device.h" 34#include "device.h"
32#include "wear_ui.h"
33#include "android-base/properties.h" 35#include "android-base/properties.h"
34#include "android-base/strings.h" 36#include "android-base/strings.h"
35#include "android-base/stringprintf.h" 37#include "android-base/stringprintf.h"
@@ -204,51 +206,48 @@ bool WearRecoveryUI::InitTextParams() {
204 return true; 206 return true;
205} 207}
206 208
207bool WearRecoveryUI::Init() { 209bool WearRecoveryUI::Init(const std::string& locale) {
208 if (!ScreenRecoveryUI::Init()) { 210 if (!ScreenRecoveryUI::Init(locale)) {
209 return false; 211 return false;
210 } 212 }
211 213
212 LoadBitmap("icon_error", &backgroundIcon[ERROR]); 214 LoadBitmap("icon_error", &backgroundIcon[ERROR]);
213 backgroundIcon[NO_COMMAND] = backgroundIcon[ERROR]; 215 backgroundIcon[NO_COMMAND] = backgroundIcon[ERROR];
214 216
215 // This leaves backgroundIcon[INSTALLING_UPDATE] and backgroundIcon[ERASING] 217 // This leaves backgroundIcon[INSTALLING_UPDATE] and backgroundIcon[ERASING]
216 // as NULL which is fine since draw_background_locked() doesn't use them. 218 // as NULL which is fine since draw_background_locked() doesn't use them.
217 219
218 return true; 220 return true;
219} 221}
220 222
221void WearRecoveryUI::SetStage(int current, int max) 223void WearRecoveryUI::SetStage(int current, int max) {}
222{
223}
224 224
225void WearRecoveryUI::Print(const char *fmt, ...) 225void WearRecoveryUI::Print(const char* fmt, ...) {
226{ 226 char buf[256];
227 char buf[256]; 227 va_list ap;
228 va_list ap; 228 va_start(ap, fmt);
229 va_start(ap, fmt); 229 vsnprintf(buf, 256, fmt, ap);
230 vsnprintf(buf, 256, fmt, ap); 230 va_end(ap);
231 va_end(ap);
232 231
233 fputs(buf, stdout); 232 fputs(buf, stdout);
234 233
235 // This can get called before ui_init(), so be careful. 234 // This can get called before ui_init(), so be careful.
236 pthread_mutex_lock(&updateMutex); 235 pthread_mutex_lock(&updateMutex);
237 if (text_rows_ > 0 && text_cols_ > 0) { 236 if (text_rows_ > 0 && text_cols_ > 0) {
238 char *ptr; 237 char* ptr;
239 for (ptr = buf; *ptr != '\0'; ++ptr) { 238 for (ptr = buf; *ptr != '\0'; ++ptr) {
240 if (*ptr == '\n' || text_col_ >= text_cols_) { 239 if (*ptr == '\n' || text_col_ >= text_cols_) {
241 text_[text_row_][text_col_] = '\0';
242 text_col_ = 0;
243 text_row_ = (text_row_ + 1) % text_rows_;
244 if (text_row_ == text_top_) text_top_ = (text_top_ + 1) % text_rows_;
245 }
246 if (*ptr != '\n') text_[text_row_][text_col_++] = *ptr;
247 }
248 text_[text_row_][text_col_] = '\0'; 240 text_[text_row_][text_col_] = '\0';
249 update_screen_locked(); 241 text_col_ = 0;
242 text_row_ = (text_row_ + 1) % text_rows_;
243 if (text_row_ == text_top_) text_top_ = (text_top_ + 1) % text_rows_;
244 }
245 if (*ptr != '\n') text_[text_row_][text_col_++] = *ptr;
250 } 246 }
251 pthread_mutex_unlock(&updateMutex); 247 text_[text_row_][text_col_] = '\0';
248 update_screen_locked();
249 }
250 pthread_mutex_unlock(&updateMutex);
252} 251}
253 252
254void WearRecoveryUI::StartMenu(const char* const * headers, const char* const * items, 253void WearRecoveryUI::StartMenu(const char* const * headers, const char* const * items,
diff --git a/wear_ui.h b/wear_ui.h
index 5ac6f49d..4cd852f2 100644
--- a/wear_ui.h
+++ b/wear_ui.h
@@ -19,11 +19,13 @@
19 19
20#include "screen_ui.h" 20#include "screen_ui.h"
21 21
22#include <string>
23
22class WearRecoveryUI : public ScreenRecoveryUI { 24class WearRecoveryUI : public ScreenRecoveryUI {
23 public: 25 public:
24 WearRecoveryUI(); 26 WearRecoveryUI();
25 27
26 bool Init() override; 28 bool Init(const std::string& locale) override;
27 29
28 void SetStage(int current, int max) override; 30 void SetStage(int current, int max) override;
29 31