今天来从源码的角度 分析一下android 系统复位的流程

1. 从点击 Reset 看起。点击Reset后,会弹出Erase everything。故而从在Setting中搜索此字段开始。


因为我这里面有TV项目,也有手机项目。这里就看手机项目,即“master_clear_final_button_text”字段。

packages\apps\Settings\res\layout\master_clear_confirm.xml

接下来找这个button 的点击事件。

packages\apps\Settings\src\com\android\settings\MasterClearConfirm.java
public class MasterClearConfirm extends InstrumentedFragment {private View mContentView;private boolean mEraseSdCard;private boolean mEraseEsims;/*** The user has gone through the multiple confirmation, so now we go ahead* and invoke the Checkin Service to reset the device to its factory-default* state (rebooting in the process).*/private Button.OnClickListener mFinalClickListener = new Button.OnClickListener() {public void onClick(View v) {if (Utils.isMonkeyRunning()) {return;}final PersistentDataBlockManager pdbManager = (PersistentDataBlockManager)getActivity().getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);final OemLockManager oemLockManager = (OemLockManager)getActivity().getSystemService(Context.OEM_LOCK_SERVICE);if (pdbManager != null && !oemLockManager.isOemUnlockAllowed() &&Utils.isDeviceProvisioned(getActivity())) {// if OEM unlock is allowed, the persistent data block will be wiped during FR// process. If disabled, it will be wiped here, unless the device is still being// provisioned, in which case the persistent data block will be preserved.new AsyncTask<Void, Void, Void>() {int mOldOrientation;ProgressDialog mProgressDialog;@Overrideprotected Void doInBackground(Void... params) {pdbManager.wipe();return null;}@Overrideprotected void onPostExecute(Void aVoid) {mProgressDialog.hide();if (getActivity() != null) {getActivity().setRequestedOrientation(mOldOrientation);doMasterClear();    //  点击后此方法}}@Overrideprotected void onPreExecute() {mProgressDialog = getProgressDialog();mProgressDialog.show();   // 执行时 转圈等待// need to prevent orientation changes as we're about to go into// a long IO request, so we won't be able to access inflate resources on flashmOldOrientation = getActivity().getRequestedOrientation();getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);}}.execute();} else {doMasterClear();}}private ProgressDialog getProgressDialog() {final ProgressDialog progressDialog = new ProgressDialog(getActivity());progressDialog.setIndeterminate(true);progressDialog.setCancelable(false);progressDialog.setTitle(getActivity().getString(R.string.master_clear_progress_title));progressDialog.setMessage(getActivity().getString(R.string.master_clear_progress_text));return progressDialog;}};private void doMasterClear() {   //  重点是这个方法,其实是发送了一个广播。Intent intent = new Intent(Intent.ACTION_FACTORY_RESET);//intent.setPackage("android");intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);intent.putExtra(Intent.EXTRA_REASON, "MasterClearConfirm");intent.putExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, mEraseSdCard);intent.putExtra(Intent.EXTRA_WIPE_ESIMS, mEraseEsims);getActivity().sendBroadcast(intent);  // Intent handling is asynchronous -- assume it will happen soon.}/*** Configure the UI for the final confirmation interaction*/private void establishFinalConfirmationState() {mContentView.findViewById(R.id.execute_master_clear).setOnClickListener(mFinalClickListener);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(getActivity(), UserManager.DISALLOW_FACTORY_RESET, UserHandle.myUserId());if (RestrictedLockUtils.hasBaseUserRestriction(getActivity(),UserManager.DISALLOW_FACTORY_RESET, UserHandle.myUserId())) {return inflater.inflate(R.layout.master_clear_disallowed_screen, null);} else if (admin != null) {new ActionDisabledByAdminDialogHelper(getActivity()).prepareDialogBuilder(UserManager.DISALLOW_FACTORY_RESET, admin).setOnDismissListener(__ -> getActivity().finish()).show();return new View(getActivity());}mContentView = inflater.inflate(R.layout.master_clear_confirm, null);establishFinalConfirmationState();setAccessibilityTitle();return mContentView;}private void setAccessibilityTitle() {CharSequence currentTitle = getActivity().getTitle();TextView confirmationMessage =(TextView) mContentView.findViewById(R.id.master_clear_confirm);if (confirmationMessage != null) {String accessibleText = new StringBuilder(currentTitle).append(",").append(confirmationMessage.getText()).toString();getActivity().setTitle(Utils.createAccessibleSequence(currentTitle, accessibleText));}}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Bundle args = getArguments();mEraseSdCard = args != null&& args.getBoolean(MasterClear.ERASE_EXTERNAL_EXTRA);mEraseEsims = args != null&& args.getBoolean(MasterClear.ERASE_ESIMS_EXTRA);}@Overridepublic int getMetricsCategory() {return MetricsEvent.MASTER_CLEAR_CONFIRM;}
}

从上面可以看出,用户点击reset 后,其实是发送了一个名为ACTION_FACTORY_RESET(android.intent.action.FACTORY_RESET)的广播。这里值得注意的是:以前的广播为android.intent.action.MASTER_CLEAR,但是已经被ACTION_FACTORY_RESET 替换

