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

2023-10-31

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

 一、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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android--Recovery模块之恢复出厂设置 的相关文章

随机推荐

  • R语言的基本数据类型:数值,字符串,逻辑

    R语言的基本数据类型 数值 双整型 储存普通数值型数据 可正可负 可大可小 可含小数可不含 R中输入的任何一个数值都默认以双整型存储 可以使用typeof 函数来查看对象类型 在数据科学里 它更常被称为数值型 整型 只能用来储存正数 在R中
  • 前端面试题之——兼容篇

    兼容性面试题 一 html 部分 1 H5 新标签在 IE9 以下的浏览器识别 html5shiv js 下载地址 2 ul 标签内外边距问题 ul 标签在 IE6 IE7 中 有个默认的外边距 但是在 IE8 以上及其他浏览器中 有个默认
  • websphere6.x 调用集群EJB的Context.PROVIDER_URL写法

    import java util Hashtable import javax naming Context import javax naming InitialContext Hashtable env new Hashtable en
  • caffe源码解析 — net.cpp

    Net类是Solve类的一个成员 在net cpp中定义了对Net的所有操作 其中包括 Init GetLearningRateAndWeightDecay ForwardPrefilled Backward ShareTrainedLay
  • 计算机数值转换教案,计算机数值方法教案.doc

    第O章 绪论 一 教学设计 1 教学内容 数值计算方法这门课程的形成背景及主要研究内容 研究方法 主要特点 算法的有关概念及要求 误差的来源 意义 及其有关概念 数值计算中应注意的一些问题 2 重点难点 算法设计及其表达法 误差的基本概念
  • 数据结构——快速排序

    1 原理及代码实现 快速排序 快速排序也是一种分治的排序算法 快速排序和归并排序是互补的 归并排序将数组分成两个子数组分别排序 并将有序的子数组归并以将整个数组排序 会需要一个额外的数组 而快速排序的排序方式是当两个子数组都有序时 整个数组
  • @Async注解线程池

    在启动类上添加 EnableAsync配合该注解使用 自定义线程池方法 implements AsyncConfigurer extends AsyncSupportConfigurer Bean 注入线程池 public interfac
  • Shell中表示数字跨度的几种方式

    在Shell脚本中 如果要输出数字为0 20中3的倍数 可以使用下面三种方式来完成 方式一 i 0 i lt 20 i 3 for i 0 i lt 20 i 3 do echo i done 方式二 0 20 3 for i in 0 2
  • ElasticSearch 评分排序

    背景 通过脚本改变评分 背景 近期有一个需求 需要对优惠券可用商品列表加个排序 只针对面值类的券不包括折扣券 需求是这样的 假设有一张面值券 50 块钱 可用商品列表 A 100 B 40 C 10 当用户查询当前券可用商品列表的时候优先将
  • RuntimeError: expected dtype Double but got dtype Float 损失求导出错

    求导出现问题 源代码 修改为 把损失修改为loss clone detach requires grad
  • 卫星通信的资源调度 vs 地面无线通信的资源调度

    以OFDM系统为例 考虑多个用户共用多个子载波的场景 一 两类资源 调整时频资源 即基站或卫星决定给各个用户在哪些时隙分配多少子载波 调整发射功率 即基站或卫星决定给每个用户在每个子信道上的功率是多大 用字母 P n k P n k Pn
  • 【TestNG】TestNG使用教程详解

    一 TestNG介绍 TestNG是Java中的一个测试框架 类似于JUnit 和NUnit 功能都差不多 只是功能更加强大 使用也更方便 详细使用说明请参考官方链接 https testng org doc index html 二 Te
  • anaconda 创建虚拟环境、激活及使用的基本方法

    1 查看当前存在的虚拟环境 conda env list 2 创建虚拟环境 环境名 conda create n 环境名 python X X 3 激活指定虚拟环境 activate 环境名 4 删除虚拟环境 conda remove n
  • c++ 鼠标控制

    windows下获得鼠标位置和控制鼠标 include
  • 使用nodejs开发一个markdown文档管理小系统(一)Using Nodejs to quickly develop a markdown management system...

    好多年没碰过前端jquery了 用一两天时间重温一下 刚好写个小工具 不递归取文件夹和文件 只写一层 保持足够简单 验证和参数判断暂不写 毕竟只写了几个小时而已 功能算完备了 添加一个简单的管理员权限管理修改的所有功能即可放出去了 看来还不
  • LaTeX各种算法排版

    1 首先在导言区加入语句 usepackage algorithm usepackage algorithmic 2 例1 begin algorithm caption A label alg A begin algorithmic ST
  • AUTOSEMO“恒以致远,共创共赢”主题研讨会圆满落幕

    2023年8月31日 中国汽车工业协会软件分会中国汽车基础软件生态标委会 简称 AUTOSEMO 与天津市西青区人民政府联合主办 北京经纬恒润科技股份有限公司承办的 恒以致远 共创共赢 主题研讨会在天津隆重召开 本次研讨会是AUTOSEMO
  • vue2.0使用less 创建全局的颜色变量,配置主题色

    1 使用场景 项目中需要统一配置前端的主题样式 我们可以使用less创建 theme colors rgba 54 174 149 1 变量 供全局调用 2 安装依赖 cnpm install less less loader save 安
  • 【Android】WebView控件最全使用解析

    WebView控件最全使用解析 一 WebView 概述 二 WebView使用基础篇 2 1添加方式 2 2 加载远程网页 2 3 加载本地网页 2 4 加载HTML片段 2 5 WebView 常用方法 三 WebView 进阶篇 3
  • Android--Recovery模块之恢复出厂设置

    一 在进行详细流程分析之前 先看一下几个重要概念 一 Recovery的工作需要整个软件平台的配合 从架构角度看 有三个部分 1 Main system 用boot img启动的Linux系统 Android的正常工作模式 2 Recove