1、Settings中点击重置选项后进入的布局如下
packages/apps/Settings/res/xml/reset_dashboard_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
android:title="@string/reset_dashboard_title"
android:key="reset_dashboard_fragment_screen">
<!-- Network reset -->
<com.android.settingslib.RestrictedPreference
android:key="network_reset_pref"
android:title="@string/reset_network_title"
settings:userRestriction="no_network_reset"
settings:useAdminDisabledSummary="true"
android:fragment="com.android.settings.ResetNetwork" />
<!-- Reset app preferences -->
<Preference
android:key="reset_app_prefs"
android:title="@string/reset_app_preferences" />
<!-- Factory reset -->
<com.android.settingslib.RestrictedPreference
android:key="factory_reset"
android:title="@string/master_clear_title"
settings:keywords="@string/keywords_factory_data_reset"
settings:userRestriction="no_factory_reset"
settings:useAdminDisabledSummary="true"
android:fragment="com.android.settings.MasterClear" />
</PreferenceScreen>
2、如下是重置应用的逻辑处理
packages/apps/Settings/src/com/android/settings/applications/ResetAppPrefPreferenceController.java
package com.android.settings.applications;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.preference.Preference;
import android.text.TextUtils;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnCreate;
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
public class ResetAppPrefPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnCreate, OnSaveInstanceState {
privat ResetAppsHelper mResetAppsHelper;//ResetAppsHelper的是重点逻辑处理
public ResetAppPrefPreferenceController(Context context, Lifecycle lifecycle) {
super(context);
mResetAppsHelper = new ResetAppsHelper(context);
if (lifecycle != null) {
lifecycle.addObserver(this);
}
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
return false;
}
mResetAppsHelper.buildResetDialog();
return true;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public String getPreferenceKey() {
return "reset_app_prefs";
}
@Override
public void onCreate(Bundle savedInstanceState) {
mResetAppsHelper.onRestoreInstanceState(savedInstanceState);
}
@Override
public void onSaveInstanceState(Bundle outState) {
mResetAppsHelper.onSaveInstanceState(outState);
}
}
3、packages/apps/Settings/src/com/android/settings/applications/ResetAppsHelper.java
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.AppOpsManager;
import android.app.INotificationManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.net.NetworkPolicyManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.webkit.IWebViewUpdateService;
import com.android.settings.R;
import java.util.List;
public class ResetAppsHelper implements DialogInterface.OnClickListener,
DialogInterface.OnDismissListener {
private static final String EXTRA_RESET_DIALOG = "resetDialog";
private final PackageManager mPm;
private final IPackageManager mIPm;
private final INotificationManager mNm;
private final IWebViewUpdateService mWvus;
private final NetworkPolicyManager mNpm;
private final AppOpsManager mAom;
private final Context mContext;
private AlertDialog mResetDialog;
public ResetAppsHelper(Context context) {
mContext = context;
mPm = context.getPackageManager();
mIPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
mNm = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
mWvus = IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate"));
mNpm = NetworkPolicyManager.from(context);
mAom = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
}
public void onRestoreInstanceState(Bundle savedInstanceState) {
if (savedInstanceState != null && savedInstanceState.getBoolean(EXTRA_RESET_DIALOG)) {
buildResetDialog();
}
}
public void onSaveInstanceState(Bundle outState) {
if (mResetDialog != null) {
outState.putBoolean(EXTRA_RESET_DIALOG, true);
}
}
public void stop() {
if (mResetDialog != null) {
mResetDialog.dismiss();
mResetDialog = null;
}
}
void buildResetDialog() {
if (mResetDialog == null) {
mResetDialog = new AlertDialog.Builder(mContext)
.setTitle(R.string.reset_app_preferences_title)
.setMessage(R.string.reset_app_preferences_desc)
.setPositiveButton(R.string.reset_app_preferences_button, this)
.setNegativeButton(R.string.cancel, null)
.setOnDismissListener(this)
.show();
}
}
@Override
public void onDismiss(DialogInterface dialog) {
if (mResetDialog == dialog) {
mResetDialog = null;
}
}
@Override
public void onClick(DialogInterface dialog, int which) {
if (mResetDialog != dialog) {
return;
}
AsyncTask.execute(new Runnable() {
@Override
public void run() {
List<ApplicationInfo> apps = mPm.getInstalledApplications(
PackageManager.GET_DISABLED_COMPONENTS);
for (int i = 0; i < apps.size(); i++) {
ApplicationInfo app = apps.get(i);
try {
mNm.setNotificationsEnabledForPackage(app.packageName, app.uid, true);
} catch (android.os.RemoteException ex) {
}
if (!app.enabled) {
if (mPm.getApplicationEnabledSetting(app.packageName)
== PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER
&& !isNonEnableableFallback(app.packageName)) {
mPm.setApplicationEnabledSetting(app.packageName,
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
PackageManager.DONT_KILL_APP);
}
}
}
try {
mIPm.resetApplicationPreferences(UserHandle.myUserId());
} catch (RemoteException e) {
}
mAom.resetAllModes();
final int[] restrictedUids = mNpm.getUidsWithPolicy(
POLICY_REJECT_METERED_BACKGROUND);
final int currentUserId = ActivityManager.getCurrentUser();
for (int uid : restrictedUids) {
// Only reset for current user
if (UserHandle.getUserId(uid) == currentUserId) {
mNpm.setUidPolicy(uid, POLICY_NONE);
}
}
}
});
}
private boolean isNonEnableableFallback(String packageName) {
try {
return mWvus.isFallbackPackage(packageName);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
}
4、packages/apps/Settings/res/layout/master_clear.xml
<Button
android:id="@+id/initiate_master_clear"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dip"
android:layout_marginBottom="12dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/master_clear_button_text"
android:gravity="center" />
5、packages/apps/Settings/src/com/android/settings/MasterClear.java
mInitiateButton = (Button) mContentView.findViewById(R.id.initiate_master_clear);
mInitiateButton.setOnClickListener(mInitiateListener);
protected final Button.OnClickListener mInitiateListener = new Button.OnClickListener() {
public void onClick(View view) {
final Context context = view.getContext();
if (Utils.isDemoUser(context)) {
final ComponentName componentName = Utils.getDeviceOwnerComponent(context);
if (componentName != null) {
final Intent requestFactoryReset = new Intent()
.setPackage(componentName.getPackageName())
.setAction(Intent.ACTION_FACTORY_RESET);
context.startActivity(requestFactoryReset);
}
/*SPRD added for bug 692488, pop a dialog when low battery */
} else if (mLevelpower < POWER_LIMIT) {
mIsDialogShow = true;
dialog();
} else if (!runKeyguardConfirmation(KEYGUARD_REQUEST)) {
showFinalConfirmation();
}
}
};
6、packages/apps/Settings/res/layout/master_clear_confirm.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
android:id="@+id/master_clear_confirm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:layout_marginTop="12dp"
android:textSize="20sp"
android:text="@string/master_clear_final_desc" />
<Button android:id="@+id/execute_master_clear"
android:layout_gravity="center_horizontal"
android:layout_marginTop="40dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/master_clear_final_button_text"
android:gravity="center" />
</LinearLayout>
7、packages/apps/Settings/src/com/android/settings/MasterClearConfirm.java
private void establishFinalConfirmationState() {
mContentView.findViewById(R.id.execute_master_clear)
.setOnClickListener(mFinalClickListener);
}
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;
@Override
protected Void doInBackground(Void... params) {
pdbManager.wipe();
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
mProgressDialog.hide();
if (getActivity() != null) {
getActivity().setRequestedOrientation(mOldOrientation);
doMasterClear();
}
}
@Override
protected 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 flash
mOldOrientation = 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;
}
};
8、frameworks/base/services/core/java/com/android/server/MasterClearReceiver.java
public class MasterClearReceiver extends BroadcastReceiver {
private static final String TAG = "MasterClear";
private boolean mWipeExternalStorage;
private boolean mWipeEsims;
@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;
}
}
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") {
@Override
public 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) {
// 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> {
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);
}
@Override
protected void onPreExecute() {
mProgressDialog.setIndeterminate(true);
mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
mProgressDialog.setMessage(mContext.getText(R.string.progress_erasing));
mProgressDialog.show();
}
@Override
protected Void doInBackground(Void... params) {
Slog.w(TAG, "Wiping adoptable disks");
if (mWipeExternalStorage) {
StorageManager sm = (StorageManager) mContext.getSystemService(
Context.STORAGE_SERVICE);
sm.wipeAdoptableDisks();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
mProgressDialog.dismiss();
mChainedTask.start();
}
}
}
9、frameworks/base/core/java/android/os/RecoverySystem.java
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() {
@Override
public void onReceive(Context context, Intent intent) {
condition.open();
}
}, null, 0, null, null);
// Block until the ordered broadcast has completed.
condition.block();
wipeEuiccData(context, wipeEuicc);
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);
}
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?)");
}