Android--Recovery模块之恢复出厂设置

本文详细解析了Android设备中Recovery模块执行恢复出厂设置的流程,包括入口流程、应用层流程、重启流程和恢复模式流程。在恢复模式下,系统执行更新、删除分区、显示菜单等操作,并在完成恢复后更新相关文件,确保系统正常启动。
摘要由CSDN通过智能技术生成

(一)、 在进行详细流程分析之前,先看一下几个重要概念:

 一、Recovery的工作需要整个软件平台的配合,从架构角度看,有三个部分:

    1、Main system:用boot.img启动的Linux系统,Android的正常工作模式。

    2、Recovery:用recovery.img启动的Linux系统,只要是运行Recovery程序。

    3、Bootloader:除了加载、启动系统,还会通过读取flash的MISC分区获取来自Main system和Recovery的消息,并以此觉得做何种操作。

    在Recovery的工作流程中,上述三个实体的通信是必不可少的。

二、通信接口

    1、BCB(bootloader control block)

    Bootloader和Recovery模块以及主系统之间的通信是通过系统的misc分区来完成的,描述misc分区的数据结构是bootloader_message,定义如下:

struct bootloader_message {
    char command[32];
    char status[32];
    char recovery[768];

    // The 'recovery' field used to be 1024 bytes.  It has only ever
    // been used to store the recovery command line, so 768 bytes
    // should be plenty.  We carve off the last 256 bytes to store the
    // stage string (for multistage packages) and possible future
    // expansion.
    char stage[32];
    char reserved[224];
};
    command:command字段中存储的是命令,当想要重启进入Recovery模式,或升级radio/bootloader firmware时,会更新这个字段(如果它的值是“boot-recovery”,系统进入Recovery模式;如果它的值是“update-radio”或“update-hboot”,系统进入更新firmware模式,这个更新过程由bootloader完成;如果command中的值为null,则进入主系统,正常启动);当firmware更新完毕,为了启动后进入Recovery做最终的清除,bootloader还会修改它。

    status:status字段存储的是更新的结果。update-radio或update-hboot完成后,由Recovery或Bootloader将更新结果写入到这个字段中。

    recovery:recovery字段存放的是recovery模块的启动参数。仅被Main system写入,用于向Recovery发送消息,必须以“recovery\n”开头,否则这个字段中的所有内容会被忽略。这一项的内容中“recovery/\n”以后的部分,是/cache/recovery/command支持的命令,可以认为这是在Recovery操作过程中,对命令操作的备份。Recovery也会更新这个域的信息,执行某操作前把该操作命令写到recovery域,并更新command域,操作完成后再清空recovery域及command域,这样在进入Main system之前,就能确保操作被执行。

(二)详细流程分析 

一、入口流程分析

    1、在MasterClearConfirm.java(/packages/apps/settings/src/com/android/settings/MasterClearConfirm.java)中显示恢复出厂提示和对应button,点击button后调用button的click方法。如果选中了mEraseSdCard(格式化SD卡),则启动ExternalStorageFormatter的服务;否则发送Intent.ACTION_MASTER_CLEAR广播。

    private void doMasterClear() {
        if (mEraseSdCard) {
            Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
            intent.putExtra(Intent.EXTRA_REASON, "MasterClearConfirm");
            intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
            getActivity().startService(intent);
        } else {
            Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR);
            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
            intent.putExtra(Intent.EXTRA_REASON, "MasterClearConfirm");
            getActivity().sendBroadcast(intent);
            // Intent handling is asynchronous -- assume it will happen soon.
        }
    }
     2、定位到注册改广播的地方,/frameworks/base/core/res/AndroidMenifest.xml中注册了改广播接收器。

        <receiver android:name="com.android.server.MasterClearReceiver"
            android:permission="android.permission.MASTER_CLEAR">
            <intent-filter
                    android:priority="100" >
                <!-- For Checkin, Settings, etc.: action=MASTER_CLEAR -->
                <action android:name="android.intent.action.MASTER_CLEAR" />

                <!-- MCS always uses REMOTE_INTENT: category=MASTER_CLEAR -->
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <category android:name="android.intent.category.MASTER_CLEAR" />
            </intent-filter>
        </receiver>
    3、对应的在MasterClearReceiver(\frameworks\base\services\core\java\com\android\server)会接受此广播,在onReceive()方法中会调用RecoverySystem.rebootWipeUserData()方法,并传递三个参数:context;shutdown=false;reason=“MasterClearConfirm”。

    @Override
    public void onReceive(final Context context, final Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_REMOTE_INTENT)) {
            if (!"google.com".equals(intent.getStringExtra("from"))) {
                Slog.w(TAG, "Ignoring master clear request -- not from trusted server.");
                return;
            }
        }

        final boolean shutdown = intent.getBooleanExtra("shutdown", false);
        final String reason = intent.getStringExtra(Intent.EXTRA_REASON);//"MasterClearConfirm"

        Slog.w(TAG, "!!! FACTORY RESET !!!");
        // The reboot call is blocking, so we need to do it on another thread.
        Thread thr = new Thread("Reboot") {
            @Override
            public void run() {
                try {
                    RecoverySystem.rebootWipeUserData(context, shutdown, reason);//shutdown=false;reason="MasterClearConfirm"
                    Log.wtf(TAG, "Still running after master clear?!");
                } catch (IOException e) {
                    Slog.e(TAG, "Can't perform master clear/factory reset", e);
                } catch (SecurityException e) {
                    Slog.e(TAG, "Can't perform master clear/factory reset", e);
                }
            }
        };
        thr.start();
    }

二、应用层流程分析

设置模块中恢复出厂设置,不管是否删除SD卡,最终都会执行如下两步:

1、 /cache/recovery/command文件中写入命令字段

2、 重启系统,进入recovery模式

具体可参考framework/base/core/java/android/os/RecoverySystem.java文件,代码片段如下:

 /**
     * Reboots the device and wipes the user data and cache
     * partitions.  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.
     *重启设备并且擦除用户data和cache分区;难免有些用词不当,因为system分区没有回复到出厂状态。
     * @param context   the Context to use
     * @param shutdown  if true, the device will be powered down after
     *                  the wipe completes, rather than being rebooted
     *                  back to the regular system.
     * true,擦除完成后关闭设备;否则重新引导回正常系统;
     * @throws IOException  if writing the recovery command file
     * fails, or if the reboot itself fails.
     * @throws SecurityException if the current user is not allowed to wipe data.
     * 如果当前用户不允许擦除数据,抛出SecurityException。
     * @hide
     */
    public static void rebootWipeUserData(Context context, boolean shutdown, String reason)
            throws IOException {
        UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
        if (um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) {
            throw new SecurityException("Wiping data is not allowed for this user.");
        }
        final ConditionVariable condition = new ConditionVariable();

        Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION");
        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        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);//发送广播:android.intent.action.MASTER_CLEAR_NOTIFICATION,通知所有接收端处理相关行为

        // Block until the ordered broa
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值