add simple text to recovery UI
- recovery takes a --locale argument, which will be passed by the main system - the locale is saved in cache, in case the --locale argument is missing (eg, when recovery is started from fastboot) - we include images that have prerendered text for many locales - we split the background states into four (installing update, erasing, no command, error) so that appropriate text can be shown. Change-Id: I731b8108e83d5ccc09a4aacfc1dbf7e86b397aaf
This commit is contained in:
@@ -277,7 +277,7 @@ exit:
|
|||||||
static int
|
static int
|
||||||
really_install_package(const char *path, int* wipe_cache)
|
really_install_package(const char *path, int* wipe_cache)
|
||||||
{
|
{
|
||||||
ui->SetBackground(RecoveryUI::INSTALLING);
|
ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
|
||||||
ui->Print("Finding update package...\n");
|
ui->Print("Finding update package...\n");
|
||||||
ui->SetProgressType(RecoveryUI::INDETERMINATE);
|
ui->SetProgressType(RecoveryUI::INDETERMINATE);
|
||||||
LOGI("Update location: %s\n", path);
|
LOGI("Update location: %s\n", path);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT };
|
enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT, INSTALL_NONE };
|
||||||
// Install the package specified by root_path. If INSTALL_SUCCESS is
|
// Install the package specified by root_path. If INSTALL_SUCCESS is
|
||||||
// returned and *wipe_cache is true on exit, caller should wipe the
|
// returned and *wipe_cache is true on exit, caller should wipe the
|
||||||
// cache partition.
|
// cache partition.
|
||||||
|
|||||||
@@ -244,6 +244,22 @@ int gr_text(int x, int y, const char *s)
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gr_texticon(int x, int y, gr_surface icon) {
|
||||||
|
GGLContext* gl = gr_context;
|
||||||
|
|
||||||
|
gl->bindTexture(gl, (GGLSurface*) icon);
|
||||||
|
gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE);
|
||||||
|
gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
|
||||||
|
gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
|
||||||
|
gl->enable(gl, GGL_TEXTURE_2D);
|
||||||
|
|
||||||
|
int w = gr_get_width(icon);
|
||||||
|
int h = gr_get_height(icon);
|
||||||
|
|
||||||
|
gl->texCoord2i(gl, -x, -y);
|
||||||
|
gl->recti(gl, x, y, x+gr_get_width(icon), y+gr_get_height(icon));
|
||||||
|
}
|
||||||
|
|
||||||
void gr_fill(int x, int y, int w, int h)
|
void gr_fill(int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
GGLContext *gl = gr_context;
|
GGLContext *gl = gr_context;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ void gr_fb_blank(bool blank);
|
|||||||
void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
|
void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
|
||||||
void gr_fill(int x, int y, int w, int h);
|
void gr_fill(int x, int y, int w, int h);
|
||||||
int gr_text(int x, int y, const char *s);
|
int gr_text(int x, int y, const char *s);
|
||||||
|
void gr_texticon(int x, int y, gr_surface icon);
|
||||||
int gr_measure(const char *s);
|
int gr_measure(const char *s);
|
||||||
void gr_font_size(int *x, int *y);
|
void gr_font_size(int *x, int *y);
|
||||||
|
|
||||||
@@ -71,6 +72,7 @@ void ev_dispatch(void);
|
|||||||
|
|
||||||
// Returns 0 if no error, else negative.
|
// Returns 0 if no error, else negative.
|
||||||
int res_create_surface(const char* name, gr_surface* pSurface);
|
int res_create_surface(const char* name, gr_surface* pSurface);
|
||||||
|
int res_create_localized_surface(const char* name, gr_surface* pSurface);
|
||||||
void res_free_surface(gr_surface surface);
|
void res_free_surface(gr_surface surface);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
|
|
||||||
#include "minui.h"
|
#include "minui.h"
|
||||||
|
|
||||||
|
extern char* locale;
|
||||||
|
|
||||||
// libpng gives "undefined reference to 'pow'" errors, and I have no
|
// libpng gives "undefined reference to 'pow'" errors, and I have no
|
||||||
// idea how to convince the build system to link with -lm. We don't
|
// idea how to convince the build system to link with -lm. We don't
|
||||||
// need this functionality (it's used for gamma adjustment) so provide
|
// need this functionality (it's used for gamma adjustment) so provide
|
||||||
@@ -173,6 +175,154 @@ exit:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int matches_locale(const char* loc) {
|
||||||
|
if (locale == NULL) return 0;
|
||||||
|
|
||||||
|
printf("matching loc=[%s] vs locale=[%s]\n", loc, locale);
|
||||||
|
|
||||||
|
if (strcmp(loc, locale) == 0) return 1;
|
||||||
|
|
||||||
|
// if loc does *not* have an underscore, and it matches the start
|
||||||
|
// of locale, and the next character in locale *is* an underscore,
|
||||||
|
// that's a match. For instance, loc == "en" matches locale ==
|
||||||
|
// "en_US".
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; loc[i] != 0 && loc[i] != '_'; ++i);
|
||||||
|
if (loc[i] == '_') return 0;
|
||||||
|
printf(" partial match possible; i = %d\n", i);
|
||||||
|
|
||||||
|
return (strncmp(locale, loc, i) == 0 && locale[i] == '_');
|
||||||
|
}
|
||||||
|
|
||||||
|
int res_create_localized_surface(const char* name, gr_surface* pSurface) {
|
||||||
|
char resPath[256];
|
||||||
|
GGLSurface* surface = NULL;
|
||||||
|
int result = 0;
|
||||||
|
unsigned char header[8];
|
||||||
|
png_structp png_ptr = NULL;
|
||||||
|
png_infop info_ptr = NULL;
|
||||||
|
|
||||||
|
*pSurface = NULL;
|
||||||
|
|
||||||
|
snprintf(resPath, sizeof(resPath)-1, "/res/images/%s.png", name);
|
||||||
|
resPath[sizeof(resPath)-1] = '\0';
|
||||||
|
FILE* fp = fopen(resPath, "rb");
|
||||||
|
if (fp == NULL) {
|
||||||
|
result = -1;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t bytesRead = fread(header, 1, sizeof(header), fp);
|
||||||
|
if (bytesRead != sizeof(header)) {
|
||||||
|
result = -2;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (png_sig_cmp(header, 0, sizeof(header))) {
|
||||||
|
result = -3;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||||
|
if (!png_ptr) {
|
||||||
|
result = -4;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (!info_ptr) {
|
||||||
|
result = -5;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||||
|
result = -6;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_init_io(png_ptr, fp);
|
||||||
|
png_set_sig_bytes(png_ptr, sizeof(header));
|
||||||
|
png_read_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
size_t width = info_ptr->width;
|
||||||
|
size_t height = info_ptr->height;
|
||||||
|
size_t stride = 4 * width;
|
||||||
|
|
||||||
|
printf("image size is %d x %d\n", width, height);
|
||||||
|
|
||||||
|
int color_type = info_ptr->color_type;
|
||||||
|
int bit_depth = info_ptr->bit_depth;
|
||||||
|
int channels = info_ptr->channels;
|
||||||
|
printf("color_type %d bit_depth %d channels %d\n",
|
||||||
|
color_type, bit_depth, channels);
|
||||||
|
|
||||||
|
if (!(bit_depth == 8 &&
|
||||||
|
(channels == 1 && color_type == PNG_COLOR_TYPE_GRAY))) {
|
||||||
|
return -7;
|
||||||
|
printf("exiting -7\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* row = malloc(width);
|
||||||
|
int y;
|
||||||
|
for (y = 0; y < height; ++y) {
|
||||||
|
png_read_row(png_ptr, row, NULL);
|
||||||
|
int w = (row[1] << 8) | row[0];
|
||||||
|
int h = (row[3] << 8) | row[2];
|
||||||
|
int len = row[4];
|
||||||
|
char* loc = row+5;
|
||||||
|
|
||||||
|
printf("row %d: %s %d x %d\n", y, loc, w, h);
|
||||||
|
|
||||||
|
if (y+1+h >= height || matches_locale(loc)) {
|
||||||
|
printf(" taking this one\n");
|
||||||
|
|
||||||
|
surface = malloc(sizeof(GGLSurface));
|
||||||
|
if (surface == NULL) {
|
||||||
|
result = -8;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
unsigned char* pData = malloc(w*h);
|
||||||
|
|
||||||
|
surface->version = sizeof(GGLSurface);
|
||||||
|
surface->width = w;
|
||||||
|
surface->height = h;
|
||||||
|
surface->stride = w; /* Yes, pixels, not bytes */
|
||||||
|
surface->data = pData;
|
||||||
|
surface->format = GGL_PIXEL_FORMAT_A_8;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < h; ++i, ++y) {
|
||||||
|
png_read_row(png_ptr, row, NULL);
|
||||||
|
memcpy(pData + i*w, row, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
*pSurface = (gr_surface) surface;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
printf(" skipping\n");
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < h; ++i, ++y) {
|
||||||
|
png_read_row(png_ptr, row, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
|
||||||
|
if (fp != NULL) {
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
if (result < 0) {
|
||||||
|
if (surface) {
|
||||||
|
free(surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void res_free_surface(gr_surface surface) {
|
void res_free_surface(gr_surface surface) {
|
||||||
GGLSurface* pSurface = (GGLSurface*) surface;
|
GGLSurface* pSurface = (GGLSurface*) surface;
|
||||||
if (pSurface) {
|
if (pSurface) {
|
||||||
|
|||||||
63
recovery.cpp
63
recovery.cpp
@@ -54,6 +54,7 @@ static const struct option OPTIONS[] = {
|
|||||||
{ "wipe_cache", no_argument, NULL, 'c' },
|
{ "wipe_cache", no_argument, NULL, 'c' },
|
||||||
{ "show_text", no_argument, NULL, 't' },
|
{ "show_text", no_argument, NULL, 't' },
|
||||||
{ "just_exit", no_argument, NULL, 'x' },
|
{ "just_exit", no_argument, NULL, 'x' },
|
||||||
|
{ "locale", required_argument, NULL, 'l' },
|
||||||
{ NULL, 0, NULL, 0 },
|
{ NULL, 0, NULL, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -62,6 +63,7 @@ static const char *INTENT_FILE = "/cache/recovery/intent";
|
|||||||
static const char *LOG_FILE = "/cache/recovery/log";
|
static const char *LOG_FILE = "/cache/recovery/log";
|
||||||
static const char *LAST_LOG_FILE = "/cache/recovery/last_log";
|
static const char *LAST_LOG_FILE = "/cache/recovery/last_log";
|
||||||
static const char *LAST_INSTALL_FILE = "/cache/recovery/last_install";
|
static const char *LAST_INSTALL_FILE = "/cache/recovery/last_install";
|
||||||
|
static const char *LOCALE_FILE = "/cache/recovery/locale";
|
||||||
static const char *CACHE_ROOT = "/cache";
|
static const char *CACHE_ROOT = "/cache";
|
||||||
static const char *SDCARD_ROOT = "/sdcard";
|
static const char *SDCARD_ROOT = "/sdcard";
|
||||||
static const char *TEMPORARY_LOG_FILE = "/tmp/recovery.log";
|
static const char *TEMPORARY_LOG_FILE = "/tmp/recovery.log";
|
||||||
@@ -69,6 +71,7 @@ static const char *TEMPORARY_INSTALL_FILE = "/tmp/last_install";
|
|||||||
static const char *SIDELOAD_TEMP_DIR = "/tmp/sideload";
|
static const char *SIDELOAD_TEMP_DIR = "/tmp/sideload";
|
||||||
|
|
||||||
RecoveryUI* ui = NULL;
|
RecoveryUI* ui = NULL;
|
||||||
|
char* locale = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The recovery tool communicates with the main system through /cache files.
|
* The recovery tool communicates with the main system through /cache files.
|
||||||
@@ -283,6 +286,15 @@ finish_recovery(const char *send_intent) {
|
|||||||
chmod(LAST_LOG_FILE, 0640);
|
chmod(LAST_LOG_FILE, 0640);
|
||||||
chmod(LAST_INSTALL_FILE, 0644);
|
chmod(LAST_INSTALL_FILE, 0644);
|
||||||
|
|
||||||
|
// Save the locale to cache, so if recovery is next started up
|
||||||
|
// without a --locale argument (eg, directly from the bootloader)
|
||||||
|
// it will use the last-known locale.
|
||||||
|
if (locale != NULL) {
|
||||||
|
FILE* fp = fopen(LOCALE_FILE, "w");
|
||||||
|
fwrite(locale, 1, strlen(locale), fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
// Reset to normal system boot so recovery won't cycle indefinitely.
|
// Reset to normal system boot so recovery won't cycle indefinitely.
|
||||||
struct bootloader_message boot;
|
struct bootloader_message boot;
|
||||||
memset(&boot, 0, sizeof(boot));
|
memset(&boot, 0, sizeof(boot));
|
||||||
@@ -300,7 +312,7 @@ finish_recovery(const char *send_intent) {
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
erase_volume(const char *volume) {
|
erase_volume(const char *volume) {
|
||||||
ui->SetBackground(RecoveryUI::INSTALLING);
|
ui->SetBackground(RecoveryUI::ERASING);
|
||||||
ui->SetProgressType(RecoveryUI::INDETERMINATE);
|
ui->SetProgressType(RecoveryUI::INDETERMINATE);
|
||||||
ui->Print("Formatting %s...\n", volume);
|
ui->Print("Formatting %s...\n", volume);
|
||||||
|
|
||||||
@@ -658,6 +670,7 @@ prompt_and_wait(Device* device) {
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
finish_recovery(NULL);
|
finish_recovery(NULL);
|
||||||
|
ui->SetBackground(RecoveryUI::NO_COMMAND);
|
||||||
ui->SetProgressType(RecoveryUI::EMPTY);
|
ui->SetProgressType(RecoveryUI::EMPTY);
|
||||||
|
|
||||||
int chosen_item = get_menu_selection(headers, device->GetMenuItems(), 0, 0, device);
|
int chosen_item = get_menu_selection(headers, device->GetMenuItems(), 0, 0, device);
|
||||||
@@ -679,6 +692,7 @@ prompt_and_wait(Device* device) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Device::WIPE_CACHE:
|
case Device::WIPE_CACHE:
|
||||||
|
ui->ShowText(false);
|
||||||
ui->Print("\n-- Wiping cache...\n");
|
ui->Print("\n-- Wiping cache...\n");
|
||||||
erase_volume("/cache");
|
erase_volume("/cache");
|
||||||
ui->Print("Cache wipe complete.\n");
|
ui->Print("Cache wipe complete.\n");
|
||||||
@@ -757,6 +771,24 @@ print_property(const char *key, const char *name, void *cookie) {
|
|||||||
printf("%s=%s\n", key, name);
|
printf("%s=%s\n", key, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
load_locale_from_cache() {
|
||||||
|
FILE* fp = fopen_path(LOCALE_FILE, "r");
|
||||||
|
char buffer[80];
|
||||||
|
if (fp != NULL) {
|
||||||
|
fgets(buffer, sizeof(buffer), fp);
|
||||||
|
int j = 0;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < sizeof(buffer) && buffer[i]; ++i) {
|
||||||
|
if (!isspace(buffer[i])) {
|
||||||
|
buffer[j++] = buffer[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer[j] = 0;
|
||||||
|
locale = strdup(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv) {
|
main(int argc, char **argv) {
|
||||||
time_t start = time(NULL);
|
time_t start = time(NULL);
|
||||||
@@ -779,18 +811,13 @@ main(int argc, char **argv) {
|
|||||||
|
|
||||||
printf("Starting recovery on %s", ctime(&start));
|
printf("Starting recovery on %s", ctime(&start));
|
||||||
|
|
||||||
Device* device = make_device();
|
|
||||||
ui = device->GetUI();
|
|
||||||
|
|
||||||
ui->Init();
|
|
||||||
ui->SetBackground(RecoveryUI::NONE);
|
|
||||||
load_volume_table();
|
load_volume_table();
|
||||||
get_args(&argc, &argv);
|
get_args(&argc, &argv);
|
||||||
|
|
||||||
int previous_runs = 0;
|
int previous_runs = 0;
|
||||||
const char *send_intent = NULL;
|
const char *send_intent = NULL;
|
||||||
const char *update_package = NULL;
|
const char *update_package = NULL;
|
||||||
int wipe_data = 0, wipe_cache = 0;
|
int wipe_data = 0, wipe_cache = 0, show_text = 0;
|
||||||
bool just_exit = false;
|
bool just_exit = false;
|
||||||
|
|
||||||
int arg;
|
int arg;
|
||||||
@@ -801,14 +828,27 @@ main(int argc, char **argv) {
|
|||||||
case 'u': update_package = optarg; break;
|
case 'u': update_package = optarg; break;
|
||||||
case 'w': wipe_data = wipe_cache = 1; break;
|
case 'w': wipe_data = wipe_cache = 1; break;
|
||||||
case 'c': wipe_cache = 1; break;
|
case 'c': wipe_cache = 1; break;
|
||||||
case 't': ui->ShowText(true); break;
|
case 't': show_text = 1; break;
|
||||||
case 'x': just_exit = true; break;
|
case 'x': just_exit = true; break;
|
||||||
|
case 'l': locale = optarg; break;
|
||||||
case '?':
|
case '?':
|
||||||
LOGE("Invalid command argument\n");
|
LOGE("Invalid command argument\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (locale == NULL) {
|
||||||
|
load_locale_from_cache();
|
||||||
|
}
|
||||||
|
printf("locale is [%s]\n", locale);
|
||||||
|
|
||||||
|
Device* device = make_device();
|
||||||
|
ui = device->GetUI();
|
||||||
|
|
||||||
|
ui->Init();
|
||||||
|
ui->SetBackground(RecoveryUI::NONE);
|
||||||
|
if (show_text) ui->ShowText(true);
|
||||||
|
|
||||||
#ifdef HAVE_SELINUX
|
#ifdef HAVE_SELINUX
|
||||||
struct selinux_opt seopts[] = {
|
struct selinux_opt seopts[] = {
|
||||||
{ SELABEL_OPT_PATH, "/file_contexts" }
|
{ SELABEL_OPT_PATH, "/file_contexts" }
|
||||||
@@ -868,10 +908,13 @@ main(int argc, char **argv) {
|
|||||||
if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR;
|
if (wipe_cache && erase_volume("/cache")) status = INSTALL_ERROR;
|
||||||
if (status != INSTALL_SUCCESS) ui->Print("Cache wipe failed.\n");
|
if (status != INSTALL_SUCCESS) ui->Print("Cache wipe failed.\n");
|
||||||
} else if (!just_exit) {
|
} else if (!just_exit) {
|
||||||
status = INSTALL_ERROR; // No command specified
|
status = INSTALL_NONE; // No command specified
|
||||||
|
ui->SetBackground(RecoveryUI::NO_COMMAND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status != INSTALL_SUCCESS) ui->SetBackground(RecoveryUI::ERROR);
|
if (status == INSTALL_ERROR || status == INSTALL_CORRUPT) {
|
||||||
|
ui->SetBackground(RecoveryUI::ERROR);
|
||||||
|
}
|
||||||
if (status != INSTALL_SUCCESS || ui->IsTextVisible()) {
|
if (status != INSTALL_SUCCESS || ui->IsTextVisible()) {
|
||||||
prompt_and_wait(device);
|
prompt_and_wait(device);
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
res/images/erasing_text.png
Normal file
BIN
res/images/erasing_text.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
BIN
res/images/error_text.png
Normal file
BIN
res/images/error_text.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
BIN
res/images/installing_text.png
Normal file
BIN
res/images/installing_text.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.3 KiB |
BIN
res/images/no_command_text.png
Normal file
BIN
res/images/no_command_text.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
@@ -94,7 +94,7 @@ void ScreenRecoveryUI::draw_install_overlay_locked(int frame) {
|
|||||||
int iconWidth = gr_get_width(surface);
|
int iconWidth = gr_get_width(surface);
|
||||||
int iconHeight = gr_get_height(surface);
|
int iconHeight = gr_get_height(surface);
|
||||||
gr_blit(surface, 0, 0, iconWidth, iconHeight,
|
gr_blit(surface, 0, 0, iconWidth, iconHeight,
|
||||||
install_overlay_offset_x, install_overlay_offset_y);
|
overlay_offset_x, overlay_offset_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the screen and draw the currently selected background icon (if any).
|
// Clear the screen and draw the currently selected background icon (if any).
|
||||||
@@ -107,14 +107,26 @@ void ScreenRecoveryUI::draw_background_locked(Icon icon)
|
|||||||
|
|
||||||
if (icon) {
|
if (icon) {
|
||||||
gr_surface surface = backgroundIcon[icon];
|
gr_surface surface = backgroundIcon[icon];
|
||||||
|
gr_surface text_surface = backgroundText[icon];
|
||||||
|
|
||||||
int iconWidth = gr_get_width(surface);
|
int iconWidth = gr_get_width(surface);
|
||||||
int iconHeight = gr_get_height(surface);
|
int iconHeight = gr_get_height(surface);
|
||||||
|
int textWidth = gr_get_width(text_surface);
|
||||||
|
int textHeight = gr_get_height(text_surface);
|
||||||
|
|
||||||
int iconX = (gr_fb_width() - iconWidth) / 2;
|
int iconX = (gr_fb_width() - iconWidth) / 2;
|
||||||
int iconY = (gr_fb_height() - iconHeight) / 2;
|
int iconY = (gr_fb_height() - (iconHeight+textHeight+40)) / 2;
|
||||||
|
|
||||||
|
int textX = (gr_fb_width() - textWidth) / 2;
|
||||||
|
int textY = ((gr_fb_height() - (iconHeight+textHeight+40)) / 2) + iconHeight + 40;
|
||||||
|
|
||||||
gr_blit(surface, 0, 0, iconWidth, iconHeight, iconX, iconY);
|
gr_blit(surface, 0, 0, iconWidth, iconHeight, iconX, iconY);
|
||||||
if (icon == INSTALLING) {
|
if (icon == INSTALLING_UPDATE || icon == ERASING) {
|
||||||
draw_install_overlay_locked(installingFrame);
|
draw_install_overlay_locked(installingFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gr_color(255, 255, 255, 255);
|
||||||
|
gr_texticon(textX, textY, text_surface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,12 +136,12 @@ void ScreenRecoveryUI::draw_progress_locked()
|
|||||||
{
|
{
|
||||||
if (currentIcon == ERROR) return;
|
if (currentIcon == ERROR) return;
|
||||||
|
|
||||||
if (currentIcon == INSTALLING) {
|
if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) {
|
||||||
draw_install_overlay_locked(installingFrame);
|
draw_install_overlay_locked(installingFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progressBarType != EMPTY) {
|
if (progressBarType != EMPTY) {
|
||||||
int iconHeight = gr_get_height(backgroundIcon[INSTALLING]);
|
int iconHeight = gr_get_height(backgroundIcon[INSTALLING_UPDATE]);
|
||||||
int width = gr_get_width(progressBarEmpty);
|
int width = gr_get_width(progressBarEmpty);
|
||||||
int height = gr_get_height(progressBarEmpty);
|
int height = gr_get_height(progressBarEmpty);
|
||||||
|
|
||||||
@@ -242,7 +254,8 @@ void ScreenRecoveryUI::progress_loop() {
|
|||||||
|
|
||||||
// update the installation animation, if active
|
// update the installation animation, if active
|
||||||
// skip this if we have a text overlay (too expensive to update)
|
// skip this if we have a text overlay (too expensive to update)
|
||||||
if (currentIcon == INSTALLING && installing_frames > 0 && !show_text) {
|
if ((currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) &&
|
||||||
|
installing_frames > 0 && !show_text) {
|
||||||
installingFrame = (installingFrame + 1) % installing_frames;
|
installingFrame = (installingFrame + 1) % installing_frames;
|
||||||
redraw = 1;
|
redraw = 1;
|
||||||
}
|
}
|
||||||
@@ -283,6 +296,13 @@ void ScreenRecoveryUI::LoadBitmap(const char* filename, gr_surface* surface) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScreenRecoveryUI::LoadLocalizedBitmap(const char* filename, gr_surface* surface) {
|
||||||
|
int result = res_create_localized_surface(filename, surface);
|
||||||
|
if (result < 0) {
|
||||||
|
LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ScreenRecoveryUI::Init()
|
void ScreenRecoveryUI::Init()
|
||||||
{
|
{
|
||||||
gr_init();
|
gr_init();
|
||||||
@@ -295,11 +315,19 @@ void ScreenRecoveryUI::Init()
|
|||||||
text_cols = gr_fb_width() / CHAR_WIDTH;
|
text_cols = gr_fb_width() / CHAR_WIDTH;
|
||||||
if (text_cols > kMaxCols - 1) text_cols = kMaxCols - 1;
|
if (text_cols > kMaxCols - 1) text_cols = kMaxCols - 1;
|
||||||
|
|
||||||
LoadBitmap("icon_installing", &backgroundIcon[INSTALLING]);
|
LoadBitmap("icon_installing", &backgroundIcon[INSTALLING_UPDATE]);
|
||||||
|
backgroundIcon[ERASING] = backgroundIcon[INSTALLING_UPDATE];
|
||||||
LoadBitmap("icon_error", &backgroundIcon[ERROR]);
|
LoadBitmap("icon_error", &backgroundIcon[ERROR]);
|
||||||
|
backgroundIcon[NO_COMMAND] = backgroundIcon[ERROR];
|
||||||
|
|
||||||
LoadBitmap("progress_empty", &progressBarEmpty);
|
LoadBitmap("progress_empty", &progressBarEmpty);
|
||||||
LoadBitmap("progress_fill", &progressBarFill);
|
LoadBitmap("progress_fill", &progressBarFill);
|
||||||
|
|
||||||
|
LoadLocalizedBitmap("installing_text", &backgroundText[INSTALLING_UPDATE]);
|
||||||
|
LoadLocalizedBitmap("erasing_text", &backgroundText[ERASING]);
|
||||||
|
LoadLocalizedBitmap("no_command_text", &backgroundText[NO_COMMAND]);
|
||||||
|
LoadLocalizedBitmap("error_text", &backgroundText[ERROR]);
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
progressBarIndeterminate = (gr_surface*)malloc(indeterminate_frames *
|
progressBarIndeterminate = (gr_surface*)malloc(indeterminate_frames *
|
||||||
@@ -321,14 +349,6 @@ void ScreenRecoveryUI::Init()
|
|||||||
sprintf(filename, "icon_installing_overlay%02d", i+1);
|
sprintf(filename, "icon_installing_overlay%02d", i+1);
|
||||||
LoadBitmap(filename, installationOverlay+i);
|
LoadBitmap(filename, installationOverlay+i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust the offset to account for the positioning of the
|
|
||||||
// base image on the screen.
|
|
||||||
if (backgroundIcon[INSTALLING] != NULL) {
|
|
||||||
gr_surface bg = backgroundIcon[INSTALLING];
|
|
||||||
install_overlay_offset_x += (gr_fb_width() - gr_get_width(bg)) / 2;
|
|
||||||
install_overlay_offset_y += (gr_fb_height() - gr_get_height(bg)) / 2;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
installationOverlay = NULL;
|
installationOverlay = NULL;
|
||||||
}
|
}
|
||||||
@@ -343,6 +363,17 @@ void ScreenRecoveryUI::SetBackground(Icon icon)
|
|||||||
pthread_mutex_lock(&updateMutex);
|
pthread_mutex_lock(&updateMutex);
|
||||||
currentIcon = icon;
|
currentIcon = icon;
|
||||||
update_screen_locked();
|
update_screen_locked();
|
||||||
|
|
||||||
|
// Adjust the offset to account for the positioning of the
|
||||||
|
// base image on the screen.
|
||||||
|
if (backgroundIcon[icon] != NULL) {
|
||||||
|
gr_surface bg = backgroundIcon[icon];
|
||||||
|
gr_surface text = backgroundText[icon];
|
||||||
|
overlay_offset_x = install_overlay_offset_x + (gr_fb_width() - gr_get_width(bg)) / 2;
|
||||||
|
overlay_offset_y = install_overlay_offset_y +
|
||||||
|
(gr_fb_height() - (gr_get_height(bg) + gr_get_height(text) + 40)) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&updateMutex);
|
pthread_mutex_unlock(&updateMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,8 @@ class ScreenRecoveryUI : public RecoveryUI {
|
|||||||
int installingFrame;
|
int installingFrame;
|
||||||
|
|
||||||
pthread_mutex_t updateMutex;
|
pthread_mutex_t updateMutex;
|
||||||
gr_surface backgroundIcon[3];
|
gr_surface backgroundIcon[5];
|
||||||
|
gr_surface backgroundText[5];
|
||||||
gr_surface *installationOverlay;
|
gr_surface *installationOverlay;
|
||||||
gr_surface *progressBarIndeterminate;
|
gr_surface *progressBarIndeterminate;
|
||||||
gr_surface progressBarEmpty;
|
gr_surface progressBarEmpty;
|
||||||
@@ -92,6 +93,7 @@ class ScreenRecoveryUI : public RecoveryUI {
|
|||||||
int indeterminate_frames;
|
int indeterminate_frames;
|
||||||
int installing_frames;
|
int installing_frames;
|
||||||
int install_overlay_offset_x, install_overlay_offset_y;
|
int install_overlay_offset_x, install_overlay_offset_y;
|
||||||
|
int overlay_offset_x, overlay_offset_y;
|
||||||
|
|
||||||
void draw_install_overlay_locked(int frame);
|
void draw_install_overlay_locked(int frame);
|
||||||
void draw_background_locked(Icon icon);
|
void draw_background_locked(Icon icon);
|
||||||
@@ -104,7 +106,7 @@ class ScreenRecoveryUI : public RecoveryUI {
|
|||||||
void progress_loop();
|
void progress_loop();
|
||||||
|
|
||||||
void LoadBitmap(const char* filename, gr_surface* surface);
|
void LoadBitmap(const char* filename, gr_surface* surface);
|
||||||
|
void LoadLocalizedBitmap(const char* filename, gr_surface* surface);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // RECOVERY_UI_H
|
#endif // RECOVERY_UI_H
|
||||||
|
|||||||
2
ui.h
2
ui.h
@@ -31,7 +31,7 @@ class RecoveryUI {
|
|||||||
virtual void Init();
|
virtual void Init();
|
||||||
|
|
||||||
// Set the overall recovery state ("background image").
|
// Set the overall recovery state ("background image").
|
||||||
enum Icon { NONE, INSTALLING, ERROR };
|
enum Icon { NONE, INSTALLING_UPDATE, ERASING, NO_COMMAND, ERROR };
|
||||||
virtual void SetBackground(Icon icon) = 0;
|
virtual void SetBackground(Icon icon) = 0;
|
||||||
|
|
||||||
// --- progress indicator ---
|
// --- progress indicator ---
|
||||||
|
|||||||
Reference in New Issue
Block a user