前言:
恢复出厂设置的本质上是先写入command到BCB中,然后让手机进入recovery模式,此时会根据BCB中的命令来执行对应的操作,本文主要分析java层的流程。力有不逮,如有错漏,请多指教。
流程图:
流程分析:
packages/apps/Settings/src/com/android/settings/MasterClearConfirm.java
恢复出厂设置的功能在设置中,源生版本中用户通过点击恢复出厂设置的button就可以了
private void doMasterClear() {
Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_REASON, "MasterClearConfirm");
//参数的意思是是否擦除SdCard,默认为false
intent.putExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, mEraseSdCard);
//step:[1]
getActivity().sendBroadcast(intent);
// Intent handling is asynchronous -- assume it will happen soon.
}
可以看出设置中只是简单的发送了一个广播,理所当然的需要找到广播的接受者–MasterClearReceiver.java
frameworks/base/services/core/java/com/android/server/MasterClearReceiver.java
接收到设置发出的恢复出厂设置的广播之后,将会调用RecoverySystem的rebootWipeUserData方法
@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);
final boolean wipeExternalStorage = intent.getBooleanExtra(
Intent.EXTRA_WIPE_EXTERNAL_STORAGE, false);
final boolean forceWipe = intent.getBooleanExtra(Intent.EXTRA_FORCE_MASTER_CLEAR, 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") {
@Override
public void run() {
try {
//step:[2]
RecoverySystem.rebootWipeUserData(context, shutdown, reason, forceWipe);
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 (wipeExternalStorage) {
// thr will be started at the end of this task.
// 继承AsyncTask的类,发现此处擦除的SdCard指的是android M 新加入的使用外部存储卡扩容为
// 内置存储设备的功能中的存储位置--SD卡或者USB存储设备,不是传统data分区下的SdCard
// 另一方面分析,手机进入recovery模式之后,直接擦除data分区,SdCard目录包含在内,这
// 样SdCard必然会被擦除,那么不必在此做多余擦除操作。
new WipeAdoptableDisksTask(context, thr).execute();
} else {
thr.start();
}
}
frameworks/base/core/java/android/os/RecoverySystem.java
public static void rebootWipeUserData(Context context, boolean shutdown, String reason,
boolean force) 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);
context.sendOrderedBroadcastAsUser(intent, UserHandle.SYSTEM,
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();
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().toString();
//step:[3]
bootCommand(context, shutd