恢复出厂设置后之persit.sys.model保存

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  
  1. main(int argc, char **argv) {  
  2.     time_t start = time(NULL);  
  3.   
  4.     // If these fail, there's not really anywhere to complain...  
  5.     freopen(TEMPORARY_LOG_FILE, "a", stdout); setbuf(stdout, NULL);  
  6.     freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL);  
  7.     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.
get_args(&argc, &argv);
从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

你可能感兴趣的:(android系统)