diff options
Diffstat (limited to 'screen_ui.cpp')
-rw-r--r-- | screen_ui.cpp | 303 |
1 files changed, 154 insertions, 149 deletions
diff --git a/screen_ui.cpp b/screen_ui.cpp index fab348964..706877b4d 100644 --- a/screen_ui.cpp +++ b/screen_ui.cpp @@ -29,6 +29,7 @@ #include <time.h> #include <unistd.h> +#include <string> #include <vector> #include <android-base/logging.h> @@ -51,37 +52,34 @@ static double now() { return tv.tv_sec + tv.tv_usec / 1000000.0; } -ScreenRecoveryUI::ScreenRecoveryUI() : - currentIcon(NONE), - locale(nullptr), - intro_done(false), - current_frame(0), - progressBarType(EMPTY), - progressScopeStart(0), - progressScopeSize(0), - progress(0), - pagesIdentical(false), - text_cols_(0), - text_rows_(0), - text_(nullptr), - text_col_(0), - text_row_(0), - text_top_(0), - show_text(false), - show_text_ever(false), - menu_(nullptr), - show_menu(false), - menu_items(0), - menu_sel(0), - file_viewer_text_(nullptr), - intro_frames(0), - loop_frames(0), - animation_fps(30), // TODO: there's currently no way to infer this. - stage(-1), - max_stage(-1), - updateMutex(PTHREAD_MUTEX_INITIALIZER), - rtl_locale(false) { -} +ScreenRecoveryUI::ScreenRecoveryUI() + : currentIcon(NONE), + progressBarType(EMPTY), + progressScopeStart(0), + progressScopeSize(0), + progress(0), + pagesIdentical(false), + text_cols_(0), + text_rows_(0), + text_(nullptr), + text_col_(0), + text_row_(0), + text_top_(0), + show_text(false), + show_text_ever(false), + menu_(nullptr), + show_menu(false), + menu_items(0), + menu_sel(0), + 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), + updateMutex(PTHREAD_MUTEX_INITIALIZER) {} GRSurface* ScreenRecoveryUI::GetCurrentFrame() { if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) { @@ -106,29 +104,41 @@ int ScreenRecoveryUI::PixelsFromDp(int dp) { // Here's the intended layout: -// | regular large -// ---------+-------------------- -// | 220dp 366dp -// icon | (200dp) (200dp) -// | 68dp 68dp -// text | (14sp) (14sp) -// | 32dp 32dp -// progress | (2dp) (2dp) -// | 194dp 340dp +// | portrait large landscape large +// ---------+------------------------------------------------- +// gap | 220dp 366dp 142dp 284dp +// icon | (200dp) +// gap | 68dp 68dp 56dp 112dp +// text | (14sp) +// gap | 32dp 32dp 26dp 52dp +// progress | (2dp) +// gap | 194dp 340dp 131dp 262dp // Note that "baseline" is actually the *top* of each icon (because that's how our drawing // routines work), so that's the more useful measurement for calling code. +enum Layout { PORTRAIT = 0, PORTRAIT_LARGE = 1, LANDSCAPE = 2, LANDSCAPE_LARGE = 3, LAYOUT_MAX }; +enum Dimension { PROGRESS = 0, TEXT = 1, ICON = 2, DIMENSION_MAX }; +static constexpr int kLayouts[LAYOUT_MAX][DIMENSION_MAX] = { + { 194, 32, 68, }, // PORTRAIT + { 340, 32, 68, }, // PORTRAIT_LARGE + { 131, 26, 56, }, // LANDSCAPE + { 262, 52, 112, }, // LANDSCAPE_LARGE +}; + int ScreenRecoveryUI::GetAnimationBaseline() { - return GetTextBaseline() - PixelsFromDp(68) - gr_get_height(loopFrames[0]); + return GetTextBaseline() - PixelsFromDp(kLayouts[layout_][ICON]) - + gr_get_height(loopFrames[0]); } int ScreenRecoveryUI::GetTextBaseline() { - return GetProgressBaseline() - PixelsFromDp(32) - gr_get_height(installing_text); + return GetProgressBaseline() - PixelsFromDp(kLayouts[layout_][TEXT]) - + gr_get_height(installing_text); } int ScreenRecoveryUI::GetProgressBaseline() { - return gr_fb_height() - PixelsFromDp(is_large_ ? 340 : 194) - gr_get_height(progressBarFill); + return gr_fb_height() - PixelsFromDp(kLayouts[layout_][PROGRESS]) - + gr_get_height(progressBarFill); } // Clear the screen and draw the currently selected background icon (if any). @@ -163,51 +173,50 @@ void ScreenRecoveryUI::draw_background_locked() { // Does not flip pages. // Should only be called with updateMutex locked. void ScreenRecoveryUI::draw_foreground_locked() { - if (currentIcon != NONE) { - GRSurface* frame = GetCurrentFrame(); - int frame_width = gr_get_width(frame); - int frame_height = gr_get_height(frame); - int frame_x = (gr_fb_width() - frame_width) / 2; - int frame_y = GetAnimationBaseline(); - gr_blit(frame, 0, 0, frame_width, frame_height, frame_x, frame_y); - } - - if (progressBarType != EMPTY) { - int width = gr_get_width(progressBarEmpty); - int height = gr_get_height(progressBarEmpty); - - int progress_x = (gr_fb_width() - width)/2; - int progress_y = GetProgressBaseline(); - - // Erase behind the progress bar (in case this was a progress-only update) - gr_color(0, 0, 0, 255); - gr_fill(progress_x, progress_y, width, height); + if (currentIcon != NONE) { + GRSurface* frame = GetCurrentFrame(); + int frame_width = gr_get_width(frame); + int frame_height = gr_get_height(frame); + int frame_x = (gr_fb_width() - frame_width) / 2; + int frame_y = GetAnimationBaseline(); + gr_blit(frame, 0, 0, frame_width, frame_height, frame_x, frame_y); + } + + if (progressBarType != EMPTY) { + int width = gr_get_width(progressBarEmpty); + int height = gr_get_height(progressBarEmpty); + + int progress_x = (gr_fb_width() - width) / 2; + int progress_y = GetProgressBaseline(); + + // Erase behind the progress bar (in case this was a progress-only update) + gr_color(0, 0, 0, 255); + gr_fill(progress_x, progress_y, width, height); - if (progressBarType == DETERMINATE) { - float p = progressScopeStart + progress * progressScopeSize; - int pos = (int) (p * width); + if (progressBarType == DETERMINATE) { + float p = progressScopeStart + progress * progressScopeSize; + int pos = static_cast<int>(p * width); - if (rtl_locale) { - // Fill the progress bar from right to left. - if (pos > 0) { - gr_blit(progressBarFill, width-pos, 0, pos, height, - progress_x+width-pos, progress_y); - } - if (pos < width-1) { - gr_blit(progressBarEmpty, 0, 0, width-pos, height, progress_x, progress_y); - } - } else { - // Fill the progress bar from left to right. - if (pos > 0) { - gr_blit(progressBarFill, 0, 0, pos, height, progress_x, progress_y); - } - if (pos < width-1) { - gr_blit(progressBarEmpty, pos, 0, width-pos, height, - progress_x+pos, progress_y); - } - } + if (rtl_locale_) { + // Fill the progress bar from right to left. + if (pos > 0) { + gr_blit(progressBarFill, width - pos, 0, pos, height, progress_x + width - pos, + progress_y); + } + if (pos < width - 1) { + gr_blit(progressBarEmpty, 0, 0, width - pos, height, progress_x, progress_y); + } + } else { + // Fill the progress bar from left to right. + if (pos > 0) { + gr_blit(progressBarFill, 0, 0, pos, height, progress_x, progress_y); } + if (pos < width - 1) { + gr_blit(progressBarEmpty, pos, 0, width - pos, height, progress_x + pos, progress_y); + } + } } + } } void ScreenRecoveryUI::SetColor(UIElement e) { @@ -411,10 +420,10 @@ void ScreenRecoveryUI::LoadBitmap(const char* filename, GRSurface** surface) { } void ScreenRecoveryUI::LoadLocalizedBitmap(const char* filename, GRSurface** surface) { - int result = res_create_localized_alpha_surface(filename, locale, surface); - if (result < 0) { - LOG(ERROR) << "couldn't load bitmap " << filename << " (error " << result << ")"; - } + int result = res_create_localized_alpha_surface(filename, locale_.c_str(), surface); + if (result < 0) { + LOG(ERROR) << "couldn't load bitmap " << filename << " (error " << result << ")"; + } } static char** Alloc2d(size_t rows, size_t cols) { @@ -436,98 +445,94 @@ void ScreenRecoveryUI::SetSystemUpdateText(bool security_update) { Redraw(); } -void ScreenRecoveryUI::Init() { - gr_init(); - - density_ = static_cast<float>(android::base::GetIntProperty("ro.sf.lcd_density", 160)) / 160.f; - is_large_ = gr_fb_height() > PixelsFromDp(800); +bool ScreenRecoveryUI::InitTextParams() { + if (gr_init() < 0) { + return false; + } gr_font_size(gr_sys_font(), &char_width_, &char_height_); text_rows_ = gr_fb_height() / char_height_; text_cols_ = gr_fb_width() / char_width_; + return true; +} - text_ = Alloc2d(text_rows_, text_cols_ + 1); - file_viewer_text_ = Alloc2d(text_rows_, text_cols_ + 1); - menu_ = Alloc2d(text_rows_, text_cols_ + 1); +bool ScreenRecoveryUI::Init(const std::string& locale) { + RecoveryUI::Init(locale); + if (!InitTextParams()) { + return false; + } - text_col_ = text_row_ = 0; - text_top_ = 1; + density_ = static_cast<float>(android::base::GetIntProperty("ro.sf.lcd_density", 160)) / 160.f; + + // Are we portrait or landscape? + layout_ = (gr_fb_width() > gr_fb_height()) ? LANDSCAPE : PORTRAIT; + // Are we the large variant of our base layout? + if (gr_fb_height() > PixelsFromDp(800)) ++layout_; + + text_ = Alloc2d(text_rows_, text_cols_ + 1); + file_viewer_text_ = Alloc2d(text_rows_, text_cols_ + 1); + menu_ = Alloc2d(text_rows_, text_cols_ + 1); - LoadBitmap("icon_error", &error_icon); + text_col_ = text_row_ = 0; + text_top_ = 1; - LoadBitmap("progress_empty", &progressBarEmpty); - LoadBitmap("progress_fill", &progressBarFill); + LoadBitmap("icon_error", &error_icon); - LoadBitmap("stage_empty", &stageMarkerEmpty); - LoadBitmap("stage_fill", &stageMarkerFill); + LoadBitmap("progress_empty", &progressBarEmpty); + LoadBitmap("progress_fill", &progressBarFill); - // Background text for "installing_update" could be "installing update" - // or "installing security update". It will be set after UI init according - // to commands in BCB. - installing_text = nullptr; - LoadLocalizedBitmap("erasing_text", &erasing_text); - LoadLocalizedBitmap("no_command_text", &no_command_text); - LoadLocalizedBitmap("error_text", &error_text); + LoadBitmap("stage_empty", &stageMarkerEmpty); + LoadBitmap("stage_fill", &stageMarkerFill); - LoadAnimation(); + // Background text for "installing_update" could be "installing update" + // or "installing security update". It will be set after UI init according + // to commands in BCB. + installing_text = nullptr; + LoadLocalizedBitmap("erasing_text", &erasing_text); + LoadLocalizedBitmap("no_command_text", &no_command_text); + LoadLocalizedBitmap("error_text", &error_text); - pthread_create(&progress_thread_, nullptr, ProgressThreadStartRoutine, this); + LoadAnimation(); - RecoveryUI::Init(); + pthread_create(&progress_thread_, nullptr, ProgressThreadStartRoutine, this); + + return true; } 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(); + // 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]); - } -} - -void ScreenRecoveryUI::SetLocale(const char* new_locale) { - this->locale = new_locale; - this->rtl_locale = false; - - if (locale) { - char* lang = strdup(locale); - for (char* p = lang; *p; ++p) { - if (*p == '_') { - *p = '\0'; - break; - } - } - - // A bit cheesy: keep an explicit list of supported RTL languages. - if (strcmp(lang, "ar") == 0 || // Arabic - strcmp(lang, "fa") == 0 || // Persian (Farsi) - strcmp(lang, "he") == 0 || // Hebrew (new language code) - strcmp(lang, "iw") == 0 || // Hebrew (old language code) - strcmp(lang, "ur") == 0) { // Urdu - rtl_locale = true; - } - free(lang); + for (size_t i = 0; i < loop_frames; i++) { + LoadBitmap(loop_frame_names.at(i).c_str(), &loopFrames[i]); } } |