Android Recovery Ui 分析
Android
recovery和android本质上是两个独立的rootfs, 仅仅是recovery这个rootfs存在的意义就是为android这个rootfs服务,因此被解释为Android系统的一部分。
recovery作为一个简单的rootfs, 提供了很有限的几个功能,仅仅包括了几个简单的库。UI的显示採用的是直接刷framebuffer的形式。作为android
framework及app层的码农。对这样的形式相对陌生,特抽点时间梳理了一番。 首先,浏览一下reocvery的main函数代码中UI相关的语句
main(int argc, char **argv) { ...... Device* device = make_device();
ui = device->GetUI();
gCurrentUI = ui; ui->Init();
ui->SetLocale(locale);
ui->SetBackground(RecoveryUI::NONE);
if (show_text) ui->ShowText(true); ...... if (status != INSTALL_SUCCESS || ui->IsTextVisible()) {
prompt_and_wait(device, status);
} ......
}
1、首先新建了一个Device类的对象。 Device类封装了一些操作,包含UI的操作 2、调用Device类的GetUI()返回一个DefaultUI对象,recovery中涉及到三个UI类,三个类之间为继承关系。分别为DefaultUI、 ScreenRecoveryUI、RecoveryUI
3、调用DefaultUI类的Init(), DefaultUI类没有Init()方法,因此将调用它的父类ScreenRecoveryUI的Init() 4、同理。调用ScreenRecoveryUI类的SetLocale()来标识几个比較特别的区域 5、同理。调用ScreenRecoveryUI类的SetBackground()设置初始状态的背景图 6、显示recovery的主界面,即一个选择菜单
void ScreenRecoveryUI::Init()
{
gr_init(); gr_font_size(&char_width, &char_height); text_col = text_row = 0;
text_rows = gr_fb_height() / char_height;
if (text_rows > kMaxRows) text_rows = kMaxRows;
text_top = 1; text_cols = gr_fb_width() / char_width;
if (text_cols > kMaxCols - 1) text_cols = kMaxCols - 1; LoadBitmap("icon_installing", &backgroundIcon[INSTALLING_UPDATE]);
backgroundIcon[ERASING] = backgroundIcon[INSTALLING_UPDATE];
LoadBitmap("icon_error", &backgroundIcon[ERROR]);
backgroundIcon[NO_COMMAND] = backgroundIcon[ERROR]; LoadBitmap("progress_empty", &progressBarEmpty);
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; progressBarIndeterminate = (gr_surface*)malloc(indeterminate_frames *
sizeof(gr_surface));
for (i = 0; i 0) {
installationOverlay = (gr_surface*)malloc(installing_frames *
sizeof(gr_surface));
for (i = 0; i 1、gr_init() 初始化图形设备,分配Pixelflinger库渲染的内存 2、gr_font_size() 将字体相应的surface长宽赋值给char_width和char_height 3、LoadBitmap() 将png生成surface, 每一个png图片相应一个surface, 全部surface存放在一个数组中
4、LoadLocalizedBitmap() 将区域文字所在的图片中的text信息依据当前的locale提取出来,生成相应的surface, 所以
surface也存放在一个数组中
6、pthread_create(&progress_t, NULL, progress_thread, NULL)
创建一个线程,该线程的任务是一个死循环。在该循环中不停
地检測currentIcon以及progressBarType来决定是不是要更新进度条。
7、调用RecoveryUI的Init(),初始化输入事件处理。void ScreenRecoveryUI::SetLocale(const char* locale) {
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 languages
// that are RTL.
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);
}
}ScreenRecoveryUI类的SetLocale, 该函数依据locale推断所用的字体是否属于阿拉伯语系,阿拉伯语的书写习惯是从右到左,假设是阿拉伯语系的话,就设置一个标志。后面依据这个标志决定从右到左显示文字或进度条。SetLocale的參数locale赋值逻辑是这种,先从command文件里读取, command文件里设置locale的命令如"--locale=zh_CN“,假设没有传入locale,初始化过程中会尝试从/cache/recovery/last_locale中读取locale, 假设该文件也没有,则locale不会被赋值,就默认用English.
void ScreenRecoveryUI::SetBackground(Icon icon)
{
pthread_mutex_lock(&updateMutex); // 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;
} currentIcon = icon;
update_screen_locked(); pthread_mutex_unlock(&updateMutex);
}SetBackground函数比較简洁,关键部分在update_screen_locked。以下我们重点分析一下。
update_screen_locked和update_progress_locked是recovery的UI部分的关键函数,update_screen_locked用来更新背景, update_progress_locked用来更新进度条。由于显示的画面会一直在更新,所以这两个函数会在不同的地方被重复调用
void ScreenRecoveryUI::update_screen_locked()
{
draw_screen_locked();
gr_flip();
}update_screen_locked包括两个操作。一是更新screen, 二是切换前后buffer。
void ScreenRecoveryUI::draw_screen_locked()
{
draw_background_locked(currentIcon);
draw_progress_locked(); if (show_text) {
SetColor(TEXT_FILL);
gr_fill(0, 0, gr_fb_width(), gr_fb_height()); int y = 0;
int i = 0;
if (show_menu) {
SetColor(HEADER); for (; i y+2 && count draw_background_locked函数的实现代码中又出现了几个以gr_开头的函数,以gr_开头的函数来自minui库。minui库的代码在recovery源代码下的minui文件夹下。minui提供的接口实现了图形的描绘以及固定大小的文字显示。 gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a); /* 设置字体颜色 */
gr_fill(int x, int y, int w, int h); /* 填充矩形区域,參数分别代表起始坐标、矩形区域大小 */
gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy); /* 填充由source指定的图片 */ draw_background_locked函数先将整个渲染buffer填充为黑色,然后计算背景surface的长宽。文字surface的长宽。再结合fb的长宽计算出背景surface以及文字surface显示的坐标,有长宽和坐标就能够调用Pixelflinger的接口在渲染buffer上进行渲染。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); 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 0) {
gr_blit(progressBarFill, 0, 0, pos, height, dx, dy);
}
if (pos draw_progress_locked函数的原理与 update_screen_locked函数类似, 终于是将进度条的surface输出到渲染buffer,
recovery中各个场景的画面,就是由背景、文字、进度条的重叠,不同的是所用的surface 以及surface的坐标。 recovery main函数中的UI代码基本上已经分析过了。最后一点主菜单的显示,就是通过上面介绍的这些接口将文字图片显示出来。因此就不再多讲。总的来说,recovery的UI显示部分难度不大,应用层调用minui库实现了图形的描绘以及固定大小的文字显示,minui库调用了Pixelflinger库来进行渲染。 附上minui部分接口的说明。供參考int gr_init(void); /* 初始化图形显示,主要是打开设备、分配内存、初始化一些參数 */
void gr_exit(void); /* 注销图形显示,关闭设备并释放内存 */ int gr_fb_width(void); /* 获取屏幕的宽度 */
int gr_fb_height(void); /* 获取屏幕的高度 */
gr_pixel *gr_fb_data(void); /* 获取显示数据缓存的地址 */
void gr_flip(void); /* 刷新显示内容 */
void gr_fb_blank(bool blank); /* 清屏 */ 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); /* 填充矩形区域,參数分别代表起始坐标、矩形区域大小 */
int gr_text(int x, int y, const char *s); /* 显示字符串 */
int gr_measure(const char *s); /* 获取字符串在默认字库中占用的像素长度 */
void gr_font_size(int *x, int *y); /* 获取当前字库一个字符所占的长宽 */ void gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy); /* 填充由source指定的图片 */
unsigned int gr_get_width(gr_surface surface); /* 获取图片宽度 */
unsigned int gr_get_height(gr_surface surface); /* 获取图片高度 */
/* 依据图片创建显示资源数据,name为图片在mk文件指定的相对路径 */
int res_create_surface(const char* name, gr_surface* pSurface);
void res_free_surface(gr_surface surface); /* 释放资源数据 */
Android Recovery Ui 分析的更多相关文章
- Android recovery UI实现分析
Android recovery模式为何物? 关于这个问题, baidu上已经有无数的答案.不理解的朋友先补习一下. 从纯技术角度来讲, recovery和android本质上是两个独立的rootfs ...
- Recovery启动流程--recovery.cpp分析
这篇文章主要通过分析高通recovery目录下的recovery.cpp源码,对recovery启动流程有一个宏观的了解. 当开机以后,在lk阶段,如果是recovery,会设置boot_into_r ...
- Android APP性能分析方法及工具
近期读到<Speed up your app>一文.这是一篇关于Android APP性能分析.优化的文章.在这篇文章中,作者介绍他的APP分析优化规则.使用的工具和方法.我觉得值得大家借 ...
- Android优化——UI检视利器:Hierarchy Viewer
在Android的SDK工具包中,有很多十分有用的工具,可以帮助程序员开发和测试Android应用程序,大大提高其工作效率.其中的一款叫 Hierachy Viewer的可视化调试工具,可以很方便地在 ...
- android recovery模式及ROM制作
转自android recovery模式及ROM制作 1.总述 为了方便客户日后的固件升级,本周研究了一下android的recovery模式.网上有不少这类的资料,但都比较繁杂,没有一个系统的介绍与 ...
- Qualcomm Android display架构分析
Android display架构分析(一) http://blog.csdn.net/BonderWu/archive/2010/08/12/5805961.aspx http://hi.baidu ...
- 高通Android display架构分析
目录(?)[-] Kernel Space Display架构介绍 函数和数据结构介绍 函数和数据结构介绍 函数和数据结构介绍 数据流分析 初始化过程分析 User Space display接口 K ...
- Android HttpURLConnection源代码分析
Android HttpURLConnection源代码分析 之前写过HttpURLConnection与HttpClient的差别及选择.后来又分析了Volley的源代码. 近期又遇到了问题,想在V ...
- Android 消息处理源代码分析(2)
Android 消息处理源代码分析(1)点击打开链接 继续接着分析剩下的类文件 Looper.java public final class Looper { final MessageQueue m ...
随机推荐
- PDF数据提取------3.解析Demo
1.PDF中文本字符串格式中关键值信息抓取(已完成) 简介:这种解析比较传统最简单主要熟练使用Regular Expression做语义识别和验证.例如抓取下面红色圈内关键信息 string mett ...
- 【Unity入门】编辑器常用视图介绍
版权声明:本文为博主原创文章,转载请注明出处. 打开Unity编辑器的主窗口,在窗口的右上角可以看到有个“Layout”按钮.这是用来对Unity编辑器主窗口上面的各个窗口面板进行布局的.通常情况下我 ...
- STL map 用法
首先make_pair Pairs C++标准程序库中凡是"必须返回两个值"的函数, 也都会利用pair对象 class pair可以将两个值视为一个单元.容器类别map和mul ...
- 如何引用CSS样式表
如何使用样式 当浏览器读到一个样式表,它就会按照这个样式表来对文档进行格式化.有以下三种方式来插入样式表: 1.外部样式表 当样式需要被应用到很多页面的时候,外部样式表将是理想的选择.使用外部样式 ...
- android开发中遇到的bug
这种NullPointerException这么解决啊 Activity.dispatchTouchEvent 里try catch一下 参考:http://www.eoeandroid.com/th ...
- 精选PSD素材下载周刊【Goodfav PSD 20130720】
我们每周精选来自Goodfav PSD的免费PSD素材,有兴趣的朋友尤其是做设计工作的,不妨收藏或者下载. 这些现成的PSD素材能给我们一些相关的灵感,从而提高工作的效率. 1.File Upload ...
- Java Web高性能开发(三)
今日要闻: Clarifai:可识别视频中物体 最近几年,得益于深度学习技术的发展,谷歌和Facebook等企业的研究人员在图形识别软件领域取得了重大突破.现在,一家名为Clarifai的创业公司则提 ...
- 指定的值不是类型“Edm.Int32”的实例
指定的值不是类型“Edm.Int32”的实例参数名: value 说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息. 异常 ...
- SQL时间第二期_时间格式化
0 或 100 (*) 默认值 mon dd yyyy hh:miAM(或 PM) 1 101 美国 mm/dd/yyyy ...
- schedule和scheduleUpdate
在init()函数里面加上scheduleUpdate(),这样才会每一帧都调用update(). Schedule() 函数有两种方式,一种带时间参数,一种不带时间参数. 带时间参数的,间隔指定时间 ...