com.android.settings.MasterClear
private void showFinalConfirmation() {
Preference preference = new Preference(getActivity());
preference.setFragment(MasterClearConfirm.class.getName());
preference.setTitle(R.string.master_clear_confirm_title);
preference.getExtras().putBoolean(ERASE_EXTERNAL_EXTRA, mExternalStorage.isChecked());
((SettingsActivity) getActivity()).onPreferenceStartFragment(null, preference);
}
MasterClearConfirm.java
Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR);
private void doMasterClear() {
if (mEraseSdCard) {
Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
intent.putExtra(Intent.EXTRA_REASON, "WipeAllFlash");
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.
}
}
core/res/AndroidManifest.xml: <receiver android:name="com.android.server.MasterClearReceiver"
系统注册一个receiver
<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>
services/core/java/com/android/server/MasterClearReceiver.java
Thread thr = new Thread("Reboot") {
@Override
public void run() {
try {
RecoverySystem.rebootWipeUserData(context, shutdown, reason);
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();
格式化sdcard,执行umount命令
core/res/AndroidManifest.xml: <service android:name="com.android.internal.os.storage.ExternalStorageFormatter“
<service android:name="com.android.internal.os.storage.ExternalStorageFormatter"
android:permission="android.permission.MASTER_CLEAR"
android:exported="true" />
services/core/java/com/android/server/MountService.java
public void unmountVolume(String path, boolean force, boolean removeEncryption) {
validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
waitForReady();
String volState = getVolumeState(path);
if (DEBUG_UNMOUNT) {
Slog.i(TAG, "Unmounting " + path
+ " force = " + force
+ " removeEncryption = " + removeEncryption);
}
if (Environment.MEDIA_UNMOUNTED.equals(volState) ||
Environment.MEDIA_REMOVED.equals(volState) ||
Environment.MEDIA_SHARED.equals(volState) ||
Environment.MEDIA_UNMOUNTABLE.equals(volState)) {
// Media already unmounted or cannot be unmounted.
// TODO return valid return code when adding observer call back.
return;
}
UnmountCallBack ucb = new UnmountCallBack(path, force, removeEncryption);
mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_PM_UPDATE, ucb));
}
private int doUnmountVolume(String path, boolean force, boolean removeEncryption) {
if (!getVolumeState(path).equals(Environment.MEDIA_MOUNTED)) {
return VoldResponseCode.OpFailedVolNotMounted;
}
/*
* Force a GC to make sure AssetManagers in other threads of the
* system_server are cleaned up. We have to do this since AssetManager
* instances are kept as a WeakReference and it's possible we have files
* open on the external storage.
*/
Runtime.getRuntime().gc();
// Redundant probably. But no harm in updating state again.
if (path.equals(mExternalStoragePath)) //only flash
{
mPms.updateExternalMediaStatus(false, false);
}
try {
final Command cmd = new Command("volume", "unmount", path);
if (removeEncryption) {
cmd.appendArg("force_and_revert");
} else if (force) {
cmd.appendArg("force");
}
mConnector.execute(cmd);
// We unmounted the volume. None of the asec containers are available now.
synchronized (mAsecMountSet) {
mAsecMountSet.clear();
}
return StorageResultCode.OperationSucceeded;
} catch (NativeDaemonConnectorException e) {
// Don't worry about mismatch in PackageManager since the
// call back will handle the status changes any way.
int code = e.getCode();
if (code == VoldResponseCode.OpFailedVolNotMounted) {
return StorageResultCode.OperationFailedStorageNotMounted;
} else if (code == VoldResponseCode.OpFailedStorageBusy) {
return StorageResultCode.OperationFailedStorageBusy;
} else {
return StorageResultCode.OperationFailedInternalError;
}
}
}