您的位置:首页 > 移动开发 > Android开发

android系统恢复出厂设置和升级界面的修改方法

2018-01-10 10:48 1856 查看
       最近需要定制恢复出厂设置和升级的画面,将原生的绿色机器人改成其他的图片。
基于的android版本是4.4.4,改起来挺简单的,但是遇到了几个坑,特地记录下。
android 4.4.4的升级机器人图片是由两部分构成的:静态部分和动态部分。

icon_installing.png



icon_installing_overlay01.png



    静态部分提供了一个大的背景图icon_install.png,动态部分是在背景图上进行覆盖的7张小图片installationOverlay01-07.png,实现机器人肚子上旋转的动画。
整体这部分的代码路径是在platform/bootable/recovery下,主要涉及的类是screen_ui.cpp
修改的思路是替换installationOverlay01-07.png图片为自己需要的图片,然后修改installationOverlay01-07.png显示的坐标位置,同时调整一下下方progressbar的高度和文字的高度,实现整体协调的效果。

修改installationOverlay01-07.png的具体位置:
void ScreenRecoveryUI::draw_install_overlay_locked(int frame) {
if (installationOverlay == NULL || overlay_offset_x < 0) return;
gr_surface surface = installationOverlay[frame];
int iconWidth = gr_get_width(surface);
int iconHeight = gr_get_height(surface);
// 改变iconX和iconY的位置,修改overlay图片的描画坐标,数值自己定
int iconX = (gr_fb_width()-127) / 2;
int iconY = (gr_fb_height()-192) / 2;
gr_blit(surface, 0, 0, iconWidth, iconHeight,
iconX, iconY);
}


修改progressbar的具体高度:
void ScreenRecoveryUI::draw_progress_locked()
{
if (currentIcon == ERROR) return;

if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) {
draw_install_overlay_locked(installingFrame);
}

if (progressBarType != EMPTY) {
int iconHeight = gr_get_height(backgroundIcon[INSTALLING_UPDATE]);
int width = gr_get_width(progressBarEmpty);
int height = gr_get_height(progressBarEmpty);

//修改dx dy的数值,改变progressbar的位置显示
int dx = (gr_fb_width() - width)/2;
int dy = (3*gr_fb_height() + iconHeight - 2*height)/4;

// Erase behind the progress bar (in case this was a progress-only update)
gr_color(0, 0, 0, 255);
gr_fill(dx, dy, width, height);

if (progressBarType == DETERMINATE) {
float p = progressScopeStart + progress * progressScopeSize;
int pos = (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, dx+width-pos, dy);
}
if (pos < width-1) {
gr_blit(progressBarEmpty, 0, 0, width-pos, height, dx, dy);
}
} else {
// Fill the progress bar from left to right.
if (pos > 0) {
gr_blit(progressBarFill, 0, 0, pos, height, dx, dy);
}
if (pos < width-1) {
gr_blit(progressBarEmpty, pos, 0, width-pos, height, dx+pos, dy);
}
}
}

if (progressBarType == INDETERMINATE) {
static int frame = 0;
gr_blit(progressBarIndeterminate[frame], 0, 0, width, height, dx, dy);
// in RTL locales, we run the animation backwards, which
// makes the spinner spin the other way.
if (rtl_locale) {
frame = (frame + indeterminate_frames - 1) % indeterminate_frames;
} else {
frame = (frame + 1) % indeterminate_frames;
}
}
}
}


修改升级和恢复出厂界面下文字的位置:
void ScreenRecoveryUI::draw_background_locked(Icon icon)
{
pagesIdentical = false;
gr_color(0, 0, 0, 255);
gr_fill(0, 0, gr_fb_width(), gr_fb_height());

if (icon) {
gr_surface surface = backgroundIcon[icon];
gr_surface text_surface = backgroundText[icon];

int iconWidth = gr_get_width(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 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);
if (icon == INSTALLING_UPDATE || icon == ERASING) {
draw_install_overlay_locked(installingFrame);
}

gr_color(255, 255, 255, 255);
gr_texticon(textX, textY, text_surface);
}
}


