Loading screen_ui.cpp +32 −20 Original line number Diff line number Diff line Loading @@ -54,8 +54,6 @@ static double now() { ScreenRecoveryUI::ScreenRecoveryUI() : currentIcon(NONE), locale(nullptr), intro_done(false), current_frame(0), progressBarType(EMPTY), progressScopeStart(0), progressScopeSize(0), Loading @@ -76,6 +74,8 @@ ScreenRecoveryUI::ScreenRecoveryUI() : file_viewer_text_(nullptr), intro_frames(0), loop_frames(0), current_frame(0), intro_done(false), animation_fps(30), // TODO: there's currently no way to infer this. stage(-1), max_stage(-1), Loading Loading @@ -448,9 +448,18 @@ void ScreenRecoveryUI::SetSystemUpdateText(bool security_update) { Redraw(); } void ScreenRecoveryUI::Init() { void ScreenRecoveryUI::InitTextParams() { gr_init(); gr_font_size(gr_sys_font(), &char_width_, &char_height_); text_rows_ = gr_fb_height() / char_height_; text_cols_ = gr_fb_width() / char_width_; } void ScreenRecoveryUI::Init() { RecoveryUI::Init(); InitTextParams(); density_ = static_cast<float>(property_get_int32("ro.sf.lcd_density", 160)) / 160.f; // Are we portrait or landscape? Loading @@ -458,10 +467,6 @@ void ScreenRecoveryUI::Init() { // Are we the large variant of our base layout? if (gr_fb_height() > PixelsFromDp(800)) ++layout_; gr_font_size(gr_sys_font(), &char_width_, &char_height_); text_rows_ = gr_fb_height() / char_height_; text_cols_ = gr_fb_width() / char_width_; text_ = Alloc2d(text_rows_, text_cols_ + 1); file_viewer_text_ = Alloc2d(text_rows_, text_cols_ + 1); menu_ = Alloc2d(text_rows_, text_cols_ + 1); Loading @@ -488,37 +493,44 @@ void ScreenRecoveryUI::Init() { LoadAnimation(); pthread_create(&progress_thread_, nullptr, ProgressThreadStartRoutine, this); RecoveryUI::Init(); } void ScreenRecoveryUI::LoadAnimation() { // How many frames of intro and loop do we have? std::unique_ptr<DIR, decltype(&closedir)> dir(opendir("/res/images"), closedir); dirent* de; std::vector<std::string> intro_frame_names; std::vector<std::string> loop_frame_names; while ((de = readdir(dir.get())) != nullptr) { int value; if (sscanf(de->d_name, "intro%d", &value) == 1 && intro_frames < (value + 1)) { intro_frames = value + 1; } else if (sscanf(de->d_name, "loop%d", &value) == 1 && loop_frames < (value + 1)) { loop_frames = value + 1; int value, num_chars; if (sscanf(de->d_name, "intro%d%n.png", &value, &num_chars) == 1) { intro_frame_names.emplace_back(de->d_name, num_chars); } else if (sscanf(de->d_name, "loop%d%n.png", &value, &num_chars) == 1) { loop_frame_names.emplace_back(de->d_name, num_chars); } } intro_frames = intro_frame_names.size(); loop_frames = loop_frame_names.size(); LOGD("Recovery animation intro_frames: %d, loop_frames: %d\n", intro_frames, loop_frames); // It's okay to not have an intro. if (intro_frames == 0) intro_done = true; // But you must have an animation. if (loop_frames == 0) abort(); std::sort(intro_frame_names.begin(), intro_frame_names.end()); std::sort(loop_frame_names.begin(), loop_frame_names.end()); introFrames = new GRSurface*[intro_frames]; for (int i = 0; i < intro_frames; ++i) { // TODO: remember the names above, so we don't have to hard-code the number of 0s. LoadBitmap(android::base::StringPrintf("intro%05d", i).c_str(), &introFrames[i]); for (size_t i = 0; i < intro_frames; i++) { LoadBitmap(intro_frame_names.at(i).c_str(), &introFrames[i]); } loopFrames = new GRSurface*[loop_frames]; for (int i = 0; i < loop_frames; ++i) { LoadBitmap(android::base::StringPrintf("loop%05d", i).c_str(), &loopFrames[i]); for (size_t i = 0; i < loop_frames; i++) { LoadBitmap(loop_frame_names.at(i).c_str(), &loopFrames[i]); } } Loading screen_ui.h +24 −21 Original line number Diff line number Diff line Loading @@ -37,16 +37,16 @@ class ScreenRecoveryUI : public RecoveryUI { void SetSystemUpdateText(bool security_update); // progress indicator void SetProgressType(ProgressType type); void ShowProgress(float portion, float seconds); void SetProgress(float fraction); void SetProgressType(ProgressType type) override; void ShowProgress(float portion, float seconds) override; void SetProgress(float fraction) override; void SetStage(int current, int max); void SetStage(int current, int max) override; // text log void ShowText(bool visible); bool IsTextVisible(); bool WasTextEverVisible(); void ShowText(bool visible) override; bool IsTextVisible() override; bool WasTextEverVisible() override; // printing messages void Print(const char* fmt, ...) __printflike(2, 3); Loading @@ -72,8 +72,6 @@ class ScreenRecoveryUI : public RecoveryUI { Icon currentIcon; const char* locale; bool intro_done; int current_frame; // The scale factor from dp to pixels. 1.0 for mdpi, 4.0 for xxxhdpi. float density_; Loading Loading @@ -123,8 +121,11 @@ class ScreenRecoveryUI : public RecoveryUI { pthread_t progress_thread_; // Number of intro frames and loop frames in the animation. int intro_frames; int loop_frames; size_t intro_frames; size_t loop_frames; size_t current_frame; bool intro_done; // Number of frames per sec (default: 30) for both parts of the animation. int animation_fps; Loading @@ -136,11 +137,13 @@ class ScreenRecoveryUI : public RecoveryUI { pthread_mutex_t updateMutex; bool rtl_locale; void draw_background_locked(); void draw_foreground_locked(); void draw_screen_locked(); void update_screen_locked(); void update_progress_locked(); virtual void InitTextParams(); virtual void draw_background_locked(); virtual void draw_foreground_locked(); virtual void draw_screen_locked(); virtual void update_screen_locked(); virtual void update_progress_locked(); GRSurface* GetCurrentFrame(); GRSurface* GetCurrentText(); Loading @@ -148,8 +151,8 @@ class ScreenRecoveryUI : public RecoveryUI { static void* ProgressThreadStartRoutine(void* data); void ProgressThreadLoop(); void ShowFile(FILE*); void PrintV(const char*, bool, va_list); virtual void ShowFile(FILE*); virtual void PrintV(const char*, bool, va_list); void PutChar(char); void ClearText(); Loading @@ -158,9 +161,9 @@ class ScreenRecoveryUI : public RecoveryUI { void LoadLocalizedBitmap(const char* filename, GRSurface** surface); int PixelsFromDp(int dp); int GetAnimationBaseline(); int GetProgressBaseline(); int GetTextBaseline(); virtual int GetAnimationBaseline(); virtual int GetProgressBaseline(); virtual int GetTextBaseline(); void DrawHorizontalRule(int* y); void DrawTextLine(int x, int* y, const char* line, bool bold); Loading wear_ui.cpp +77 −236 Original line number Diff line number Diff line Loading @@ -47,32 +47,13 @@ static double now() { } WearRecoveryUI::WearRecoveryUI() : progress_bar_height(3), progress_bar_width(200), progress_bar_y(259), outer_height(0), outer_width(0), menu_unusable_rows(0), intro_frames(22), loop_frames(60), animation_fps(30), currentIcon(NONE), intro_done(false), current_frame(0), progressBarType(EMPTY), progressScopeStart(0), progressScopeSize(0), progress(0), text_cols(0), text_rows(0), text_col(0), text_row(0), text_top(0), show_text(false), show_text_ever(false), show_menu(false), menu_items(0), menu_sel(0) { menu_unusable_rows(0) { intro_frames = 22; loop_frames = 60; animation_fps = 30; for (size_t i = 0; i < 5; i++) backgroundIcon[i] = NULL; Loading @@ -80,16 +61,22 @@ WearRecoveryUI::WearRecoveryUI() : self = this; } int WearRecoveryUI::GetProgressBaseline() { return progress_bar_y; } // Draw background frame on the screen. Does not flip pages. // Should only be called with updateMutex locked. void WearRecoveryUI::draw_background_locked(Icon icon) // TODO merge drawing routines with screen_ui void WearRecoveryUI::draw_background_locked() { pagesIdentical = false; gr_color(0, 0, 0, 255); gr_fill(0, 0, gr_fb_width(), gr_fb_height()); if (icon) { if (currentIcon != NONE) { GRSurface* surface; if (icon == INSTALLING_UPDATE || icon == ERASING) { if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) { if (!intro_done) { surface = introFrames[current_frame]; } else { Loading @@ -97,7 +84,7 @@ void WearRecoveryUI::draw_background_locked(Icon icon) } } else { surface = backgroundIcon[icon]; surface = backgroundIcon[currentIcon]; } int width = gr_get_width(surface); Loading @@ -110,36 +97,6 @@ void WearRecoveryUI::draw_background_locked(Icon icon) } } // Draw the progress bar (if any) on the screen. Does not flip pages. // Should only be called with updateMutex locked. void WearRecoveryUI::draw_progress_locked() { if (currentIcon == ERROR) return; if (progressBarType != DETERMINATE) return; int width = progress_bar_width; int height = progress_bar_height; int dx = (gr_fb_width() - width)/2; int dy = progress_bar_y; float p = progressScopeStart + progress * progressScopeSize; int pos = (int) (p * width); gr_color(0x43, 0x43, 0x43, 0xff); gr_fill(dx, dy, dx + width, dy + height); if (pos > 0) { gr_color(0x02, 0xa8, 0xf3, 255); if (rtl_locale) { // Fill the progress bar from right to left. gr_fill(dx + width - pos, dy, dx + width, dy + height); } else { // Fill the progress bar from left to right. gr_fill(dx, dy, dx + pos, dy + height); } } } static const char* HEADERS[] = { "Swipe up/down to move.", "Swipe left/right to select.", Loading @@ -147,13 +104,15 @@ static const char* HEADERS[] = { NULL }; // TODO merge drawing routines with screen_ui void WearRecoveryUI::draw_screen_locked() { draw_background_locked(currentIcon); draw_progress_locked(); char cur_selection_str[50]; if (show_text) { draw_background_locked(); if (!show_text) { draw_foreground_locked(); } else { SetColor(TEXT_FILL); gr_fill(0, 0, gr_fb_width(), gr_fb_height()); Loading Loading @@ -192,10 +151,12 @@ void WearRecoveryUI::draw_screen_locked() gr_fill(x, y-2, gr_fb_width()-x, y+char_height_+2); // white text of selected item SetColor(MENU_SEL_FG); if (menu[i][0]) gr_text(gr_sys_font(), x+4, y, menu[i], 1); if (menu_[i][0]) { gr_text(gr_sys_font(), x + 4, y, menu_[i], 1); } SetColor(MENU); } else if (menu[i][0]) { gr_text(gr_sys_font(), x+4, y, menu[i], 0); } else if (menu_[i][0]) { gr_text(gr_sys_font(), x + 4, y, menu_[i], 0); } y += char_height_+4; } Loading @@ -211,24 +172,18 @@ void WearRecoveryUI::draw_screen_locked() // screen, the bottom of the menu, or we've displayed the // entire text buffer. int ty; int row = (text_top+text_rows-1) % text_rows; int row = (text_top_ + text_rows_ - 1) % text_rows_; size_t count = 0; for (int ty = gr_fb_height() - char_height_ - outer_height; ty > y+2 && count < text_rows; ty > y + 2 && count < text_rows_; ty -= char_height_, ++count) { gr_text(gr_sys_font(), x+4, ty, text[row], 0); gr_text(gr_sys_font(), x+4, ty, text_[row], 0); --row; if (row < 0) row = text_rows-1; if (row < 0) row = text_rows_ - 1; } } } void WearRecoveryUI::update_screen_locked() { draw_screen_locked(); gr_flip(); } // Keeps the progress bar updated, even when the process is otherwise busy. void* WearRecoveryUI::progress_thread(void *cookie) { self->progress_loop(); Loading @@ -240,7 +195,7 @@ void WearRecoveryUI::progress_loop() { for (;;) { double start = now(); pthread_mutex_lock(&updateMutex); int redraw = 0; bool redraw = false; if ((currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) && !show_text) { Loading @@ -254,7 +209,7 @@ void WearRecoveryUI::progress_loop() { } else { current_frame = (current_frame + 1) % loop_frames; } redraw = 1; redraw = true; } // move the progress bar forward on timed intervals, if configured Loading @@ -265,12 +220,11 @@ void WearRecoveryUI::progress_loop() { if (p > 1.0) p = 1.0; if (p > progress) { progress = p; redraw = 1; redraw = true; } } if (redraw) update_screen_locked(); if (redraw) update_screen_locked(); pthread_mutex_unlock(&updateMutex); double end = now(); Loading @@ -281,93 +235,27 @@ void WearRecoveryUI::progress_loop() { } } void WearRecoveryUI::Init() { gr_init(); void WearRecoveryUI::InitTextParams() { ScreenRecoveryUI::InitTextParams(); text_cols_ = (gr_fb_width() - (outer_width * 2)) / char_width_; gr_font_size(gr_sys_font(), &char_width_, &char_height_); if (text_rows_ > kMaxRows) text_rows_ = kMaxRows; if (text_cols_ > kMaxCols) text_cols_ = kMaxCols; text_col = text_row = 0; text_rows = (gr_fb_height()) / char_height_; visible_text_rows = (gr_fb_height() - (outer_height * 2)) / char_height_; if (text_rows > kMaxRows) text_rows = kMaxRows; text_top = 1; } text_cols = (gr_fb_width() - (outer_width * 2)) / char_width_; if (text_cols > kMaxCols - 1) text_cols = kMaxCols - 1; void WearRecoveryUI::Init() { ScreenRecoveryUI::Init(); LoadBitmap("icon_installing", &backgroundIcon[INSTALLING_UPDATE]); backgroundIcon[ERASING] = backgroundIcon[INSTALLING_UPDATE]; LoadBitmap("icon_error", &backgroundIcon[ERROR]); backgroundIcon[NO_COMMAND] = backgroundIcon[ERROR]; introFrames = (GRSurface**)malloc(intro_frames * sizeof(GRSurface*)); for (int i = 0; i < intro_frames; ++i) { char filename[40]; sprintf(filename, "intro%02d", i); LoadBitmap(filename, introFrames + i); } loopFrames = (GRSurface**)malloc(loop_frames * sizeof(GRSurface*)); for (int i = 0; i < loop_frames; ++i) { char filename[40]; sprintf(filename, "loop%02d", i); LoadBitmap(filename, loopFrames + i); } pthread_create(&progress_t, NULL, progress_thread, NULL); RecoveryUI::Init(); } void WearRecoveryUI::SetBackground(Icon icon) { pthread_mutex_lock(&updateMutex); currentIcon = icon; update_screen_locked(); pthread_mutex_unlock(&updateMutex); } void WearRecoveryUI::SetProgressType(ProgressType type) { pthread_mutex_lock(&updateMutex); if (progressBarType != type) { progressBarType = type; } progressScopeStart = 0; progressScopeSize = 0; progress = 0; update_screen_locked(); pthread_mutex_unlock(&updateMutex); } void WearRecoveryUI::ShowProgress(float portion, float seconds) { pthread_mutex_lock(&updateMutex); progressBarType = DETERMINATE; progressScopeStart += progressScopeSize; progressScopeSize = portion; progressScopeTime = now(); progressScopeDuration = seconds; progress = 0; update_screen_locked(); pthread_mutex_unlock(&updateMutex); } void WearRecoveryUI::SetProgress(float fraction) { pthread_mutex_lock(&updateMutex); if (fraction < 0.0) fraction = 0.0; if (fraction > 1.0) fraction = 1.0; if (progressBarType == DETERMINATE && fraction > progress) { // Skip updates that aren't visibly different. int width = progress_bar_width; float scale = width * progressScopeSize; if ((int) (progress * scale) != (int) (fraction * scale)) { progress = fraction; update_screen_locked(); } } pthread_mutex_unlock(&updateMutex); } void WearRecoveryUI::SetStage(int current, int max) Loading @@ -386,18 +274,18 @@ void WearRecoveryUI::Print(const char *fmt, ...) // This can get called before ui_init(), so be careful. pthread_mutex_lock(&updateMutex); if (text_rows > 0 && text_cols > 0) { if (text_rows_ > 0 && text_cols_ > 0) { char *ptr; for (ptr = buf; *ptr != '\0'; ++ptr) { if (*ptr == '\n' || text_col >= text_cols) { text[text_row][text_col] = '\0'; text_col = 0; text_row = (text_row + 1) % text_rows; if (text_row == text_top) text_top = (text_top + 1) % text_rows; if (*ptr == '\n' || text_col_ >= text_cols_) { text_[text_row_][text_col_] = '\0'; text_col_ = 0; text_row_ = (text_row_ + 1) % text_rows_; if (text_row_ == text_top_) text_top_ = (text_top_ + 1) % text_rows_; } if (*ptr != '\n') text[text_row][text_col++] = *ptr; if (*ptr != '\n') text_[text_row_][text_col_++] = *ptr; } text[text_row][text_col] = '\0'; text_[text_row_][text_col_] = '\0'; update_screen_locked(); } pthread_mutex_unlock(&updateMutex); Loading @@ -406,20 +294,20 @@ void WearRecoveryUI::Print(const char *fmt, ...) void WearRecoveryUI::StartMenu(const char* const * headers, const char* const * items, int initial_selection) { pthread_mutex_lock(&updateMutex); if (text_rows > 0 && text_cols > 0) { if (text_rows_ > 0 && text_cols_ > 0) { menu_headers_ = headers; size_t i = 0; // "i < text_rows" is removed from the loop termination condition, // "i < text_rows_" is removed from the loop termination condition, // which is different from the one in ScreenRecoveryUI::StartMenu(). // Because WearRecoveryUI supports scrollable menu, it's fine to have // more entries than text_rows. The menu may be truncated otherwise. // more entries than text_rows_. The menu may be truncated otherwise. // Bug: 23752519 for (; items[i] != nullptr; i++) { strncpy(menu[i], items[i], text_cols - 1); menu[i][text_cols - 1] = '\0'; strncpy(menu_[i], items[i], text_cols_ - 1); menu_[i][text_cols_ - 1] = '\0'; } menu_items = i; show_menu = 1; show_menu = true; menu_sel = initial_selection; menu_start = 0; menu_end = visible_text_rows - 1 - menu_unusable_rows; Loading @@ -433,7 +321,7 @@ void WearRecoveryUI::StartMenu(const char* const * headers, const char* const * int WearRecoveryUI::SelectMenu(int sel) { int old_sel; pthread_mutex_lock(&updateMutex); if (show_menu > 0) { if (show_menu) { old_sel = menu_sel; menu_sel = sel; if (menu_sel < 0) menu_sel = 0; Loading @@ -452,53 +340,6 @@ int WearRecoveryUI::SelectMenu(int sel) { return sel; } void WearRecoveryUI::EndMenu() { int i; pthread_mutex_lock(&updateMutex); if (show_menu > 0 && text_rows > 0 && text_cols > 0) { show_menu = 0; update_screen_locked(); } pthread_mutex_unlock(&updateMutex); } bool WearRecoveryUI::IsTextVisible() { pthread_mutex_lock(&updateMutex); int visible = show_text; pthread_mutex_unlock(&updateMutex); return visible; } bool WearRecoveryUI::WasTextEverVisible() { pthread_mutex_lock(&updateMutex); int ever_visible = show_text_ever; pthread_mutex_unlock(&updateMutex); return ever_visible; } void WearRecoveryUI::ShowText(bool visible) { pthread_mutex_lock(&updateMutex); // Don't show text during ota install or factory reset if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) { pthread_mutex_unlock(&updateMutex); return; } show_text = visible; if (show_text) show_text_ever = 1; update_screen_locked(); pthread_mutex_unlock(&updateMutex); } void WearRecoveryUI::Redraw() { pthread_mutex_lock(&updateMutex); update_screen_locked(); pthread_mutex_unlock(&updateMutex); } void WearRecoveryUI::ShowFile(FILE* fp) { std::vector<off_t> offsets; offsets.push_back(ftello(fp)); Loading Loading @@ -538,12 +379,12 @@ void WearRecoveryUI::ShowFile(FILE* fp) { int ch = getc(fp); if (ch == EOF) { text_row = text_top = text_rows - 2; text_row_ = text_top_ = text_rows_ - 2; show_prompt = true; } else { PutChar(ch); if (text_col == 0 && text_row >= text_rows - 2) { text_top = text_row; if (text_col_ == 0 && text_row_ >= text_rows_ - 2) { text_top_ = text_row_; show_prompt = true; } } Loading @@ -552,10 +393,10 @@ void WearRecoveryUI::ShowFile(FILE* fp) { void WearRecoveryUI::PutChar(char ch) { pthread_mutex_lock(&updateMutex); if (ch != '\n') text[text_row][text_col++] = ch; if (ch == '\n' || text_col >= text_cols) { text_col = 0; ++text_row; if (ch != '\n') text_[text_row_][text_col_++] = ch; if (ch == '\n' || text_col_ >= text_cols_) { text_col_ = 0; ++text_row_; } pthread_mutex_unlock(&updateMutex); } Loading @@ -572,11 +413,11 @@ void WearRecoveryUI::ShowFile(const char* filename) { void WearRecoveryUI::ClearText() { pthread_mutex_lock(&updateMutex); text_col = 0; text_row = 0; text_top = 1; for (size_t i = 0; i < text_rows; ++i) { memset(text[i], 0, text_cols + 1); text_col_ = 0; text_row_ = 0; text_top_ = 1; for (size_t i = 0; i < text_rows_; ++i) { memset(text_[i], 0, text_cols_ + 1); } pthread_mutex_unlock(&updateMutex); } Loading @@ -597,17 +438,17 @@ void WearRecoveryUI::PrintV(const char* fmt, bool copy_to_stdout, va_list ap) { } pthread_mutex_lock(&updateMutex); if (text_rows > 0 && text_cols > 0) { if (text_rows_ > 0 && text_cols_ > 0) { for (const char* ptr = str.c_str(); *ptr != '\0'; ++ptr) { if (*ptr == '\n' || text_col >= text_cols) { text[text_row][text_col] = '\0'; text_col = 0; text_row = (text_row + 1) % text_rows; if (text_row == text_top) text_top = (text_top + 1) % text_rows; if (*ptr == '\n' || text_col_ >= text_cols_) { text_[text_row_][text_col_] = '\0'; text_col_ = 0; text_row_ = (text_row_ + 1) % text_rows_; if (text_row_ == text_top_) text_top_ = (text_top_ + 1) % text_rows_; } if (*ptr != '\n') text[text_row][text_col++] = *ptr; if (*ptr != '\n') text_[text_row_][text_col_++] = *ptr; } text[text_row][text_col] = '\0'; text_[text_row_][text_col_] = '\0'; update_screen_locked(); } pthread_mutex_unlock(&updateMutex); Loading wear_ui.h +15 −57 Original line number Diff line number Diff line Loading @@ -23,39 +23,22 @@ class WearRecoveryUI : public ScreenRecoveryUI { public: WearRecoveryUI(); void Init(); // overall recovery state ("background image") void SetBackground(Icon icon); void Init() override; // progress indicator void SetProgressType(ProgressType type); void ShowProgress(float portion, float seconds); void SetProgress(float fraction); void SetStage(int current, int max); // text log void ShowText(bool visible); bool IsTextVisible(); bool WasTextEverVisible(); void SetStage(int current, int max) override; // printing messages void Print(const char* fmt, ...); void PrintOnScreenOnly(const char* fmt, ...) __printflike(2, 3); void ShowFile(const char* filename); void ShowFile(FILE* fp); void Print(const char* fmt, ...) override; void PrintOnScreenOnly(const char* fmt, ...) override __printflike(2, 3); void ShowFile(const char* filename) override; void ShowFile(FILE* fp) override; // menu display void StartMenu(const char* const * headers, const char* const * items, int initial_selection); int SelectMenu(int sel); void EndMenu(); void Redraw(); int initial_selection) override; int SelectMenu(int sel) override; protected: int progress_bar_height, progress_bar_width; // progress bar vertical position, it's centered horizontally int progress_bar_y; Loading @@ -67,59 +50,34 @@ class WearRecoveryUI : public ScreenRecoveryUI { // that may otherwise go out of the screen. int menu_unusable_rows; // number of intro frames (default: 22) and loop frames (default: 60) int intro_frames; int loop_frames; // Number of frames per sec (default: 30) for both of intro and loop. int animation_fps; private: Icon currentIcon; int GetProgressBaseline() override; bool intro_done; void InitTextParams() override; int current_frame; void PrintV(const char*, bool, va_list) override; private: GRSurface* backgroundIcon[5]; GRSurface* *introFrames; GRSurface* *loopFrames; ProgressType progressBarType; float progressScopeStart, progressScopeSize, progress; double progressScopeTime, progressScopeDuration; static const int kMaxCols = 96; static const int kMaxRows = 96; // Log text overlay, displayed when a magic key is pressed char text[kMaxRows][kMaxCols]; size_t text_cols, text_rows; // Number of text rows seen on screen int visible_text_rows; size_t text_col, text_row, text_top; bool show_text; bool show_text_ever; // has show_text ever been true? char menu[kMaxRows][kMaxCols]; bool show_menu; const char* const* menu_headers_; int menu_items, menu_sel; int menu_start, menu_end; pthread_t progress_t; private: void draw_background_locked(Icon icon); void draw_background_locked() override; void draw_screen_locked() override; void draw_progress_locked(); void draw_screen_locked(); void update_screen_locked(); static void* progress_thread(void* cookie); void progress_loop(); void PutChar(char); void ClearText(); void PrintV(const char*, bool, va_list); }; #endif // RECOVERY_WEAR_UI_H Loading
screen_ui.cpp +32 −20 Original line number Diff line number Diff line Loading @@ -54,8 +54,6 @@ static double now() { ScreenRecoveryUI::ScreenRecoveryUI() : currentIcon(NONE), locale(nullptr), intro_done(false), current_frame(0), progressBarType(EMPTY), progressScopeStart(0), progressScopeSize(0), Loading @@ -76,6 +74,8 @@ ScreenRecoveryUI::ScreenRecoveryUI() : file_viewer_text_(nullptr), intro_frames(0), loop_frames(0), current_frame(0), intro_done(false), animation_fps(30), // TODO: there's currently no way to infer this. stage(-1), max_stage(-1), Loading Loading @@ -448,9 +448,18 @@ void ScreenRecoveryUI::SetSystemUpdateText(bool security_update) { Redraw(); } void ScreenRecoveryUI::Init() { void ScreenRecoveryUI::InitTextParams() { gr_init(); gr_font_size(gr_sys_font(), &char_width_, &char_height_); text_rows_ = gr_fb_height() / char_height_; text_cols_ = gr_fb_width() / char_width_; } void ScreenRecoveryUI::Init() { RecoveryUI::Init(); InitTextParams(); density_ = static_cast<float>(property_get_int32("ro.sf.lcd_density", 160)) / 160.f; // Are we portrait or landscape? Loading @@ -458,10 +467,6 @@ void ScreenRecoveryUI::Init() { // Are we the large variant of our base layout? if (gr_fb_height() > PixelsFromDp(800)) ++layout_; gr_font_size(gr_sys_font(), &char_width_, &char_height_); text_rows_ = gr_fb_height() / char_height_; text_cols_ = gr_fb_width() / char_width_; text_ = Alloc2d(text_rows_, text_cols_ + 1); file_viewer_text_ = Alloc2d(text_rows_, text_cols_ + 1); menu_ = Alloc2d(text_rows_, text_cols_ + 1); Loading @@ -488,37 +493,44 @@ void ScreenRecoveryUI::Init() { LoadAnimation(); pthread_create(&progress_thread_, nullptr, ProgressThreadStartRoutine, this); RecoveryUI::Init(); } void ScreenRecoveryUI::LoadAnimation() { // How many frames of intro and loop do we have? std::unique_ptr<DIR, decltype(&closedir)> dir(opendir("/res/images"), closedir); dirent* de; std::vector<std::string> intro_frame_names; std::vector<std::string> loop_frame_names; while ((de = readdir(dir.get())) != nullptr) { int value; if (sscanf(de->d_name, "intro%d", &value) == 1 && intro_frames < (value + 1)) { intro_frames = value + 1; } else if (sscanf(de->d_name, "loop%d", &value) == 1 && loop_frames < (value + 1)) { loop_frames = value + 1; int value, num_chars; if (sscanf(de->d_name, "intro%d%n.png", &value, &num_chars) == 1) { intro_frame_names.emplace_back(de->d_name, num_chars); } else if (sscanf(de->d_name, "loop%d%n.png", &value, &num_chars) == 1) { loop_frame_names.emplace_back(de->d_name, num_chars); } } intro_frames = intro_frame_names.size(); loop_frames = loop_frame_names.size(); LOGD("Recovery animation intro_frames: %d, loop_frames: %d\n", intro_frames, loop_frames); // It's okay to not have an intro. if (intro_frames == 0) intro_done = true; // But you must have an animation. if (loop_frames == 0) abort(); std::sort(intro_frame_names.begin(), intro_frame_names.end()); std::sort(loop_frame_names.begin(), loop_frame_names.end()); introFrames = new GRSurface*[intro_frames]; for (int i = 0; i < intro_frames; ++i) { // TODO: remember the names above, so we don't have to hard-code the number of 0s. LoadBitmap(android::base::StringPrintf("intro%05d", i).c_str(), &introFrames[i]); for (size_t i = 0; i < intro_frames; i++) { LoadBitmap(intro_frame_names.at(i).c_str(), &introFrames[i]); } loopFrames = new GRSurface*[loop_frames]; for (int i = 0; i < loop_frames; ++i) { LoadBitmap(android::base::StringPrintf("loop%05d", i).c_str(), &loopFrames[i]); for (size_t i = 0; i < loop_frames; i++) { LoadBitmap(loop_frame_names.at(i).c_str(), &loopFrames[i]); } } Loading
screen_ui.h +24 −21 Original line number Diff line number Diff line Loading @@ -37,16 +37,16 @@ class ScreenRecoveryUI : public RecoveryUI { void SetSystemUpdateText(bool security_update); // progress indicator void SetProgressType(ProgressType type); void ShowProgress(float portion, float seconds); void SetProgress(float fraction); void SetProgressType(ProgressType type) override; void ShowProgress(float portion, float seconds) override; void SetProgress(float fraction) override; void SetStage(int current, int max); void SetStage(int current, int max) override; // text log void ShowText(bool visible); bool IsTextVisible(); bool WasTextEverVisible(); void ShowText(bool visible) override; bool IsTextVisible() override; bool WasTextEverVisible() override; // printing messages void Print(const char* fmt, ...) __printflike(2, 3); Loading @@ -72,8 +72,6 @@ class ScreenRecoveryUI : public RecoveryUI { Icon currentIcon; const char* locale; bool intro_done; int current_frame; // The scale factor from dp to pixels. 1.0 for mdpi, 4.0 for xxxhdpi. float density_; Loading Loading @@ -123,8 +121,11 @@ class ScreenRecoveryUI : public RecoveryUI { pthread_t progress_thread_; // Number of intro frames and loop frames in the animation. int intro_frames; int loop_frames; size_t intro_frames; size_t loop_frames; size_t current_frame; bool intro_done; // Number of frames per sec (default: 30) for both parts of the animation. int animation_fps; Loading @@ -136,11 +137,13 @@ class ScreenRecoveryUI : public RecoveryUI { pthread_mutex_t updateMutex; bool rtl_locale; void draw_background_locked(); void draw_foreground_locked(); void draw_screen_locked(); void update_screen_locked(); void update_progress_locked(); virtual void InitTextParams(); virtual void draw_background_locked(); virtual void draw_foreground_locked(); virtual void draw_screen_locked(); virtual void update_screen_locked(); virtual void update_progress_locked(); GRSurface* GetCurrentFrame(); GRSurface* GetCurrentText(); Loading @@ -148,8 +151,8 @@ class ScreenRecoveryUI : public RecoveryUI { static void* ProgressThreadStartRoutine(void* data); void ProgressThreadLoop(); void ShowFile(FILE*); void PrintV(const char*, bool, va_list); virtual void ShowFile(FILE*); virtual void PrintV(const char*, bool, va_list); void PutChar(char); void ClearText(); Loading @@ -158,9 +161,9 @@ class ScreenRecoveryUI : public RecoveryUI { void LoadLocalizedBitmap(const char* filename, GRSurface** surface); int PixelsFromDp(int dp); int GetAnimationBaseline(); int GetProgressBaseline(); int GetTextBaseline(); virtual int GetAnimationBaseline(); virtual int GetProgressBaseline(); virtual int GetTextBaseline(); void DrawHorizontalRule(int* y); void DrawTextLine(int x, int* y, const char* line, bool bold); Loading
wear_ui.cpp +77 −236 Original line number Diff line number Diff line Loading @@ -47,32 +47,13 @@ static double now() { } WearRecoveryUI::WearRecoveryUI() : progress_bar_height(3), progress_bar_width(200), progress_bar_y(259), outer_height(0), outer_width(0), menu_unusable_rows(0), intro_frames(22), loop_frames(60), animation_fps(30), currentIcon(NONE), intro_done(false), current_frame(0), progressBarType(EMPTY), progressScopeStart(0), progressScopeSize(0), progress(0), text_cols(0), text_rows(0), text_col(0), text_row(0), text_top(0), show_text(false), show_text_ever(false), show_menu(false), menu_items(0), menu_sel(0) { menu_unusable_rows(0) { intro_frames = 22; loop_frames = 60; animation_fps = 30; for (size_t i = 0; i < 5; i++) backgroundIcon[i] = NULL; Loading @@ -80,16 +61,22 @@ WearRecoveryUI::WearRecoveryUI() : self = this; } int WearRecoveryUI::GetProgressBaseline() { return progress_bar_y; } // Draw background frame on the screen. Does not flip pages. // Should only be called with updateMutex locked. void WearRecoveryUI::draw_background_locked(Icon icon) // TODO merge drawing routines with screen_ui void WearRecoveryUI::draw_background_locked() { pagesIdentical = false; gr_color(0, 0, 0, 255); gr_fill(0, 0, gr_fb_width(), gr_fb_height()); if (icon) { if (currentIcon != NONE) { GRSurface* surface; if (icon == INSTALLING_UPDATE || icon == ERASING) { if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) { if (!intro_done) { surface = introFrames[current_frame]; } else { Loading @@ -97,7 +84,7 @@ void WearRecoveryUI::draw_background_locked(Icon icon) } } else { surface = backgroundIcon[icon]; surface = backgroundIcon[currentIcon]; } int width = gr_get_width(surface); Loading @@ -110,36 +97,6 @@ void WearRecoveryUI::draw_background_locked(Icon icon) } } // Draw the progress bar (if any) on the screen. Does not flip pages. // Should only be called with updateMutex locked. void WearRecoveryUI::draw_progress_locked() { if (currentIcon == ERROR) return; if (progressBarType != DETERMINATE) return; int width = progress_bar_width; int height = progress_bar_height; int dx = (gr_fb_width() - width)/2; int dy = progress_bar_y; float p = progressScopeStart + progress * progressScopeSize; int pos = (int) (p * width); gr_color(0x43, 0x43, 0x43, 0xff); gr_fill(dx, dy, dx + width, dy + height); if (pos > 0) { gr_color(0x02, 0xa8, 0xf3, 255); if (rtl_locale) { // Fill the progress bar from right to left. gr_fill(dx + width - pos, dy, dx + width, dy + height); } else { // Fill the progress bar from left to right. gr_fill(dx, dy, dx + pos, dy + height); } } } static const char* HEADERS[] = { "Swipe up/down to move.", "Swipe left/right to select.", Loading @@ -147,13 +104,15 @@ static const char* HEADERS[] = { NULL }; // TODO merge drawing routines with screen_ui void WearRecoveryUI::draw_screen_locked() { draw_background_locked(currentIcon); draw_progress_locked(); char cur_selection_str[50]; if (show_text) { draw_background_locked(); if (!show_text) { draw_foreground_locked(); } else { SetColor(TEXT_FILL); gr_fill(0, 0, gr_fb_width(), gr_fb_height()); Loading Loading @@ -192,10 +151,12 @@ void WearRecoveryUI::draw_screen_locked() gr_fill(x, y-2, gr_fb_width()-x, y+char_height_+2); // white text of selected item SetColor(MENU_SEL_FG); if (menu[i][0]) gr_text(gr_sys_font(), x+4, y, menu[i], 1); if (menu_[i][0]) { gr_text(gr_sys_font(), x + 4, y, menu_[i], 1); } SetColor(MENU); } else if (menu[i][0]) { gr_text(gr_sys_font(), x+4, y, menu[i], 0); } else if (menu_[i][0]) { gr_text(gr_sys_font(), x + 4, y, menu_[i], 0); } y += char_height_+4; } Loading @@ -211,24 +172,18 @@ void WearRecoveryUI::draw_screen_locked() // screen, the bottom of the menu, or we've displayed the // entire text buffer. int ty; int row = (text_top+text_rows-1) % text_rows; int row = (text_top_ + text_rows_ - 1) % text_rows_; size_t count = 0; for (int ty = gr_fb_height() - char_height_ - outer_height; ty > y+2 && count < text_rows; ty > y + 2 && count < text_rows_; ty -= char_height_, ++count) { gr_text(gr_sys_font(), x+4, ty, text[row], 0); gr_text(gr_sys_font(), x+4, ty, text_[row], 0); --row; if (row < 0) row = text_rows-1; if (row < 0) row = text_rows_ - 1; } } } void WearRecoveryUI::update_screen_locked() { draw_screen_locked(); gr_flip(); } // Keeps the progress bar updated, even when the process is otherwise busy. void* WearRecoveryUI::progress_thread(void *cookie) { self->progress_loop(); Loading @@ -240,7 +195,7 @@ void WearRecoveryUI::progress_loop() { for (;;) { double start = now(); pthread_mutex_lock(&updateMutex); int redraw = 0; bool redraw = false; if ((currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) && !show_text) { Loading @@ -254,7 +209,7 @@ void WearRecoveryUI::progress_loop() { } else { current_frame = (current_frame + 1) % loop_frames; } redraw = 1; redraw = true; } // move the progress bar forward on timed intervals, if configured Loading @@ -265,12 +220,11 @@ void WearRecoveryUI::progress_loop() { if (p > 1.0) p = 1.0; if (p > progress) { progress = p; redraw = 1; redraw = true; } } if (redraw) update_screen_locked(); if (redraw) update_screen_locked(); pthread_mutex_unlock(&updateMutex); double end = now(); Loading @@ -281,93 +235,27 @@ void WearRecoveryUI::progress_loop() { } } void WearRecoveryUI::Init() { gr_init(); void WearRecoveryUI::InitTextParams() { ScreenRecoveryUI::InitTextParams(); text_cols_ = (gr_fb_width() - (outer_width * 2)) / char_width_; gr_font_size(gr_sys_font(), &char_width_, &char_height_); if (text_rows_ > kMaxRows) text_rows_ = kMaxRows; if (text_cols_ > kMaxCols) text_cols_ = kMaxCols; text_col = text_row = 0; text_rows = (gr_fb_height()) / char_height_; visible_text_rows = (gr_fb_height() - (outer_height * 2)) / char_height_; if (text_rows > kMaxRows) text_rows = kMaxRows; text_top = 1; } text_cols = (gr_fb_width() - (outer_width * 2)) / char_width_; if (text_cols > kMaxCols - 1) text_cols = kMaxCols - 1; void WearRecoveryUI::Init() { ScreenRecoveryUI::Init(); LoadBitmap("icon_installing", &backgroundIcon[INSTALLING_UPDATE]); backgroundIcon[ERASING] = backgroundIcon[INSTALLING_UPDATE]; LoadBitmap("icon_error", &backgroundIcon[ERROR]); backgroundIcon[NO_COMMAND] = backgroundIcon[ERROR]; introFrames = (GRSurface**)malloc(intro_frames * sizeof(GRSurface*)); for (int i = 0; i < intro_frames; ++i) { char filename[40]; sprintf(filename, "intro%02d", i); LoadBitmap(filename, introFrames + i); } loopFrames = (GRSurface**)malloc(loop_frames * sizeof(GRSurface*)); for (int i = 0; i < loop_frames; ++i) { char filename[40]; sprintf(filename, "loop%02d", i); LoadBitmap(filename, loopFrames + i); } pthread_create(&progress_t, NULL, progress_thread, NULL); RecoveryUI::Init(); } void WearRecoveryUI::SetBackground(Icon icon) { pthread_mutex_lock(&updateMutex); currentIcon = icon; update_screen_locked(); pthread_mutex_unlock(&updateMutex); } void WearRecoveryUI::SetProgressType(ProgressType type) { pthread_mutex_lock(&updateMutex); if (progressBarType != type) { progressBarType = type; } progressScopeStart = 0; progressScopeSize = 0; progress = 0; update_screen_locked(); pthread_mutex_unlock(&updateMutex); } void WearRecoveryUI::ShowProgress(float portion, float seconds) { pthread_mutex_lock(&updateMutex); progressBarType = DETERMINATE; progressScopeStart += progressScopeSize; progressScopeSize = portion; progressScopeTime = now(); progressScopeDuration = seconds; progress = 0; update_screen_locked(); pthread_mutex_unlock(&updateMutex); } void WearRecoveryUI::SetProgress(float fraction) { pthread_mutex_lock(&updateMutex); if (fraction < 0.0) fraction = 0.0; if (fraction > 1.0) fraction = 1.0; if (progressBarType == DETERMINATE && fraction > progress) { // Skip updates that aren't visibly different. int width = progress_bar_width; float scale = width * progressScopeSize; if ((int) (progress * scale) != (int) (fraction * scale)) { progress = fraction; update_screen_locked(); } } pthread_mutex_unlock(&updateMutex); } void WearRecoveryUI::SetStage(int current, int max) Loading @@ -386,18 +274,18 @@ void WearRecoveryUI::Print(const char *fmt, ...) // This can get called before ui_init(), so be careful. pthread_mutex_lock(&updateMutex); if (text_rows > 0 && text_cols > 0) { if (text_rows_ > 0 && text_cols_ > 0) { char *ptr; for (ptr = buf; *ptr != '\0'; ++ptr) { if (*ptr == '\n' || text_col >= text_cols) { text[text_row][text_col] = '\0'; text_col = 0; text_row = (text_row + 1) % text_rows; if (text_row == text_top) text_top = (text_top + 1) % text_rows; if (*ptr == '\n' || text_col_ >= text_cols_) { text_[text_row_][text_col_] = '\0'; text_col_ = 0; text_row_ = (text_row_ + 1) % text_rows_; if (text_row_ == text_top_) text_top_ = (text_top_ + 1) % text_rows_; } if (*ptr != '\n') text[text_row][text_col++] = *ptr; if (*ptr != '\n') text_[text_row_][text_col_++] = *ptr; } text[text_row][text_col] = '\0'; text_[text_row_][text_col_] = '\0'; update_screen_locked(); } pthread_mutex_unlock(&updateMutex); Loading @@ -406,20 +294,20 @@ void WearRecoveryUI::Print(const char *fmt, ...) void WearRecoveryUI::StartMenu(const char* const * headers, const char* const * items, int initial_selection) { pthread_mutex_lock(&updateMutex); if (text_rows > 0 && text_cols > 0) { if (text_rows_ > 0 && text_cols_ > 0) { menu_headers_ = headers; size_t i = 0; // "i < text_rows" is removed from the loop termination condition, // "i < text_rows_" is removed from the loop termination condition, // which is different from the one in ScreenRecoveryUI::StartMenu(). // Because WearRecoveryUI supports scrollable menu, it's fine to have // more entries than text_rows. The menu may be truncated otherwise. // more entries than text_rows_. The menu may be truncated otherwise. // Bug: 23752519 for (; items[i] != nullptr; i++) { strncpy(menu[i], items[i], text_cols - 1); menu[i][text_cols - 1] = '\0'; strncpy(menu_[i], items[i], text_cols_ - 1); menu_[i][text_cols_ - 1] = '\0'; } menu_items = i; show_menu = 1; show_menu = true; menu_sel = initial_selection; menu_start = 0; menu_end = visible_text_rows - 1 - menu_unusable_rows; Loading @@ -433,7 +321,7 @@ void WearRecoveryUI::StartMenu(const char* const * headers, const char* const * int WearRecoveryUI::SelectMenu(int sel) { int old_sel; pthread_mutex_lock(&updateMutex); if (show_menu > 0) { if (show_menu) { old_sel = menu_sel; menu_sel = sel; if (menu_sel < 0) menu_sel = 0; Loading @@ -452,53 +340,6 @@ int WearRecoveryUI::SelectMenu(int sel) { return sel; } void WearRecoveryUI::EndMenu() { int i; pthread_mutex_lock(&updateMutex); if (show_menu > 0 && text_rows > 0 && text_cols > 0) { show_menu = 0; update_screen_locked(); } pthread_mutex_unlock(&updateMutex); } bool WearRecoveryUI::IsTextVisible() { pthread_mutex_lock(&updateMutex); int visible = show_text; pthread_mutex_unlock(&updateMutex); return visible; } bool WearRecoveryUI::WasTextEverVisible() { pthread_mutex_lock(&updateMutex); int ever_visible = show_text_ever; pthread_mutex_unlock(&updateMutex); return ever_visible; } void WearRecoveryUI::ShowText(bool visible) { pthread_mutex_lock(&updateMutex); // Don't show text during ota install or factory reset if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) { pthread_mutex_unlock(&updateMutex); return; } show_text = visible; if (show_text) show_text_ever = 1; update_screen_locked(); pthread_mutex_unlock(&updateMutex); } void WearRecoveryUI::Redraw() { pthread_mutex_lock(&updateMutex); update_screen_locked(); pthread_mutex_unlock(&updateMutex); } void WearRecoveryUI::ShowFile(FILE* fp) { std::vector<off_t> offsets; offsets.push_back(ftello(fp)); Loading Loading @@ -538,12 +379,12 @@ void WearRecoveryUI::ShowFile(FILE* fp) { int ch = getc(fp); if (ch == EOF) { text_row = text_top = text_rows - 2; text_row_ = text_top_ = text_rows_ - 2; show_prompt = true; } else { PutChar(ch); if (text_col == 0 && text_row >= text_rows - 2) { text_top = text_row; if (text_col_ == 0 && text_row_ >= text_rows_ - 2) { text_top_ = text_row_; show_prompt = true; } } Loading @@ -552,10 +393,10 @@ void WearRecoveryUI::ShowFile(FILE* fp) { void WearRecoveryUI::PutChar(char ch) { pthread_mutex_lock(&updateMutex); if (ch != '\n') text[text_row][text_col++] = ch; if (ch == '\n' || text_col >= text_cols) { text_col = 0; ++text_row; if (ch != '\n') text_[text_row_][text_col_++] = ch; if (ch == '\n' || text_col_ >= text_cols_) { text_col_ = 0; ++text_row_; } pthread_mutex_unlock(&updateMutex); } Loading @@ -572,11 +413,11 @@ void WearRecoveryUI::ShowFile(const char* filename) { void WearRecoveryUI::ClearText() { pthread_mutex_lock(&updateMutex); text_col = 0; text_row = 0; text_top = 1; for (size_t i = 0; i < text_rows; ++i) { memset(text[i], 0, text_cols + 1); text_col_ = 0; text_row_ = 0; text_top_ = 1; for (size_t i = 0; i < text_rows_; ++i) { memset(text_[i], 0, text_cols_ + 1); } pthread_mutex_unlock(&updateMutex); } Loading @@ -597,17 +438,17 @@ void WearRecoveryUI::PrintV(const char* fmt, bool copy_to_stdout, va_list ap) { } pthread_mutex_lock(&updateMutex); if (text_rows > 0 && text_cols > 0) { if (text_rows_ > 0 && text_cols_ > 0) { for (const char* ptr = str.c_str(); *ptr != '\0'; ++ptr) { if (*ptr == '\n' || text_col >= text_cols) { text[text_row][text_col] = '\0'; text_col = 0; text_row = (text_row + 1) % text_rows; if (text_row == text_top) text_top = (text_top + 1) % text_rows; if (*ptr == '\n' || text_col_ >= text_cols_) { text_[text_row_][text_col_] = '\0'; text_col_ = 0; text_row_ = (text_row_ + 1) % text_rows_; if (text_row_ == text_top_) text_top_ = (text_top_ + 1) % text_rows_; } if (*ptr != '\n') text[text_row][text_col++] = *ptr; if (*ptr != '\n') text_[text_row_][text_col_++] = *ptr; } text[text_row][text_col] = '\0'; text_[text_row_][text_col_] = '\0'; update_screen_locked(); } pthread_mutex_unlock(&updateMutex); Loading
wear_ui.h +15 −57 Original line number Diff line number Diff line Loading @@ -23,39 +23,22 @@ class WearRecoveryUI : public ScreenRecoveryUI { public: WearRecoveryUI(); void Init(); // overall recovery state ("background image") void SetBackground(Icon icon); void Init() override; // progress indicator void SetProgressType(ProgressType type); void ShowProgress(float portion, float seconds); void SetProgress(float fraction); void SetStage(int current, int max); // text log void ShowText(bool visible); bool IsTextVisible(); bool WasTextEverVisible(); void SetStage(int current, int max) override; // printing messages void Print(const char* fmt, ...); void PrintOnScreenOnly(const char* fmt, ...) __printflike(2, 3); void ShowFile(const char* filename); void ShowFile(FILE* fp); void Print(const char* fmt, ...) override; void PrintOnScreenOnly(const char* fmt, ...) override __printflike(2, 3); void ShowFile(const char* filename) override; void ShowFile(FILE* fp) override; // menu display void StartMenu(const char* const * headers, const char* const * items, int initial_selection); int SelectMenu(int sel); void EndMenu(); void Redraw(); int initial_selection) override; int SelectMenu(int sel) override; protected: int progress_bar_height, progress_bar_width; // progress bar vertical position, it's centered horizontally int progress_bar_y; Loading @@ -67,59 +50,34 @@ class WearRecoveryUI : public ScreenRecoveryUI { // that may otherwise go out of the screen. int menu_unusable_rows; // number of intro frames (default: 22) and loop frames (default: 60) int intro_frames; int loop_frames; // Number of frames per sec (default: 30) for both of intro and loop. int animation_fps; private: Icon currentIcon; int GetProgressBaseline() override; bool intro_done; void InitTextParams() override; int current_frame; void PrintV(const char*, bool, va_list) override; private: GRSurface* backgroundIcon[5]; GRSurface* *introFrames; GRSurface* *loopFrames; ProgressType progressBarType; float progressScopeStart, progressScopeSize, progress; double progressScopeTime, progressScopeDuration; static const int kMaxCols = 96; static const int kMaxRows = 96; // Log text overlay, displayed when a magic key is pressed char text[kMaxRows][kMaxCols]; size_t text_cols, text_rows; // Number of text rows seen on screen int visible_text_rows; size_t text_col, text_row, text_top; bool show_text; bool show_text_ever; // has show_text ever been true? char menu[kMaxRows][kMaxCols]; bool show_menu; const char* const* menu_headers_; int menu_items, menu_sel; int menu_start, menu_end; pthread_t progress_t; private: void draw_background_locked(Icon icon); void draw_background_locked() override; void draw_screen_locked() override; void draw_progress_locked(); void draw_screen_locked(); void update_screen_locked(); static void* progress_thread(void* cookie); void progress_loop(); void PutChar(char); void ClearText(); void PrintV(const char*, bool, va_list); }; #endif // RECOVERY_WEAR_UI_H