 /*** Deprecated - use ACTION_FACTORY_RESET instead.* @hide* @removed*/
@Deprecated
@SystemApi
public static final String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
2. 接下来查找接受这个广播的地方,通过全局grep 搜索 。得到:
 frameworks/base/services/core/java/com/android/server/MasterClearReceiver.javapublic class MasterClearReceiver extends BroadcastReceiver {private static final String TAG = "MasterClear";private boolean mWipeExternalStorage;private boolean mWipeEsims;@Overridepublic 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;}}if (Intent.ACTION_MASTER_CLEAR.equals(intent.getAction())) {Slog.w(TAG, "The request uses the deprecated Intent#ACTION_MASTER_CLEAR, "+ "Intent#ACTION_FACTORY_RESET should be used instead.");//这里都在说 广播都替换了}if (intent.hasExtra(Intent.EXTRA_FORCE_MASTER_CLEAR)) {Slog.w(TAG, "The request uses the deprecated Intent#EXTRA_FORCE_MASTER_CLEAR, "+ "Intent#EXTRA_FORCE_FACTORY_RESET should be used instead.");}final boolean shutdown = intent.getBooleanExtra("shutdown", false);final String reason = intent.getStringExtra(Intent.EXTRA_REASON);mWipeExternalStorage = intent.getBooleanExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, false);mWipeEsims = intent.getBooleanExtra(Intent.EXTRA_WIPE_ESIMS, false);final boolean forceWipe = intent.getBooleanExtra(Intent.EXTRA_FORCE_MASTER_CLEAR, false)|| intent.getBooleanExtra(Intent.EXTRA_FORCE_FACTORY_RESET, false);// 发广播时传过来的参数Slog.w(TAG, "!!! FACTORY RESET !!!");// The reboot call is blocking, so we need to do it on another thread.Thread thr = new Thread("Reboot") {@Overridepublic void run() {try {RecoverySystem.rebootWipeUserData(context, shutdown, reason, forceWipe, mWipeEsims);//重点,准备做重启擦除用户数据的动作。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);}}};if (mWipeExternalStorage || mWipeEsims) { // 如果传过来 这个参数为true的话,则进行清除SD的操作。// thr will be started at the end of this task.new WipeDataTask(context, thr).execute();} else {thr.start();}}private class WipeDataTask extends AsyncTask<Void, Void, Void> { // 利用AsyncTask 清除SD数据。默认不清除private final Thread mChainedTask;private final Context mContext;private final ProgressDialog mProgressDialog;public WipeDataTask(Context context, Thread chainedTask) {mContext = context;mChainedTask = chainedTask;mProgressDialog = new ProgressDialog(context);}@Overrideprotected void onPreExecute() {mProgressDialog.setIndeterminate(true);mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);mProgressDialog.setMessage(mContext.getText(R.string.progress_erasing));mProgressDialog.show();}@Overrideprotected Void doInBackground(Void... params) {Slog.w(TAG, "Wiping adoptable disks");if (mWipeExternalStorage) {StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);sm.wipeAdoptableDisks();}return null;}@Overrideprotected void onPostExecute(Void result) {mProgressDialog.dismiss();mChainedTask.start();}}}
3.RecoverySystem.java 中rebootWipeUserData 方法,擦除用户数据
 frameworks\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.** @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.* @param reason    the reason for the wipe that is visible in the logs* @param force     whether the {@link UserManager.DISALLOW_FACTORY_RESET} user restriction*                  should be ignored* @param wipeEuicc whether wipe the euicc data** @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.** @hide*/public static void rebootWipeUserData(Context context, boolean shutdown, String reason,boolean force, boolean wipeEuicc) throws IOException {UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);if (!force && 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| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);context.sendOrderedBroadcastAsUser(intent, UserHandle.SYSTEM,android.Manifest.permission.MASTER_CLEAR,new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {condition.open();}}, null, 0, null, null);// Block until the ordered broadcast has completed.condition.block();if (wipeEuicc) {wipeEuiccData(context, PACKAGE_NAME_WIPING_EUICC_DATA_CALLBACK);}String shutdownArg = null;if (shutdown) {shutdownArg = "--shutdown_after";}String reasonArg = null;if (!TextUtils.isEmpty(reason)) {reasonArg = "--reason=" + sanitizeArg(reason);}final String localeArg = "--locale=" + Locale.getDefault().toLanguageTag() ;bootCommand(context, shutdownArg, "--wipe_data", reasonArg, localeArg);//重点是这个方法,将一些重要的字段信息保存起来}

bootCommand方法