动画播放的频率默认是1秒钟20帧。如果修改可以在这里改:
void ScreenRecoveryUI::progress_loop() {
double interval = 1.0 / animation_fps;
......
}
}


    遇到的坑主要有两个。
    第一个就是在替换图片的时候,最开始替换的图片的位深度跟原始图片的位深度不一致,导致图片进去后花屏,后来查清楚了原来是图片位深度引起的,所以在替换图片的时候如果图片被不正常的拉伸了,可以看下是否是位深度不一样导致的。
    第二个就是遇到了一个奇怪的现象,每次烧写之后如果直接升级的话,升级的界面显示总是跟自己改的不一样,但是如果烧写后恢复出厂的话,然后再次升级,则界面显示是完全ok的,这个问题也查了很久最终定位在recovery模式下的语言locale上,因为升级调用启动程序是自己写的,在往/cache/recovery/command写入升级命令的时候只写了--update_package命令,并没有给指定--locale=en_US或是--locale=zh_CN,所以recovery模式并未识别到语言环境,导致影响了screen_ui.cpp中关于textHeight的计算,而textHeight的数值又影响了图片以及文字的高度设置,所以看起来不会按照自己设置的方式来改变。
    升级时的语言识别的逻辑是这样的:
    首先进入recovery模式后,在执行Recovery.cpp的main函数时,会对/cache/recovery/command写入的命令进行逐行解析,当解析到locale的时候,就会将当前升级操作的locale设置为读到的内容,当没有在command中读到locale的时候,系统会走load_locale_from_cache()函数,来获取上一次我们是否在/cache/recovery/last_locale中写入了之前的语言环境,如果还是没有的话,locale就真的找不到了,text的高度是根据locale来获取的,这时候就会影响text的高度的值,从而导致升级界面出现问题。
    那为什么先恢复出厂设置后再升级就没问题了呢?原因是恢复出厂设置的最后一步会在/cache/recovery/last_locale中写入语言环境,这样在下次升级的时候就可以找到一个语言的依据,也就不会导致text高度出现问题。

int
main(int argc, char **argv) {

......
int arg;
while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {
switch (arg) {
case 'p': previous_runs = atoi(optarg); break;
case 's': send_intent = optarg; break;
case 'u': update_package = optarg; break;
case 'w': wipe_data = wipe_cache = 1; break;
case 'c': wipe_cache = 1; break;
case 't': show_text = 1; break;
case 'x': just_exit = true; break;
case 'l': locale = optarg; break;
case 'g': {
if (stage == NULL || *stage == '\0') {
char buffer[20] = "1/";
strncat(buffer, optarg, sizeof(buffer)-3);
stage = strdup(buffer);
}
break;
}
case '?':
LOGE("Invalid command argument\n");
continue;
}
}

if (locale == NULL) {
load_locale_from_cache();
}
......
}


static void
load_locale_from_cache() {
// LOCALE_FILE就是/cache/recovery/last_locale
FILE* fp = fopen_path(LOCALE_FILE, "r");
char buffer[80];
if (fp != NULL) {
fgets(buffer, sizeof(buffer), fp);
int j = 0;
unsigned 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);
check_and_fclose(fp, LOCALE_FILE);
}
}


    刚开始接触底层,有些可能说的不对,希望自己对底层一点点的熟悉起来。对于这部分的代码可以通过LOGI来进行log输出,然后在恢复出厂后在/cache/recovery/last_log中查看到自己打印的log信息。
另外看了下android 7.1的这部分的代码,发现貌似已经可以利用max_stage是否为-1来控制不显示图片,只显示文字了。

    最后附上两个博客,对了解recovery模式和recovery模式的界面描画很有帮助。
    http://blog.csdn.net/u010223349/article/details/40392789     http://blog.csdn.net/fengying765/article/details/38301895
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: