Settings中“清除資料”流程
1、具體觸發類:
src/com/android/settings/applications/AppStorageSettings.java
2、具體按鈕:
mClearDataButton = (Button) ((LayoutPreference) findPreference(KEY_CLEAR_DATA))
.findViewById(R.id.button);
3、具體回撥:
@Override
public void onClick(View v) {
。。。
else if (v == mClearDataButton) {
if (mAppsControlDisallowedAdmin != null && !mAppsControlDisallowedBySystem) {
RestrictedLockUtils.sendShowAdminSupportDetailsIntent(
getActivity(), mAppsControlDisallowedAdmin);
} else if (mAppEntry.info.manageSpaceActivityName != null) {
if (!Utils.isMonkeyRunning()) {
Intent intent = new Intent(Intent.ACTION_DEFAULT);
intent.setClassName(mAppEntry.info.packageName,
mAppEntry.info.manageSpaceActivityName);
startActivityForResult(intent, REQUEST_MANAGE_SPACE);
}
} else {
showDialogInner(DLG_CLEAR_DATA, 0);
}
}
。。。
4、彈出dialog:
showDialogInner(DLG_CLEAR_DATA, 0);
5、彈dialog方法:
@Override
protected AlertDialog createDialog(int id, int errorCode) {
switch (id) {
case DLG_CLEAR_DATA:
return new AlertDialog.Builder(getActivity())
.setTitle(getActivity().getText(R.string.clear_data_dlg_title))
.setMessage(getActivity().getText(R.string.clear_data_dlg_text))
.setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Clear user data here
initiateClearUserData();
}
})
.setNegativeButton(R.string.dlg_cancel, null)
.create();
6、具體清除方法:
private void initiateClearUserData() {
mClearDataButton.setEnabled(false);
// Invoke uninstall or clear user data based on sysPackage
String packageName = mAppEntry.info.packageName;
Log.i(TAG, "Clearing user data for package : " + packageName);
if (mClearDataObserver == null) {
mClearDataObserver = new ClearUserDataObserver();
}
ActivityManager am = (ActivityManager)
getActivity().getSystemService(Context.ACTIVITY_SERVICE);
boolean res = am.clearApplicationUserData(packageName, mClearDataObserver);
if (!res) {
// Clearing data failed for some obscure reason. Just log error for now
Log.i(TAG, "Couldnt clear application user data for package:"+packageName);
showDialogInner(DLG_CANNOT_CLEAR_DATA, 0);
} else {
mClearDataButton.setText(R.string.recompute_size);
}
}
7、呼叫ActivityManager clearApplicationUserData方法時傳了個mClearDataObserver,該Observer會在清除完成後發一個msg給handler,handler裡會呼叫 processClearMsg
private void processClearMsg(Message msg) {
int result = msg.arg1;
String packageName = mAppEntry.info.packageName;
mClearDataButton.setText(R.string.clear_user_data_text);
if (result == OP_SUCCESSFUL) {
Log.i(TAG, "Cleared user data for package : "+packageName);
mState.requestSize(mPackageName, mUserId);
/// M ALPS00235193: send the clear success broadcast { @
Intent packageDataCleared = new Intent(Intent.ACTION_SETTINGS_PACKAGE_DATA_CLEARED);
packageDataCleared.putExtra("packageName", packageName);
getActivity().sendBroadcast(packageDataCleared);
/// @ }
} else {
mClearDataButton.setEnabled(true);
}
}
清除ok,傳送一個廣播,先不管。。。
8、跟蹤到framework ams中:
am.clearApplicationUserData(packageName, mClearDataObserver);
方法具體行數如下:
6026 public boolean clearApplicationUserData(final String packageName,
6027 final IPackageDataObserver observer, int userId) {
enforceNotIsolatedCaller("clearApplicationUserData");
int uid = Binder.getCallingUid();
int pid = Binder.getCallingPid();
userId = mUserController.handleIncomingUser(pid, uid, userId, false,
ALLOW_FULL_ONLY, "clearApplicationUserData", null);
android.util.Log.d("jackpeng","clear pkg is "+packageName+"----uid is "+uid+"---pid is "+pid);
long callingId = Binder.clearCallingIdentity();
try {
IPackageManager pm = AppGlobals.getPackageManager();
int pkgUid = -1;
synchronized(this) {
if (getPackageManagerInternalLocked().canPackageBeWiped(
userId, packageName)) {
android.util.Log.d("jackpeng","throw exception");
throw new SecurityException(
"Cannot clear data for a device owner or a profile owner");
}
try {
pkgUid = pm.getPackageUid(packageName, MATCH_UNINSTALLED_PACKAGES, userId);
} catch (RemoteException e) {
}
if (pkgUid == -1) {
Slog.w(TAG, "Invalid packageName: " + packageName);
if (observer != null) {
try {
observer.onRemoveCompleted(packageName, false);
} catch (RemoteException e) {
Slog.i(TAG, "Observer no longer exists.");
}
}
return false;
}
if (uid == pkgUid || checkComponentPermission(
android.Manifest.permission.CLEAR_APP_USER_DATA,
pid, uid, -1, true)
== PackageManager.PERMISSION_GRANTED) {
android.util.Log.d("jackpeng","permission is granted and uid is matched ");
forceStopPackageLocked(packageName, pkgUid, "clear data");
} else {
throw new SecurityException("PID " + pid + " does not have permission "
+ android.Manifest.permission.CLEAR_APP_USER_DATA + " to clear data"
+ " of package " + packageName);
}
// Remove all tasks match the cleared application package and user
for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
final TaskRecord tr = mRecentTasks.get(i);
final String taskPackageName =
tr.getBaseIntent().getComponent().getPackageName();
if (tr.userId != userId) continue;
if (!taskPackageName.equals(packageName)) continue;
removeTaskByIdLocked(tr.taskId, false, REMOVE_FROM_RECENTS);
}
}
final int pkgUidF = pkgUid;
final int userIdF = userId;
final IPackageDataObserver localObserver = new IPackageDataObserver.Stub() {
@Override
public void onRemoveCompleted(String packageName, boolean succeeded)
throws RemoteException {
synchronized (ActivityManagerService.this) {
finishForceStopPackageLocked(packageName, pkgUidF);
}
final Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
Uri.fromParts("package", packageName, null));
intent.putExtra(Intent.EXTRA_UID, pkgUidF);
intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(pkgUidF));
broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
null, null, 0, null, null, null, null, false, false, userIdF);
if (observer != null) {
observer.onRemoveCompleted(packageName, succeeded);
}
}
};
try {
// Clear application user data
pm.clearApplicationUserData(packageName, localObserver, userId);
synchronized(this) {
// Remove all permissions granted from/to this package
android.util.Log.d("jackpeng","remove permiison start ");
removeUriPermissionsForPackageLocked(packageName, userId, true);
}
// Remove all zen rules created by this package; revoke it's zen access.
INotificationManager inm = NotificationManager.getService();
inm.removeAutomaticZenRules(packageName);
inm.setNotificationPolicyAccessGranted(packageName, false);
} catch (RemoteException e) {
}
} finally {
Binder.restoreCallingIdentity(callingId);
}
return true;
}