这里主要分析non A/B模式下的recovery流程
A/B模式下的recovery在boot中
后续会不断补充,如果有疏漏或者错误的地方,请指出,共同学习,谢谢!
一、流程分析
首先列出recovery流程的几个重要点,接着会详细分析
- 加载recovery.fstab分区表
- 解析传入的参数
- recovery界面相关的设置
- 执行命令
- 如果没有命令,等待用户输入
- 结束recovery
1.加载分区表
首先看recovery.cpp的main函数,后面会解释为什么
[recovery.cpp]
int main(int argc, char **argv) {
//因为这个时候还没启动logcat,这里应该是设置将log打印到屏幕上和recovery.log中
android::base::InitLogging(argv, &UiLogger);
//下面是加载pmsg log文件
// Take last pmsg contents and rewrite it to the current pmsg session.
static const char filter[] = "recovery/";
// Do we need to rotate?
//这里应该和重命名log文件有关
bool doRotate = false;
__android_log_pmsg_file_read(
LOG_ID_SYSTEM, ANDROID_LOG_INFO, filter,
logbasename, &doRotate);
// Take action to refresh pmsg contents
__android_log_pmsg_file_read(
LOG_ID_SYSTEM, ANDROID_LOG_INFO, filter,
logrotate, &doRotate);
//看注释,这里是启动迷你版的adbd,为了使用adb sideload命令
if (argc == 2 && strcmp(argv[1], "--adbd") == 0) {
minadbd_main();
return 0;
}
//猜测这里是把log输出重定向到/tmp/recovery.log
redirect_stdio(TEMPORARY_LOG_FILE);
//加载recovery.fstab并建立分区表信息,在etc/目录下,recovery模式连adb可以看到
load_volume_table();
//从上面建立的分区表信息中读取是否有cache分区,因为log等重要信息都存在cache分区里
has_cache = volume_for_path(CACHE_ROOT) != nullptr;
..........
}
详细看下是如何加载分区表的
[roots.cpp]
void load_volume_table()
{
int i;
int ret;
fstab = fs_mgr_read_fstab_default();
if (!fstab) {
LOG(ERROR) << "failed to read default fstab";
return;
}
//将对应的信息加入到一条链表中
ret = fs_mgr_add_entry(fstab, "/tmp", "ramdisk", "ramdisk");
if (ret < 0 ) {
LOG(ERROR) << "failed to add /tmp entry to fstab";
fs_mgr_free_fstab(fstab);
fstab = NULL;
return;
}
printf("recovery filesystem table\n");
printf("=========================\n");
//在last_log中打印分区表信息
//打印的顺序是:
//编号 | 挂载节点 | 文件系统类型 | 块设备 | 长度
for (i = 0; i < fstab->num_entries; ++i) {
Volume* v = &fstab->recs[i];
printf(" %d %s %s %s %lld\n", i, v->mount_point, v->fs_type,
v->blk_device, v->length);
}
printf("\n");
}
跟踪fs_mgr_read_fstab_default
[fs_mgr_fstab.cpp]
struct fstab *fs_mgr_read_fstab_default()
{
std::string hw;
std::string default_fstab;
//下面应该是去其它位置查询fstab文件,由于/sbin/recovery是有的,这里default_fstab是"/etc/recovery.fstab"
//A/B和non A/B下fstab文件是不同的
if (access("/sbin/recovery", F_OK) == 0) {
default_fstab = "/etc/recovery.fstab";
} else if (fs_mgr_get_boot_config("hardware", &hw)) { // normal boot
for (const char *prefix : {
"/odm/etc/fstab.","/vendor/etc/fstab.", "/fstab."}) {
default_fstab = prefix + hw;
if (access(default_fstab.c_str(), F_OK) == 0) break;
}
} else {
LWARNING << __FUNCTION__ << "(): failed to find device hardware name";
}