您的位置:首页 > 其它

Recovery模式的命令行参数

2014-01-23 19:50 246 查看

概要

本文描述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 file
if (*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等的分析。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: