1.关于SystemProperties
只有标注:persist.sys.xxx的值,才能通过
SystemProperties.set("
persist.sys.xxx
","xxxxx")方法写进build.prop中,并实现跨进程之间的数据通信。(未标注
persist.sys的值,将不能在
adb shell中获取,而不能实现跨进程的通信
)
同时,该方法需要权限,需要在清单文件AndroidManifest.xml中,将sharedUserId的值设定为:
android.uid.system
注:
应用程序获得系统权限
sharedUserId=
android.uid.system
LOCAL_CERTIFICATE=
platform
2.恢复出厂设置后persit.sys.model的保存位置---cache/lost+found
2.1手机未恢复出厂设置前,cache/lost+found文件下为空
2.2 framework/base/core/java/android/os/RecoverySystem.class
选择恢复出厂设置之后,就会发送广播“android.intent.action.MASTER_CLEAR” ;// framework/base/core/res/AndroidManifest.xml
MasterClearReceiver 捕获广播 ,并进行android 层的相关处理最后重启 ;
其中会调用cleanCache()进行数据的清理:
rebootWipeUserData(Context context)--〉bootCommand(Context context, String... args) --〉cleanCache(String filepath)
private static void cleanCache(String filepath) throws IOException {
if
(filepath.toLowerCase().endsWith(
"lost+found"
))
return
;
从中可以看出,lost+found文件中的内容并不会被清理,故而将会保存下来
所以,将需要保存的数据,写在lost+found文件下,可以在恢复出厂设置后,该数据仍旧会被保存
2.3 RecoverySystem.class中
FileOutputStream command =
new
FileOutputStream(
COMMAND_FILE
);
该文件生成cache/recovery/command里,在其中写入命令(如:--wipe_data)。关机时,将command命令写入command.txt中,恢复数据时读取该文件中的command具体数据,达到引导开机的作用。开机后,该command.txt将会被清除。
命令文件/cache/recovery/command:保存着Main system传给Recovery的命令行,每一行就是一条命令,支持一下几种的组合。
--send_intent=anystring //write the text out to recovery/intent
//在Recovery结束时在finish_recovery函数中将定义的intent字符串作为参数传进来,并写入到/cache/recovery/intent中
--update_package=root:path
//verify install an OTA package file Main system将这条命令写入时,代表系统需要升级,在进入Recovery模式后,
//将该文件中的命令读取并写入BCB中,然后进行相应的更新update.zip包的操作。
--wipe_data //erase user data(and cache),then reboot。擦除用户数据。擦除data分区时必须要擦除cache分区。
--wipe_cache //wipe cache(but not user data),then reboot。擦除cache分区。
3.bootable/recovery/Recovery.c
3.1Recovery模式代码入口:
bootable\recovery 其入口文件就是 recovery.c 中 main函数
3.2
- main(int argc, char **argv) {
- time_t start = time(NULL);
-
- // If these fail, there's not really anywhere to complain...
- freopen(TEMPORARY_LOG_FILE, "a", stdout); setbuf(stdout, NULL);
- freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL);
- printf("Starting recovery on %s", ctime(&start));
printf("Command:");将标准输出和标准错误输出重定位到"/tmp/recovery.log",
同时之后,将 /tmp/recovery.log 复制到 "CACHE:recovery/log";开机后,可以查看输出的log日志
3.3
解析命令(command)----获取/cache/recovery/command中的命令(从RecoverySystem中写入,在Recovery中读取)
while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {
switch (arg) {
case 'p': previous_runs = atoi(optarg); break;
如 case 's': send_intent = optarg; break;
optarg是取命令中等号后面字符串
3.4恢复并升级
if (update_package != NULL) {
......
} else if (wipe_data) {
......
} else if (wipe_cache) {
...
} else {
status = update_by_key(); // No command specified
}
3.5升级完成
finish_recovery(send_intent);
它的功能如下:
1、
将前面定义的
intent
字符串写入(如果有的话):
CACHE:recovery/command
2、
将
/tmp/recovery.log
复制到
"CACHE:recovery/log";
3、
清空
misc
分区,这样重启就不会进入
recovery
模式
4、
删除
command
文件:
CACHE:recovery/command;
4.persit.sys.model值的保存与重写
4.1 在RecoverySystem中通过SystemProperties.get("persist.sys.model","")读取persist.sys.model的值
----final String model = "--model=" + SystemProperties.get("persist.sys.model","");
4.2 调用
bootCommand
(context,
"--wipe_data"
,ram,rom,model)
---将model以command的形式写入到command.txt文件中
4.3 recovery.c在main()方法里,通过get_args()拿到该commond
4.4 定义变量
char
*
model = NULL;并通过
while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1)解析拿到command中值,并赋值给model
4.5 在升级完成后finish_recovery(send_intent),将model值通过property_set("persist.sys.model", model);重新赋值给:persist.sys.model
编译recovery.c文件,需要make -j32 recoveryimage,并重刷recoveryimage才行(不能仅编译mmm bootable/recovery 得到recovery.bin,再将其push到手机中)
注:
1.Recovery模式代码入口:
bootable\recovery 其入口文件就是 recovery.c 中 main函数
2.static const char *COMMAND_FILE = "/cache/recovery/command";
* /cache/recovery/command - INPUT - command line for tool, one arg per line
升级完成后,将会清除command文件
static const char *INTENT_FILE = "/cache/recovery/intent";
* /cache/recovery/intent - OUTPUT - intent that was passed in
static const char *LOG_FILE = "/cache/recovery/log";
* /cache/recovery/log - OUTPUT - combined log file from recovery run(s)
static const char *LAST_LOG_FILE = "/cache/recovery/last_log";------
static const char *LAST_INSTALL_FILE = "/cache/recovery/last_install";-----
printf("Command:");将标准输出和标准错误输出重定位到"/tmp/recovery.log",如果是eng模式,就可以通过adb pull /tmp/recovery.log, 看到当前的log信息,这为我们提供了有效的调试手段。
同时之后,将 /tmp/recovery.log 复制到 "CACHE:recovery/log";开机后,可以查看输出的log日志。
3.恢复出厂设置的步骤
* FACTORY RESET
* 1. user selects "factory reset"
* 2. main system writes "--wipe_data" to /cache/recovery/command
* 3. main system reboots into recovery
* 4. get_args() writes BCB with "boot-recovery" and "--wipe_data"
* -- after this, rebooting will restart the erase --
* 5. erase_volume() reformats /data
* 6. erase_volume() reformats /cache
* 7. finish_recovery() erases BCB
* -- after this, rebooting will restart the main system --
* 8. main() calls reboot() to boot main system
4.
从misc 分区以及 CACHE:recovery/command 文件中读入参数,写入到argc, argv (get_bootloader_message) 并有可能写回 misc 分区(set_bootloader_message)
做完以上事情后就开始解析具体参数:
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': ui_show_text(1); break;
case '?':
LOGE("Invalid command argument\n");
continue;
}
}
printf("Command:");
for (arg = 0; arg < argc; arg++) {
printf(" \"%s\"", argv[arg]);
}
printf("\n");
以上仅仅是打印表明进入到哪一步,方便调试情况的掌握
5.
解析命令
int getopt_long(int, char * const *, const char *, const struct option *, int *);
如 case 's': send_intent = optarg; break;
optarg是取命令中等号后面字符串
涉及代码: https://code.csdn.net/snippets/2605815
参考文档: http://blog.csdn.net/andyhuabing/article/details/9248713
http://www.oschina.net/question/54100_27732
http://blog.chinaunix.net/uid-29783732-id-4417641.html