当前位置:网站首页>app clear data源码追踪
app clear data源码追踪
2022-07-06 23:23:00 【菜鸟xiaowang】
1.入口 setting
packages\apps\TvSettings\Settings\src\com\android\tv\settings\device\apps\ClearDataPreference.java
@Override
public void onOk() {
final AppManagementFragment fragment =
(AppManagementFragment) getTargetFragment();
fragment.clearData();
}
2.进入 AppManagementFragment
packages\apps\TvSettings\Settings\src\com\android\tv\settings\device\apps\AppManagementFragment.java
public void clearData() {
if (!clearDataAllowed()) {
Log.e(TAG, "Attempt to clear data failed. Clear data is disabled for " + mPackageName);
return;
}
mClearDataPreference.setClearingData(true);
String spaceManagementActivityName = mEntry.info.manageSpaceActivityName;
if (spaceManagementActivityName != null) {
if (!ActivityManager.isUserAMonkey()) {
Intent intent = new Intent(Intent.ACTION_DEFAULT);
intent.setClassName(mEntry.info.packageName, spaceManagementActivityName);
startActivityForResult(intent, REQUEST_MANAGE_SPACE);
}
} else {
// Disabling clear cache preference while clearing data is in progress. See b/77815256
// for details.
mClearCachePreference.setClearingCache(true);
ActivityManager am = (ActivityManager) getActivity().getSystemService(
Context.ACTIVITY_SERVICE);
boolean success = am.clearApplicationUserData(
mEntry.info.packageName, new IPackageDataObserver.Stub() {
public void onRemoveCompleted(
final String packageName, final boolean succeeded) {
mHandler.post(new Runnable() {
@Override
public void run() {
mClearDataPreference.setClearingData(false);
mClearCachePreference.setClearingCache(false);
if (succeeded) {
dataCleared(true);
} else {
dataCleared(false);
}
}
});
}
});
if (!success) {
mClearDataPreference.setClearingData(false);
dataCleared(false);
}
}
mClearDataPreference.refresh();
}
3.进入ActivityManager
frameworks\base\core\java\android\app\ActivityManager.java
@RequiresPermission(anyOf={Manifest.permission.CLEAR_APP_USER_DATA,
Manifest.permission.ACCESS_INSTANT_APPS})
@UnsupportedAppUsage
public boolean clearApplicationUserData(String packageName, IPackageDataObserver observer) {
try {
return getService().clearApplicationUserData(packageName, false,
observer, mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
@UnsupportedAppUsage
public static IActivityManager getService() {
return (IActivityManager)IActivityManagerSingleton.get();
}
4.进入 IActivityManager
frameworks\base\core\java\android\app\IActivityManager.aidl
boolean clearApplicationUserData(in String packageName, boolean keepState,
in IPackageDataObserver observer, int userId);
5.具体方法实现在AMS
frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
@Override
public boolean clearApplicationUserData(final String packageName, boolean keepState,
final IPackageDataObserver observer, int userId) {
enforceNotIsolatedCaller("clearApplicationUserData");
int uid = Binder.getCallingUid();
int pid = Binder.getCallingPid();
final int resolvedUserId = mUserController.handleIncomingUser(pid, uid, userId, false,
ALLOW_FULL_ONLY, "clearApplicationUserData", null);
final ApplicationInfo appInfo;
final boolean isInstantApp;
long callingId = Binder.clearCallingIdentity();
try {
IPackageManager pm = AppGlobals.getPackageManager();
synchronized(this) {
// Instant packages are not protected
if (getPackageManagerInternalLocked().isPackageDataProtected(
resolvedUserId, packageName)) {
throw new SecurityException(
"Cannot clear data for a protected package: " + packageName);
}
ApplicationInfo applicationInfo = null;
try {
applicationInfo = pm.getApplicationInfo(packageName,
MATCH_UNINSTALLED_PACKAGES, resolvedUserId);
} catch (RemoteException e) {
/* ignore */
}
appInfo = applicationInfo;
final boolean clearingOwnUidData = appInfo != null && appInfo.uid == uid;
if (!clearingOwnUidData && checkComponentPermission(permission.CLEAR_APP_USER_DATA,
pid, uid, -1, true) != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("PID " + pid + " does not have permission "
+ android.Manifest.permission.CLEAR_APP_USER_DATA + " to clear data"
+ " of package " + packageName);
}
final boolean hasInstantMetadata = getPackageManagerInternalLocked()
.hasInstantApplicationMetadata(packageName, resolvedUserId);
final boolean isUninstalledAppWithoutInstantMetadata =
(appInfo == null && !hasInstantMetadata);
isInstantApp = (appInfo != null && appInfo.isInstantApp())
|| hasInstantMetadata;
final boolean canAccessInstantApps = checkComponentPermission(
permission.ACCESS_INSTANT_APPS, pid, uid, -1, true)
== PackageManager.PERMISSION_GRANTED;
if (isUninstalledAppWithoutInstantMetadata || (isInstantApp
&& !canAccessInstantApps)) {
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 (appInfo != null) {
forceStopPackageLocked(packageName, appInfo.uid, "clear data");
mAtmInternal.removeRecentTasksByPackageName(packageName, resolvedUserId);
}
}
final IPackageDataObserver localObserver = new IPackageDataObserver.Stub() {
@Override
public void onRemoveCompleted(String packageName, boolean succeeded)
throws RemoteException {
if (appInfo != null) {
synchronized (ActivityManagerService.this) {
finishForceStopPackageLocked(packageName, appInfo.uid);
}
}
final Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
Uri.fromParts("package", packageName, null));
intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
intent.putExtra(Intent.EXTRA_UID, (appInfo != null) ? appInfo.uid : -1);
intent.putExtra(Intent.EXTRA_USER_HANDLE, resolvedUserId);
if (isInstantApp) {
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
broadcastIntentInPackage("android", null, SYSTEM_UID, uid, pid, intent,
null, null, 0, null, null, permission.ACCESS_INSTANT_APPS, null,
false, false, resolvedUserId, false);
} else {
broadcastIntentInPackage("android", null, SYSTEM_UID, uid, pid, intent,
null, null, 0, null, null, null, null, false, false, resolvedUserId,
false);
}
if (observer != null) {
observer.onRemoveCompleted(packageName, succeeded);
}
}
};
try {
// Clear application user data
pm.clearApplicationUserData(packageName, localObserver, resolvedUserId);
if (appInfo != null) {
// Restore already established notification state and permission grants,
// so it told us to keep those intact -- it's about to emplace app data
// that is appropriate for those bits of system state.
if (!keepState) {
// Remove all permissions granted from/to this package
mUgmInternal.removeUriPermissionsForPackage(packageName, resolvedUserId,
true, false);
// Reset notification state
INotificationManager inm = NotificationManager.getService();
inm.clearData(packageName, appInfo.uid, uid == appInfo.uid);
}
// Clear its scheduled jobs
JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class);
js.cancelJobsForUid(appInfo.uid, "clear data");
// Clear its pending alarms
AlarmManagerInternal ami = LocalServices.getService(AlarmManagerInternal.class);
ami.removeAlarmsForUid(appInfo.uid);
}
} catch (RemoteException e) {
}
} finally {
Binder.restoreCallingIdentity(callingId);
}
return true;
}
6.进入 IPackageManager
frameworks/base/core/java/android/content/pm/IPackageManager.aidl
void clearApplicationUserData(in String packageName, IPackageDataObserver observer, int userId);
7.具体实现在PMS
frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java
@Override
public void clearApplicationUserData(final String packageName,
final IPackageDataObserver observer, final int userId) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CLEAR_APP_USER_DATA, null);
final int callingUid = Binder.getCallingUid();
mPermissionManager.enforceCrossUserPermission(callingUid, userId,
true /* requireFullPermission */, false /* checkShell */, "clear application data");
final PackageSetting ps = mSettings.getPackageLPr(packageName);
final boolean filterApp =
(ps != null && shouldFilterApplicationLocked(ps, callingUid, userId));
if (!filterApp && mProtectedPackages.isPackageDataProtected(userId, packageName)) {
throw new SecurityException("Cannot clear data for a protected package: "
+ packageName);
}
// Queue up an async operation since the package deletion may take a little while.
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
final boolean succeeded;
if (!filterApp) {
try (PackageFreezer freezer = freezePackage(packageName,
"clearApplicationUserData")) {
synchronized (mInstallLock) {
succeeded = clearApplicationUserDataLIF(packageName, userId);
}
synchronized (mLock) {
mInstantAppRegistry.deleteInstantApplicationMetadataLPw(
packageName, userId);
}
}
if (succeeded) {
// invoke DeviceStorageMonitor's update method to clear any notifications
DeviceStorageMonitorInternal dsm = LocalServices
.getService(DeviceStorageMonitorInternal.class);
if (dsm != null) {
dsm.checkMemory();
}
if (checkPermission(Manifest.permission.SUSPEND_APPS, packageName, userId)
== PERMISSION_GRANTED) {
unsuspendForSuspendingPackage(packageName, userId);
removeAllDistractingPackageRestrictions(userId);
flushPackageRestrictionsAsUserInternalLocked(userId);
}
}
} else {
succeeded = false;
}
if (observer != null) {
try {
observer.onRemoveCompleted(packageName, succeeded);
} catch (RemoteException e) {
Log.i(TAG, "Observer no longer exists.");
}
} //end if observer
} //end run
});
}
private boolean clearApplicationUserDataLIF(String packageName, int userId) {
if (packageName == null) {
Slog.w(TAG, "Attempt to delete null packageName.");
return false;
}
// Try finding details about the requested package
AndroidPackage pkg;
PackageSetting ps;
synchronized (mLock) {
pkg = mPackages.get(packageName);
ps = mSettings.mPackages.get(packageName);
if (pkg == null) {
if (ps != null) {
pkg = ps.pkg;
}
}
}
if (pkg == null) {
Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
return false;
}
mPermissionManager.resetRuntimePermissions(pkg, userId);
clearAppDataLIF(pkg, userId,
FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL);
final int appId = UserHandle.getAppId(pkg.getUid());
removeKeystoreDataIfNeeded(mInjector.getUserManagerInternal(), userId, appId);
UserManagerInternal umInternal = mInjector.getUserManagerInternal();
final int flags;
if (umInternal.isUserUnlockingOrUnlocked(userId)) {
flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
} else if (umInternal.isUserRunning(userId)) {
flags = StorageManager.FLAG_STORAGE_DE;
} else {
flags = 0;
}
prepareAppDataContentsLIF(pkg, ps, userId, flags);
return true;
}
private void clearAppDataLIF(AndroidPackage pkg, int userId, int flags) {
if (pkg == null) {
Slog.wtf(TAG, "Package was null!", new Throwable());
return;
}
clearAppDataLeafLIF(pkg, userId, flags);
if ((flags & Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES) == 0) {
clearAppProfilesLIF(pkg, UserHandle.USER_ALL);
}
}
private void clearAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) {
final PackageSetting ps;
synchronized (mLock) {
ps = mSettings.mPackages.get(pkg.getPackageName());
}
for (int realUserId : resolveUserIds(userId)) {
final long ceDataInode = (ps != null) ? ps.getCeDataInode(realUserId) : 0;
try {
mInstaller.clearAppData(pkg.getVolumeUuid(), pkg.getPackageName(), realUserId,
flags, ceDataInode);
} catch (InstallerException e) {
Slog.w(TAG, String.valueOf(e));
}
}
}
8.进入 Installer
frameworks/base/services/core/java/com/android/server/pm/Installer.java
public void clearAppData(String uuid, String packageName, int userId, int flags,
long ceDataInode) throws InstallerException {
if (!checkBeforeRemote()) return;
try {
mInstalld.clearAppData(uuid, packageName, userId, flags, ceDataInode);
} catch (Exception e) {
throw InstallerException.from(e);
}
}
9.进入 IInstalld
frameworks/native/cmds/installd/binder/android/os/IInstalld.aidl
void clearAppData(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName, int userId, int flags, long ceDataInode);
10.具体清除动作在InstalldNativeService中定义
frameworks\native\cmds\installd\InstalldNativeService.cpp
binder::Status InstalldNativeService::clearAppData(const std::unique_ptr<std::string>& uuid,
const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(uuid);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
std::lock_guard<std::recursive_mutex> lock(mLock);
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
const char* pkgname = packageName.c_str();
binder::Status res = ok();
if (flags & FLAG_STORAGE_CE) {
auto path = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInode);
if (flags & FLAG_CLEAR_CACHE_ONLY) {
path = read_path_inode(path, "cache", kXattrInodeCache);
} else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
path = read_path_inode(path, "code_cache", kXattrInodeCodeCache);
}
if (access(path.c_str(), F_OK) == 0) {
if (delete_dir_contents(path) != 0) {
res = error("Failed to delete contents of " + path);
} else if ((flags & (FLAG_CLEAR_CACHE_ONLY | FLAG_CLEAR_CODE_CACHE_ONLY)) == 0) {
remove_path_xattr(path, kXattrInodeCache);
remove_path_xattr(path, kXattrInodeCodeCache);
}
}
}
if (flags & FLAG_STORAGE_DE) {
std::string suffix = "";
bool only_cache = false;
if (flags & FLAG_CLEAR_CACHE_ONLY) {
suffix = CACHE_DIR_POSTFIX;
only_cache = true;
} else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
suffix = CODE_CACHE_DIR_POSTFIX;
only_cache = true;
}
auto path = create_data_user_de_package_path(uuid_, userId, pkgname) + suffix;
if (access(path.c_str(), F_OK) == 0) {
if (delete_dir_contents(path) != 0) {
res = error("Failed to delete contents of " + path);
}
}
}
if (flags & FLAG_STORAGE_EXTERNAL) {
std::lock_guard<std::recursive_mutex> lock(mMountsLock);
for (const auto& n : mStorageMounts) {
auto extPath = n.second;
if (android::base::GetBoolProperty(kFuseProp, false)) {
std::regex re("^\\/mnt\\/pass_through\\/[0-9]+\\/emulated");
if (std::regex_match(extPath, re)) {
extPath += "/" + std::to_string(userId);
}
} else {
if (n.first.compare(0, 14, "/mnt/media_rw/") != 0) {
extPath += StringPrintf("/%d", userId);
} else if (userId != 0) {
// TODO: support devices mounted under secondary users
continue;
}
}
if (flags & FLAG_CLEAR_CACHE_ONLY) {
// Clear only cached data from shared storage
auto path = StringPrintf("%s/Android/data/%s/cache", extPath.c_str(), pkgname);
if (delete_dir_contents(path, true) != 0) {
res = error("Failed to delete contents of " + path);
}
} else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
// No code cache on shared storage
} else {
// Clear everything on shared storage
auto path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname);
if (delete_dir_contents(path, true) != 0) {
res = error("Failed to delete contents of " + path);
}
path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname);
if (delete_dir_contents(path, true) != 0) {
res = error("Failed to delete contents of " + path);
}
// Note that we explicitly don't delete OBBs - those are only removed on
// app uninstall.
}
}
}
return res;
}
边栏推荐
- 接口间调用为什么要用json、fastjson怎么赋值的、fastjson [email protected]映射关系问题
- 最长不下降子序列(LIS)(动态规划)
- QT simple layout box model with spring
- Techniques d'utilisation de sublime
- [opencv] image morphological operation opencv marks the positions of different connected domains
- Sublime tips
- 数字化如何影响工作流程自动化
- Knapsack problem unrelated to profit (depth first search)
- Safe landing practice of software supply chain under salesforce containerized ISV scenario
- 3.基金的类型
猜你喜欢
批量归一化(标准化)处理
CentOS 7.9安装Oracle 21c历险记
pmp真的有用吗?
No experts! Growth secrets for junior and intermediate programmers and "quasi programmers" who are still practicing in Universities
Longest palindrome substring (dynamic programming)
Weebly移动端网站编辑器 手机浏览新时代
一个酷酷的“幽灵”控制台工具
《四》表单
Weebly mobile website editor mobile browsing New Era
Y58. Chapter III kubernetes from entry to proficiency - continuous integration and deployment (Sany)
随机推荐
Leetcode(46)——全排列
Longest non descent subsequence (LIS) (dynamic programming)
CentOS 7.9安装Oracle 21c历险记
Linkedblockingqueue source code analysis - initialization
Dbsync adds support for mongodb and ES
HarmonyOS第四次培训
Using thread class and runnable interface to realize the difference between multithreading
[PHP SPL notes]
Wonderful express | Tencent cloud database June issue
【问道】编译原理
3.基金的类型
2.证券投资基金的概述
漏电继电器JELR-250FG
接口间调用为什么要用json、fastjson怎么赋值的、fastjson [email protected]映射关系问题
做自媒体,有哪些免费下载视频剪辑素材的网站?
局部变量的数组初始化问题
2039: [Bluebridge cup 2022 preliminaries] Li Bai's enhanced version (dynamic planning)
No experts! Growth secrets for junior and intermediate programmers and "quasi programmers" who are still practicing in Universities
第一篇论文的写作流程
Ansible overview and module explanation (you just passed today, but yesterday came to your face)