Bootstrap

android 恢复出厂设置流程分析,Android恢复出厂设置流程分析

最近看恢复出厂的一个问题,以前也查过这方面的流程,所以这里整理一些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

;