最近看恢复出厂的一个问题,以前也查过这方面的流程,所以这里整理一些AP+framework层的流程;
在setting-->备份与重置--->恢复出厂设置--->重置手机--->清除全部内容--->手机关机--->开机--->进行恢复出厂的操作--->开机流程;
Step
1:前面找settings中的布局我就省略了,这部分相对简单一些,直接到清除全部内容这个按钮的操作,
对应的java类是setting中的MasterClearConfirm.java这个类,
privateButton.OnClickListener mFinalClickListener =newButton.OnClickListener() {
publicvoidonClick(View v) {
if(Utils.isMonkeyRunning()) {
return;
}
if(mEraseSdCard) {
Intent intent =newIntent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
getActivity().startService(intent);
}else{
getActivity().sendBroadcast(newIntent("android.intent.action.MASTER_CLEAR"));
// Intent handling is asynchronous -- assume it will happen soon.
}
}
};
private Button.OnClickListener mFinalClickListener = new Button.OnClickListener() {
public void onClick(View v) {
if (Utils.isMonkeyRunning()) {
return;
}
if (mEraseSdCard) {
Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
getActivity().startService(intent);
} else {
getActivity().sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));
// Intent handling is asynchronous -- assume it will happen soon.
}
}
};
通过上述的代码,可以看出,实际上点击清除全部内容的时候,如果前面勾选上格式哈SD卡,就会执行mEraseSdCard为true里面的逻辑,如果没有勾选,就执行mEraseSdCard=false的逻辑,其实就是发送一个广播,
“android.intent.action.MASTER_CLEAR”
“android.intent.action.MASTER_CLEAR”
Step
2:这个广播接受的地方,参见AndroidManifest.xml中的代码,如下:
<receiverandroid:name="com.android.server.MasterClearReceiver"
android:permission="android.permission.MASTER_CLEAR"
android:priority="100">
<intent-filter>
<actionandroid:name="android.intent.action.MASTER_CLEAR"/>
<actionandroid:name="com.google.android.c2dm.intent.RECEIVE"/>
<categoryandroid:name="android.intent.category.MASTER_CLEAR"/>
intent-filter>
receiver>
找这个MasterClearReceiver.java这个receiver,下面来看看这个onReceiver()里面做了什么操作:
publicvoidonReceive(finalContext context,finalIntent 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;
}
}
Slog.w(TAG,"!!! FACTORY RESET !!!");
// The reboot call is blocking, so we need to do it on another thread.
Thread thr =newThread("Reboot") {
@Override
publicvoidrun() {
try{
RecoverySystem.rebootWipeUserData(context);
Log.wtf(TAG,"Still running after master clear?!");
}catch(IOException e) {
Slog.e(TAG,"Can't perform master clear/factory reset", e);
}
}
};
thr.start();
}
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;
}
}
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);
Log.wtf(TAG, "Still running after master clear?!");
} catch (IOException e) {
Slog.e(TAG, "Can't perform master clear/factory reset", e);
}
}
};
thr.start();
}
这个里面主要的操作是:RecoverySystem.rebootWipeUserData(context);准备做重启的动作,告诉手机要清除userData的数据;
Step
3:接着来看看RecoverySystem.rebootWipeUserData()这个方法做了哪些操作:
publicstaticvoidrebootWipeUserData(Context context)throwsIOException {
finalConditionVariable condition =newConditionVariable();
Intent intent =newIntent("android.intent.action.MASTER_CLEAR_NOTIFICATION");
context.sendOrderedBroadcastAsUser(intent, UserHandle.OWNER,
android.Manifest.permission.MASTER_CLEAR,
newBroadcastReceiver() {
@Override
publicvoidonReceive(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());
}
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());
}
这个里面的广播可以先忽略不计,重点来看看bootCommand()这个方法,注意这个参数“--wipe_data\n--locale=”
privatestaticvoidbootCommand(Context context, String arg)throwsIOException {
RECOVERY_DIR.mkdirs();// In case we need it
COMMAND_FILE.delete();// In case it's not writable
LOG_FILE.delete();
FileWriter command =newFileWriter(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");
thrownewIOException("Reboot failed (no permissions?)");
}
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?)");
}
这个方法的操作大致是“写节点/cache/recovery/command”,把传递过来的字符串写进去;然后调用PowerManager进行重启操作,reboot();
Step
4:接着我们来看看PowerManager的reboot方法做了哪些操作:
publicvoidreboot(String reason) {
try{
mService.reboot(false, reason,true);
}catch(RemoteException e) {
}
}
public void reboot(String reason) {
try {
mService.reboot(false, reason, true);
} catch (RemoteException e) {
}
}
这个调用到了PowerManagerService.java这个类的reboot方法中了:
@Override// Binder call
publicvoidreboot(booleanconfirm, String reason,booleanwait) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT,null);
finallongident = Binder.clearCallingIdentity();
try{
shutdownOrRebootInternal(false, confirm, reason, wait);
}finally{
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void reboot(boolean confirm, String reason, boolean wait) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
final long ident = Binder.clearCallingIdentity();
try {
shutdownOrRebootInternal(false, confirm, reason, wait);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
重点来看看shutdownOrRebootInternal()这个方法,
privatevoidshutdownOrRebootInternal(finalbooleanshutdown,finalbooleanconfirm,
finalString reason,booleanwait) {
if(mHandler ==null|| !mSystemReady) {
thrownewIllegalStateException("Too early to call shutdown() or reboot()");
}
Runnable runnable =newRunnable() {
@Override
publicvoidrun() {
synchronized(this) {
if(shutdown) {
ShutdownThread.shutdown(mContext, confirm);
}else{
ShutdownThread.reboot(mContext, reason, confirm);
}
}
}
};
// ShutdownThread must run on a