 /*** Reboot into the recovery system with the supplied argument.* @param args to pass to the recovery utility.* @throws IOException if something goes wrong.*/private static void bootCommand(Context context, String... args) throws IOException {LOG_FILE.delete();StringBuilder command = new StringBuilder();for (String arg : args) {if (!TextUtils.isEmpty(arg)) {command.append(arg);command.append("\n");// 将字段命令拼接起来}}// Write the command into BCB (bootloader control block) and boot from// there. Will not return unless failed.RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);rs.rebootRecoveryWithCommand(command.toString());//throw new IOException("Reboot failed (no permissions?)");}
4. 调用系统服务 RecoverySystemService.java
frameworks\base\services\core\java\com\android\server\RecoverySystemService.java@Override // Binder callpublic void rebootRecoveryWithCommand(String command) {if (DEBUG) Slog.d(TAG, "rebootRecoveryWithCommand: [" + command + "]");synchronized (sRequestLock) {if (!setupOrClearBcb(true, command)) {return;}// Having set up the BCB, go ahead and reboot.PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);pm.reboot(PowerManager.REBOOT_RECOVERY);}}private boolean setupOrClearBcb(boolean isSetup, String command) {mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);final boolean available = checkAndWaitForUncryptService();if (!available) {Slog.e(TAG, "uncrypt service is unavailable.");return false;}if (isSetup) {SystemProperties.set("ctl.start", "setup-bcb");} else {SystemProperties.set("ctl.start", "clear-bcb");}// Connect to the uncrypt service socket.LocalSocket socket = connectService();if (socket == null) {Slog.e(TAG, "Failed to connect to uncrypt socket");return false;}DataInputStream dis = null;DataOutputStream dos = null;try {dis = new DataInputStream(socket.getInputStream());dos = new DataOutputStream(socket.getOutputStream());// Send the BCB commands if it's to setup BCB.if (isSetup) {byte[] cmdUtf8 = command.getBytes("UTF-8");dos.writeInt(cmdUtf8.length);dos.write(cmdUtf8, 0, cmdUtf8.length);dos.flush();}// Read the status from the socket.int status = dis.readInt();// Ack receipt of the status code. uncrypt waits for the ack so// the socket won't be destroyed before we receive the code.dos.writeInt(0);if (status == 100) {Slog.i(TAG, "uncrypt " + (isSetup ? "setup" : "clear") +" bcb successfully finished.");} else {// Error in /system/bin/uncrypt.Slog.e(TAG, "uncrypt failed with status: " + status);return false;}} catch (IOException e) {Slog.e(TAG, "IOException when communicating with uncrypt:", e);return false;} finally {IoUtils.closeQuietly(dis);IoUtils.closeQuietly(dos);IoUtils.closeQuietly(socket);}return true;}
5.通过PowerManager 进行重启,重启流程可参见android系统关机源码(9.0)流程分析

这里有非常重要的一点:
在执行重启的时候,最终会走到以下的方法中:

frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java/*** Low-level function to reboot the device. On success, this* function doesn't return. If more than 20 seconds passes from* the time a reboot is requested, this method returns.** @param reason code to pass to the kernel (e.g. "recovery"), or null.*/public static void lowLevelReboot(String reason) {if (reason == null) {reason = "";}// If the reason is "quiescent", it means that the boot process should proceed// without turning on the screen/lights.// The "quiescent" property is sticky, meaning that any number// of subsequent reboots should honor the property until it is reset.if (reason.equals(PowerManager.REBOOT_QUIESCENT)) {sQuiescent = true;reason = "";} else if (reason.endsWith("," + PowerManager.REBOOT_QUIESCENT)) {sQuiescent = true;reason = reason.substring(0,reason.length() - PowerManager.REBOOT_QUIESCENT.length() - 1);}if (reason.equals(PowerManager.REBOOT_RECOVERY)|| reason.equals(PowerManager.REBOOT_RECOVERY_UPDATE)) {reason = "recovery";   //走这个,reason为 recovery}if (sQuiescent) {// Pass the optional "quiescent" argument to the bootloader to let it know// that it should not turn the screen/lights on.reason = reason + ",quiescent";}SystemProperties.set("sys.powerctl", "reboot," + reason);//通过设置reason的属性,则重启开机后,会进入到recovery 模式,进行清除数据try {Thread.sleep(20 * 1000L);} catch (InterruptedException e) {Thread.currentThread().interrupt();}Slog.wtf(TAG, "Unexpected return from lowLevelReboot!");}

到此,android 系统复位的流程就分析完毕。总结一下:

恢复出厂设置总结:
1、在MasterClearConfirm.java中确认开始执行恢复出厂设置操作,并发出"恢复出厂设置"的广播;
2、在MasterClearReceiver.java接收MasterClearConfirm.java发出的广播,根据是否清除sdcard选项来执行相应的操作;
3、调用RecoverySystem.rebootWipeUserData()方法来清除用户数据并重启设备;这个方法执行过程中会发出"android.intent.action.MASTER_CLEAR_NOTIFICATION"广播、写"/cache/recovery/command"文件(内容包含"--wipe_data"),然后重启设备;
4、设备重启后进入recovery mode之后,读取/cache/recovery/command, 內容为"--wipe_data";
5.按照读取的command,进行wipe data清除数据操作;
6.清除成功后,系统重启,然后进入正常开机流程。

参考博客:
Android6.0 Reset恢复出厂设置流程分析

android 系统复位(Reset 恢复出厂设置)9.0源码分析相关推荐

  1. 电脑计算机里怎么找恢复出厂设置,Windows系统电脑如何恢复出厂设置?

    原标题:Windows系统电脑如何恢复出厂设置? 最近有位朋友发现电脑使用时间久了,出现了运行卡顿和系统垃圾过多的问题,想知道是否可以通过恢复出厂设置来解决.其实,电脑Windows系统恢复出厂设置是 ...

  2. w10恢复出厂设置_Win10系统怎么操作恢复出厂设置_w10恢复出厂设置教程

    Win10系统怎么操作恢复出厂设置_W10恢复出厂设置教程.近期有用户反馈称,自己的win10系统在清理病毒过程中,出现功能混乱的情况,导致系统出现各种各样的问题,所以想手动操作恢复系统的出厂设置,那 ...

  3. Android6.0 Reset恢复出厂设置流程分析

    点击Settings应用中的恢复出厂设置按钮后流程分析: 先使用grep命令搜索"恢复出厂设置"字符串,找到相应的布局文件: packages/apps/Settings/res/ ...

  4. 华为手机怎样恢复Android,华为手机怎么恢复出厂设置 华为恢复出厂设置的两种方法...

    当我们的华为手机出现一些系统错乱或感染病毒或因个人原因想让我们的手机恢复出厂设置,让手机全变得一干二净,跟我们刚买来时的状态一样,我们该去哪里操作呢,下面,让小编带大家一起了解下这方面的知识. 华为恢 ...

  5. Android最新版,恢复出厂设置

    文章目录 前言 1.原生设置源码路径: 2.源码解释 3.APP的调用 前言 Android12下,如何恢复出厂设置 1.原生设置源码路径: 系统源码/package/apps/Settings/sr ...

  6. 恢复出厂设置android手机号码,手机怎么恢复出厂设置 安卓手机恢复出厂设置方法汇总...

    最近接连有不少身边的朋友遇到一些比较奇怪的智能手机问题,比如最开始有朋友无意间设置了图案锁屏保护密码,但之后却不记得自设置的图案密码,导致连续五次解锁失败,手机直接成为了锁定状态,需要注册的谷歌账号密 ...

  7. 恢复出厂设置android手机号码,安卓手机恢复出厂设置会怎么样?

    安卓手机恢复出厂设置会怎么样?事实上,用户若是主动将安卓手机恢复出厂设置,未备份的手机号码(在手机里面的,SIM卡中的电话号码不影响).短信.应用.设置等数据就会被直接删除. 安卓手机恢复出厂设置会怎 ...

  8. 计算机xp系统恢复以前设置,最新版:如何在XP系统计算机上恢复出厂设置?

    sppWatcher 计算机不具有出厂设置.您是要恢复出厂设置吗?如果这是您需要自己准备的东西,或者您没有准备,那将什么也没有. 如何使用XP还原系统(有一个前提条件,如果您的计算机崩溃,出现蓝屏,无 ...

  9. Win8先体验(6)——全新系统还原/一键恢复出厂设置[M3]

    [原创不易,转载请注明原文链接及作者,谢谢!]   先请看一张恢复之前的图片,为了跟恢复之后作对比: (哎,看下面同学说这个苹果很刺眼--偶纯是为了对比才换的桌面,随便选了一张ipad的截图..让大家 ...

最新文章

  1. ecos 编译时无法找到 tclConfig.sh 和 tkConfig.sh
  2. 内存的分配方式有几种? 动态内存的的传递注意事项!
  3. 填平数据、产品、模式需求鸿沟,浪潮云发布新一代行业云 MEP战略
  4. 看我如何用python来玩百万英雄
  5. vue-cli入门之项目结构分析
  6. 前端性能优化学习(慕课网)笔记
  7. 计算机软件版本号是什么意思,带你深入了解解密Windows系统版本和版本号
  8. 米思齐+blynk双登录控制(米思齐Mixly的新玩法)
  9. linux三种用户界面,Linux的图形用户界面-你会选择哪个?
  10. 2004. 职员招聘人数
  11. [转]CreateDIBitmap与CreateDIBSection
  12. pr 调整图层缩放移动无效
  13. 【微信小程序】随机点名系统(点击开始滚动名字点击结束按钮结束滚动)
  14. 安全专家:50% 的服务器在补丁发布后,很长时间未修复
  15. TensorFlow 字符串 与数字 互相转换
  16. 生信分析、数据库网站集合
  17. Android 一些Api说明
  18. 用筛选法求100之内的素数(C语言 数组)
  19. 【前端】组件基础使用
  20. 古堡算式 福尔摩斯到某古堡探险,看到门上写着一个奇怪的算式: ABCDE * ? = EDCBA

热门文章

  1. 网络广告术语CPC、CPM和CTR的含义和关系
  2. 【游戏开发教程】Unity Cinemachine快速上手,详细案例讲解(虚拟相机系统 | 新发出品 | 良心教程)
  3. 抽丝剥茧看华为p20pro, 三星s9+, 小米8 样张低频彩噪
  4. 【网络安全】MS17-010“永恒之蓝”漏洞的利用
  5. xrd连续扫描和步进扫描_X射线衍射仪(XRD)相关术语解释
  6. 现实迷途 第三十章 若即若离
  7. DOM的绑定事件事件
  8. 分词工具比较及使用(ansj、hanlp、jieba)
  9. Qt 编译动态库只生成dll没有lib文件
  10. 【Unity3D游戏开发学习笔记】(七)上帝之眼—第三人称摄像机的简单实现(跟随视角,自由视角)