概要


本文描述Android应用层要进入recovery模式时,需要设定参数的方式、以及参数的格式。


应用层的调用场景

有如下的场景需要让手机重启进入recovery模式:

  • 系统升级;
  • 恢复出厂设置


RecoverySystem.java

// \frameworks\base\core\java\android\os\RecoverySystem.java * fails, or if the reboot itself fails. */public static void installPackage(Context context, File packageFile)    throws IOException {    String filename = packageFile.getCanonicalPath();    Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");    String arg = "--update_package=" + filename +        "\n--locale=" + Locale.getDefault().toString();    bootCommand(context, arg);}/** * Reboots the device and wipes the user data partition.  This is * sometimes called a "factory reset", which is something of a * misnomer because the system partition is not restored to its * factory state. * Requires the {@link android.Manifest.permission#REBOOT} permission. * * @param context  the Context to use * * @throws IOException  if writing the recovery command file * fails, or if the reboot itself fails. */public static void rebootWipeUserData(Context context) throws IOException {    final ConditionVariable condition = new ConditionVariable();    Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION");    context.sendOrderedBroadcastAsUser(intent, UserHandle.OWNER,            android.Manifest.permission.MASTER_CLEAR,            new BroadcastReceiver() {                @Override                public void onReceive(Context context, Intent intent) {                    condition.open();                }            }, null, 0, null, null);    // Block until the ordered broadcast has completed.    condition.block();    bootCommand(context, "--wipe_data\n--locale=" + Locale.getDefault().toString());}/** * Reboot into the recovery system to wipe the /cache partition. * @throws IOException if something goes wrong. */public static void rebootWipeCache(Context context) throws IOException {    bootCommand(context, "--wipe_cache\n--locale=" + Locale.getDefault().toString());}/** * Reboot into the recovery system with the supplied argument. * @param arg to pass to the recovery utility. * @throws IOException if something goes wrong. */private static void bootCommand(Context context, String arg) throws IOException {    RECOVERY_DIR.mkdirs();  // In case we need it    COMMAND_FILE.delete();  // In case it's not writable    LOG_FILE.delete();    FileWriter command = new FileWriter(COMMAND_FILE);    try {        command.write(arg);        command.write("\n");    } finally {        command.close();    }    // Having written the command file, go ahead and reboot    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);    pm.reboot("recovery");    throw new IOException("Reboot failed (no permissions?)");}

这里包括了:

  • installPackage:系统升级,比如FOTA、组合按键进入recovery,等等
  • rebootWipeUserData:重启用于擦除用户数据(恢复出厂设置);
  • rebootWipeCache:擦除cache分区

所有这些都通过COMMAND_FILE(/cache/recovery/command)文件来给recovery传递命令行参数。


command文件的格式

如同上面代码所描述的,command文件中,每个参数占用一行;每个参数本身采用--parName=parValue的格式。如:

--wipe_data--locale=en

因为Android底层是Linux,所以换行使用的是\n,而不是\r\n。——参考上面的java代码。当然,recovery为了提高可靠性,增加了容错处理。下面是recovery.cpp中的处理过程:

// \bootable\recovery\recovery.cpp// --- if that doesn't work, try the command fileif (*argc <= 1) {    FILE *fp = fopen_path(COMMAND_FILE, "r");    if (fp != NULL) {        char *token;        char *argv0 = (*argv)[0];        *argv = (char **) malloc(sizeof(char *) * MAX_ARGS);        (*argv)[0] = argv0;  // use the same program name        char buf[MAX_ARG_LENGTH];        for (*argc = 1; *argc < MAX_ARGS; ++*argc) {            if (!fgets(buf, sizeof(buf), fp)) break;            token = strtok(buf, "\r\n");            if (token != NULL) {                (*argv)[*argc] = strdup(token);  // Strip newline.            } else {                --*argc;            }        }        check_and_fclose(fp, COMMAND_FILE);        LOGI("Got arguments from %s\n", COMMAND_FILE);    }}

recovery支持的命令行参数

recovery支持的参数由recovery.cpp中的OPTIONS来定义:

static const struct option OPTIONS[] = {  { "send_intent", required_argument, NULL, 's' },  { "update_package", required_argument, NULL, 'u' },  { "wipe_data", no_argument, NULL, 'w' },  { "wipe_cache", no_argument, NULL, 'c' },  { "show_text", no_argument, NULL, 't' },  { "just_exit", no_argument, NULL, 'x' },  { "locale", required_argument, NULL, 'l' },  { NULL, 0, NULL, 0 },};

事实上,各个厂商可以根据需求而进行扩展,只要recovery和上层应用保持一致即可。——在Recovery模式下的文本显示一文中讲到了locale的注意事项,如前面Java代码给出的,传入的是Locale.toString(),而不是Locale.getLanguage()。


BCB (Bootloader Control Block)

待补充

接下来分析应用层如何进入recovery模式的,包括ShutdownThread.java、android_reboot.c等的分析。



更多相关文章

  1. Android单元测试:测试RxJava的同步及异步操作
  2. android在学习——Menu背景图片,背景色的设置
  3. Kotlin Anko 使用相对布局 RelativeLayout
  4. android restart reason机制
  5. Android仿网易新闻图片详情下滑隐藏效果示例代码
  6. Android(安卓)pcm文件播放方法(AudioTrack)
  7. android activity启动模式
  8. Android培训班(26)
  9. android播放网络或者本地视频(截取某帧做封面)VideoView原生控件

随机推荐

  1. android sensor framework
  2. 全志A40i Android7永不休眠及不锁屏的修
  3. android中使用frameAnimation帧动画方法
  4. UI框架之SmartTabLayout使用
  5. Android通过LIstView显示文件列表的两种
  6. Android(安卓)音视频深入 十四 FFmpeg与O
  7. [代码片段] 【转】Android以最省内存的方
  8. android aapt apex
  9. 用java的jdk 生成android 的jni接口文档
  10. View绘制体系(三)——AttributeSet与TypedA