从PMS的内部结构上删除acitivity、service、provider等信息
删除code、library和resource等信息
调用installd删除/data/data/packageName以及/data/dalvik-cache下面的文件
更新Settings中的package信息
具体分析
当我们在Settings中的应用页面找到一个安装了的应用程序,并点击卸载后,就会发送一个Intent给UninstallerActivity,在UninstallerActivity最后会启动UninstallAppProgress的initView方法,并调用如下卸载函数:
getPackageManager().deletePackage(mAppInfo.packageName, observer,
mAllUsers ? PackageManager.DELETE_ALL_USERS : 0);
上面的mAllUsers默认是false。getPackageManager()函数的实现在ContextImpl.java,它最后会调用到ApplicantPackageManger.java的deletePackage方法:
public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
try {
mPM.deletePackageAsUser(packageName, observer, UserHandle.myUserId(), flags);
} catch (RemoteException e) {
// Should never happen!
}
}
通过Binder调用,我们来看PMS中的deletePackageAsUser方法和installPackageAsUser对应
@Override
public void deletePackageAsUser(String packageName, int versionCode,
IPackageDeleteObserver observer, int userId, int flags) {
deletePackageVersioned(new VersionedPackage(packageName, versionCode),
new LegacyPackageDeleteObserver(observer).getBinder(), userId, flags);
}
@Override
public void deletePackageVersioned(VersionedPackage versionedPackage,
final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) {
final int callingUid = Binder.getCallingUid();
//权限检查
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DELETE_PACKAGES, null);
final boolean canViewInstantApps = canViewInstantApps(callingUid, userId);
Preconditions.checkNotNull(versionedPackage);
Preconditions.checkNotNull(observer);
Preconditions.checkArgumentInRange(versionedPackage.getVersionCode(),
PackageManager.VERSION_CODE_HIGHEST,
Integer.MAX_VALUE, "versionCode must be >= -1");
final String packageName = versionedPackage.getPackageName();
final int versionCode = versionedPackage.getVersionCode();
final String internalPackageName;
synchronized (mPackages) {
// 规范化包名以处理重命名的包和静态库
internalPackageName = resolveInternalPackageNameLPr(versionedPackage.getPackageName(),
versionedPackage.getVersionCode());
}
final int uid = Binder.getCallingUid();
if (!isOrphaned(internalPackageName)
&& !isCallerAllowedToSilentlyUninstall(uid, internalPackageName)) {
try {
final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
intent.setData(Uri.fromParts(PACKAGE_SCHEME, packageName, null));
intent.putExtra(PackageInstaller.EXTRA_CALLBACK, observer.asBinder());
observer.onUserActionRequired(intent);
} catch (RemoteException re) {
}
return;
}
final boolean deleteAllUsers = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0;
final int[] users = deleteAllUsers ? sUserManager.getUserIds() : new int[]{ userId };
if (UserHandle.getUserId(uid) != userId || (deleteAllUsers && users.length > 1)) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
"deletePackage for user " + userId);
}
// 将异步操作排队,因为删除包可能需要一段时间。
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
int returnCode;
final PackageSetting ps = mSettings.mPackages.get(internalPackageName);
boolean doDeletePackage = true;
if (ps != null) {
final boolean targetIsInstantApp =
ps.getInstantApp(UserHandle.getUserId(callingUid));
doDeletePackage = !targetIsInstantApp
|| canViewInstantApps;
}
if (doDeletePackage) {
if (!deleteAllUsers) {
returnCode = deletePackageX(internalPackageName, versionCode,
userId, deleteFlags);
} else {
int[] blockUninstallUserIds = getBlockUninstallForUsers(
internalPackageName, users);
// 如果没有人阻止卸载,继续删除所有用户
if (ArrayUtils.isEmpty(blockUninstallUserIds)) {
returnCode = deletePackageX(internalPackageName, versionCode,
userId, deleteFlags);
} else {
// Otherwise uninstall individually for users with blockUninstalls=false
final int userFlags = deleteFlags & ~PackageManager.DELETE_ALL_USERS;
for (int userId : users) {
if (!ArrayUtils.contains(blockUninstallUserIds, userId)) {
returnCode = deletePackageX(internalPackageName, versionCode,
userId, userFlags);
}
}
// 该应用程序只针对特定用户被标记为“卸载”。我们仍然需要报告删除被阻止
returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED;
}
}
} else {
returnCode = PackageManager.DELETE_FAILED_INTERNAL_ERROR;
}
try {
observer.onPackageDeleted(packageName, returnCode, null);
} catch (RemoteException e) {
Log.i(TAG, "Observer no longer exists.");
} //end catch
} //end run
});
}
在deletePackageAsUser方法中,首先做权限检查,然后就调用deletePackageX方法去执行卸载任务:
public int deletePackageX(String packageName, int versionCode, int userId, int deleteFlags) {
final PackageRemovedInfo info = new PackageRemovedInfo(this);
final boolean res;
final int removeUser = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0
? UserHandle.USER_ALL : userId;
if (isPackageDeviceAdmin(packageName, removeUser)) {
Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
}
PackageSetting uninstalledPs = null;
PackageParser.Package pkg = null;
// for the uninstall-updates case and restricted profiles, remember the per-
// user handle installed state
int[] allUsers;
synchronized (mPackages) {
uninstalledPs = mSettings.mPackages.get(packageName);
if (uninstalledPs == null) {
Slog.w(TAG, "Not removing non-existent package " + packageName);
return PackageManager.DELETE_FAILED_INTERNAL_ERROR;
}
if (versionCode != PackageManager.VERSION_CODE_HIGHEST
&& uninstalledPs.versionCode != versionCode) {
Slog.w(TAG, "Not removing package " + packageName + " with versionCode "
+ uninstalledPs.versionCode + " != " + versionCode);
return PackageManager.DELETE_FAILED_INTERNAL_ERROR;
}
// Static shared libs can be declared by any package, so let us not
// allow removing a package if it provides a lib others depend on.
pkg = mPackages.get(packageName);
allUsers = sUserManager.getUserIds();
if (pkg != null && pkg.staticSharedLibName != null) {
SharedLibraryEntry libEntry = getSharedLibraryEntryLPr(pkg.staticSharedLibName,
pkg.staticSharedLibVersion);
if (libEntry != null) {
for (int currUserId : allUsers) {
if (removeUser != UserHandle.USER_ALL && removeUser != currUserId) {
continue;
}
List libClientPackages = getPackagesUsingSharedLibraryLPr(
libEntry.info, 0, currUserId);
if (!ArrayUtils.isEmpty(libClientPackages)) {
return PackageManager.DELETE_FAILED_USED_SHARED_LIBRARY;
}
}
}
}
info.origUsers = uninstalledPs.queryInstalledUsers(allUsers, true);
}
final int freezeUser;
if (isUpdatedSystemApp(uninstalledPs)
&& ((deleteFlags & PackageManager.DELETE_SYSTEM_APP) == 0)) {
// 我们正在降级一个系统应用程序,它将适用于所有用户,所以在降级期间冻结他们
freezeUser = UserHandle.USER_ALL;
} else {
freezeUser = removeUser;
}
synchronized (mInstallLock) {
//冻结package
try (PackageFreezer freezer = freezePackageForDelete(packageName, freezeUser,
deleteFlags, "deletePackageX")) {
//调用删除的函数
res = deletePackageLIF(packageName, UserHandle.of(removeUser), true, allUsers,
deleteFlags | FLAGS_REMOVE_CHATTY, info, true, null);
}
synchronized (mPackages) {
if (res) {
if (pkg != null) {
mInstantAppRegistry.onPackageUninstalledLPw(pkg, info.removedUsers);
}
updateSequenceNumberLP(uninstalledPs, info.removedUsers);
updateInstantAppInstallerLocked(packageName);
}
}
}
if (res) {
final boolean killApp = (deleteFlags & PackageManager.DELETE_DONT_KILL_APP) == 0;
info.sendPackageRemovedBroadcasts(killApp);
info.sendSystemPackageUpdatedBroadcasts();
info.sendSystemPackageAppearedBroadcasts();
}
// Force a gc here.
Runtime.getRuntime().gc();
// 在发送广播之后删除这里的资源,让其他进程在删除资源之前清理。
if (info.args != null) {
synchronized (mInstallLock) {
info.args.doPostDeleteLI(true);
}
}
return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;
}
deletePackageX在这里我们只考虑当前只有一个user的情况,来看deletePackageLIF的实现,这个方法通常处理包的删除
private boolean deletePackageLIF(String packageName, UserHandle user,
boolean deleteCodeAndResources, int[] allUserHandles, int flags,
PackageRemovedInfo outInfo, boolean writeSettings,
PackageParser.Package replacingPackage) {
if (packageName == null) {
Slog.w(TAG, "Attempt to delete null packageName.");
return false;
}
PackageSetting ps;
synchronized (mPackages) {
ps = mSettings.mPackages.get(packageName);
if (ps == null) {
Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
return false;
}
if (ps.parentPackageName != null && (!isSystemApp(ps)
|| (flags & PackageManager.DELETE_SYSTEM_APP) != 0)) {
final int removedUserId = (user != null) ? user.getIdentifier()
: UserHandle.USER_ALL;
if (!clearPackageStateForUserLIF(ps, removedUserId, outInfo)) {
return false;
}
markPackageUninstalledForUserLPw(ps, user);
scheduleWritePackageRestrictionsLocked(user);
return true;
}
}
if (((!isSystemApp(ps) || (flags&PackageManager.DELETE_SYSTEM_APP) != 0) && user != null
&& user.getIdentifier() != UserHandle.USER_ALL)) {
// The caller is asking that the package only be deleted for a single
// user. To do this, we just mark its uninstalled state and delete
// its data. If this is a system app, we only allow this to happen if
// they have set the special DELETE_SYSTEM_APP which requests different
// semantics than normal for uninstalling system apps.
markPackageUninstalledForUserLPw(ps, user);
if (!isSystemApp(ps)) {
// Do not uninstall the APK if an app should be cached
boolean keepUninstalledPackage = shouldKeepUninstalledPackageLPr(packageName);
if (ps.isAnyInstalled(sUserManager.getUserIds()) || keepUninstalledPackage) {
// 其他用户仍然安装了这个包,所以我们需要做的就是清除该用户的数据并保存它已卸载。
if (!clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo)) {
return false;
}
scheduleWritePackageRestrictionsLocked(user);
return true;
} else {
//未被其他用户安装,完全删除
ps.setInstalled(true, user.getIdentifier());
mSettings.writeKernelMappingLPr(ps);
}
} else {
// 这是一个系统应用程序,因此我们假设其他用户仍然安装了这个包,因此我们需要做的就是清除该用户的数据并保存它已卸载。
if (DEBUG_REMOVE) Slog.d(TAG, "Deleting system app");
if (!clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo)) {
return false;
}
scheduleWritePackageRestrictionsLocked(user);
return true;
}
}
// 如果我们要为所有用户删除一个复合包,请跟踪每个子组件的结果。
if (ps.childPackageNames != null && outInfo != null) {
synchronized (mPackages) {
final int childCount = ps.childPackageNames.size();
outInfo.removedChildPackages = new ArrayMap<>(childCount);
for (int i = 0; i < childCount; i++) {
String childPackageName = ps.childPackageNames.get(i);
PackageRemovedInfo childInfo = new PackageRemovedInfo(this);
childInfo.removedPackage = childPackageName;
childInfo.installerPackageName = ps.installerPackageName;
outInfo.removedChildPackages.put(childPackageName, childInfo);
PackageSetting childPs = mSettings.getPackageLPr(childPackageName);
if (childPs != null) {
childInfo.origUsers = childPs.queryInstalledUsers(allUserHandles, true);
}
}
}
}
boolean ret = false;
if (isSystemApp(ps)) {
//删除系统应用
if (DEBUG_REMOVE) Slog.d(TAG, "Removing system package: " + ps.name);
// 当更新的系统应用程序被删除时,我们也会删除现有的资源,并返回到系统分区中的现有代码
ret = deleteSystemPackageLIF(ps.pkg, ps, allUserHandles, flags, outInfo, writeSettings);
} else {
//删除非系统应用
if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package: " + ps.name);
ret = deleteInstalledPackageLIF(ps, deleteCodeAndResources, flags, allUserHandles,
outInfo, writeSettings, replacingPackage);
}
// 注意我们是否删除了所有用户的包
if (outInfo != null) {
outInfo.removedForAllUsers = mPackages.get(ps.name) == null;
if (outInfo.removedChildPackages != null) {
synchronized (mPackages) {
final int childCount = outInfo.removedChildPackages.size();
for (int i = 0; i < childCount; i++) {
PackageRemovedInfo childInfo = outInfo.removedChildPackages.valueAt(i);
if (childInfo != null) {
childInfo.removedForAllUsers = mPackages.get(
childInfo.removedPackage) == null;
}
}
}
}
// 如果我们卸载系统应用程序的更新,可能会出现一些子包,它们在系统应用程序中声明,但没有在更新中声明。
if (isSystemApp(ps)) {
synchronized (mPackages) {
PackageSetting updatedPs = mSettings.getPackageLPr(ps.name);
final int childCount = (updatedPs.childPackageNames != null)
? updatedPs.childPackageNames.size() : 0;
for (int i = 0; i < childCount; i++) {
String childPackageName = updatedPs.childPackageNames.get(i);
if (outInfo.removedChildPackages == null
|| outInfo.removedChildPackages.indexOfKey(childPackageName) < 0) {
PackageSetting childPs = mSettings.getPackageLPr(childPackageName);
if (childPs == null) {
continue;
}
PackageInstalledInfo installRes = new PackageInstalledInfo();
installRes.name = childPackageName;
installRes.newUsers = childPs.queryInstalledUsers(allUserHandles, true);
installRes.pkg = mPackages.get(childPackageName);
installRes.uid = childPs.pkg.applicationInfo.uid;
if (outInfo.appearedChildPackages == null) {
outInfo.appearedChildPackages = new ArrayMap<>();
}
outInfo.appearedChildPackages.put(childPackageName, installRes);
}
}
}
}
}
return ret;
}
在deletePackageLIF函数中根据是否是systemApp调用不同的流程,如果是systemApp,则调用deleteSystemPackageLIF完成卸载;如果非systemApp,则调用deleteInstalledPackageLIF完成卸载,当然在卸载之前,首先会调用AMS的killApplication方法先让这个APP停止运行。我们主要介绍非systemApp的卸载过程,来看deleteInstalledPackageLIF方法的实现:
private boolean deleteInstalledPackageLIF(PackageSetting ps,
boolean deleteCodeAndResources, int flags, int[] allUserHandles,
PackageRemovedInfo outInfo, boolean writeSettings,
PackageParser.Package replacingPackage) {
synchronized (mPackages) {
if (outInfo != null) {
outInfo.uid = ps.appId;
}
if (outInfo != null && outInfo.removedChildPackages != null) {
final int childCount = (ps.childPackageNames != null)
? ps.childPackageNames.size() : 0;
for (int i = 0; i < childCount; i++) {
String childPackageName = ps.childPackageNames.get(i);
PackageSetting childPs = mSettings.mPackages.get(childPackageName);
if (childPs == null) {
return false;
}
PackageRemovedInfo childInfo = outInfo.removedChildPackages.get(
childPackageName);
if (childInfo != null) {
childInfo.uid = childPs.appId;
}
}
}
}
// 从内部结构中删除包数据,并删除设置了标记的数据
removePackageDataLIF(ps, allUserHandles, outInfo, flags, writeSettings);
// 删除子包数据
final int childCount = (ps.childPackageNames != null) ? ps.childPackageNames.size() : 0;
for (int i = 0; i < childCount; i++) {
PackageSetting childPs;
synchronized (mPackages) {
childPs = mSettings.getPackageLPr(ps.childPackageNames.get(i));
}
if (childPs != null) {
PackageRemovedInfo childOutInfo = (outInfo != null
&& outInfo.removedChildPackages != null)
? outInfo.removedChildPackages.get(childPs.name) : null;
final int deleteFlags = (flags & DELETE_KEEP_DATA) != 0
&& (replacingPackage != null
&& !replacingPackage.hasChildPackage(childPs.name))
? flags & ~DELETE_KEEP_DATA : flags;
removePackageDataLIF(childPs, allUserHandles, childOutInfo,
deleteFlags, writeSettings);
}
}
// 仅为父包删除应用程序代码和资源
if (ps.parentPackageName == null) {
if (deleteCodeAndResources && (outInfo != null)) {
outInfo.args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));
if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.args);
}
}
return true;
}
在deleteInstalledPackageLIF方法中,分为两步去卸载应用:第一步删除/data/data下面的数据目录,并从PMS的内部数据结构上清除当前卸载的package信息;第二步就deleteCodeAndResources删除code和resource文件。我们先来看第一步removePackageDataLIF:
private void removePackageDataLIF(PackageSetting ps, int[] allUserHandles,
PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
String packageName = ps.name;
if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + ps);
// 检索对象以稍后删除共享用户的权限
final PackageParser.Package deletedPkg;
final PackageSetting deletedPs;
// reader
synchronized (mPackages) {
deletedPkg = mPackages.get(packageName);
deletedPs = mSettings.mPackages.get(packageName);
if (outInfo != null) {
outInfo.removedPackage = packageName;
outInfo.installerPackageName = ps.installerPackageName;
outInfo.isStaticSharedLib = deletedPkg != null
&& deletedPkg.staticSharedLibName != null;
outInfo.populateUsers(deletedPs == null ? null
: deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true), deletedPs);
}
}
//删除数据
removePackageLI(ps, (flags & FLAGS_REMOVE_CHATTY) != 0);
if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) {
final PackageParser.Package resolvedPkg;
if (deletedPkg != null) {
resolvedPkg = deletedPkg;
} else {
// We don't have a parsed package when it lives on an ejected
// adopted storage device, so fake something together
resolvedPkg = new PackageParser.Package(ps.name);
resolvedPkg.setVolumeUuid(ps.volumeUuid);
}
//删除目录和配置文件
destroyAppDataLIF(resolvedPkg, UserHandle.USER_ALL,
StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
destroyAppProfilesLIF(resolvedPkg, UserHandle.USER_ALL);
if (outInfo != null) {
outInfo.dataRemoved = true;
}
schedulePackageCleaning(packageName, UserHandle.USER_ALL, true);
}
int removedAppId = -1;
// writer
synchronized (mPackages) {
boolean installedStateChanged = false;
if (deletedPs != null) {
if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL);
clearDefaultBrowserIfNeeded(packageName);
mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName);
removedAppId = mSettings.removePackageLPw(packageName);
if (outInfo != null) {
outInfo.removedAppId = removedAppId;
}
//更新设置
updatePermissionsLPw(deletedPs.name, null, 0);
if (deletedPs.sharedUser != null) {
//删除与包关联的权限。由于运行时权限是按用户分配的,
//所以如果撤销仅由已删除的包请求的权限成功且这将导致gids的更改,
//则必须终止已删除的包或在已删除包的共享用户下运行的包。
for (int userId : UserManagerService.getInstance().getUserIds()) {
final int userIdToKill = mSettings.updateSharedUserPermsLPw(deletedPs,
userId);
if (userIdToKill == UserHandle.USER_ALL
|| userIdToKill >= UserHandle.USER_SYSTEM) {
// 如果为这个用户更改了gid,则杀死所有受影响的包。
mHandler.post(new Runnable() {
@Override
public void run() {
// 这必须在没有持有锁的情况下发生。
killApplication(deletedPs.name, deletedPs.appId,
KILL_APP_REASON_GIDS_CHANGED);
}
});
break;
}
}
}
clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL);
}
// 如果删除只是将系统应用程序降级到工厂包,请确保保留每个用户禁用状态
if (allUserHandles != null && outInfo != null && outInfo.origUsers != null) {
if (DEBUG_REMOVE) {
Slog.d(TAG, "Propagating install state across downgrade");
}
for (int userId : allUserHandles) {
final boolean installed = ArrayUtils.contains(outInfo.origUsers, userId);
if (DEBUG_REMOVE) {
Slog.d(TAG, " user " + userId + " => " + installed);
}
if (installed != ps.getInstalled(userId)) {
installedStateChanged = true;
}
ps.setInstalled(installed, userId);
}
}
}
// can downgrade to reader
if (writeSettings) {
// 现在保存设置
mSettings.writeLPr();
}
if (installedStateChanged) {
mSettings.writeKernelMappingLPr(ps);
}
}
if (removedAppId != -1) {
// A user ID was deleted here. Go through all users and remove it
// from KeyStore.
removeKeystoreDataIfNeeded(UserHandle.USER_ALL, removedAppId);
}
}
removePackageDataLIF用于删除应用的/data/data数据目录,并且从PMS内部数据结构里面清除package的信息。首先调用removePackageLI从PMS内部的数据结构上删除要卸载的package信息:
void removePackageLI(PackageSetting ps, boolean chatty) {
// writer
synchronized (mPackages) {
mPackages.remove(ps.name);
final PackageParser.Package pkg = ps.pkg;
if (pkg != null) {
cleanPackageDataStructuresLILPw(pkg, chatty);
}
}
}
cleanPackageDataStructuresLILPw用于将package的providers、services、receivers、activities等信息去PMS的全局数据结构上移除,这部分代码比较简单。接下来调用destroyAppDataLIF和destroyAppProfilesLIF去删除/data/data下面的目录
destroyAppDataLIF主要顺序
private void destroyAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) {
final PackageSetting ps;
synchronized (mPackages) {
ps = mSettings.mPackages.get(pkg.packageName);
}
for (int realUserId : resolveUserIds(userId)) {
final long ceDataInode = (ps != null) ? ps.getCeDataInode(realUserId) : 0;
try {
mInstaller.destroyAppData(pkg.volumeUuid, pkg.packageName, realUserId, flags,
ceDataInode);
} catch (InstallerException e) {
Slog.w(TAG, String.valueOf(e));
}
mDexManager.notifyPackageDataDestroyed(pkg.packageName, userId);
}
}
跨进程调用InstalldNativeService的destroyAppData方法
binder::Status InstalldNativeService::destroyAppData(const std::unique_ptr& 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 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 (delete_dir_contents_and_dir(path) != 0) {
res = error("Failed to delete " + path);
}
}
if (flags & FLAG_STORAGE_DE) {
auto path = create_data_user_de_package_path(uuid_, userId, pkgname);
if (delete_dir_contents_and_dir(path) != 0) {
res = error("Failed to delete " + path);
}
destroy_app_current_profiles(packageName, userId);
// TODO(calin): If the package is still installed by other users it's probably
// beneficial to keep the reference profile around.
// Verify if it's ok to do that.
destroy_app_reference_profile(packageName);
}
return res;
}
create_data_user_ce_package_path方法构造/data/data/packageName的文件路径名,然后调用delete_dir_contents_and_dir来删除文件内容以及目录,前面介绍过,/data/data/packageName的文件其实都是符号链接,所以delete_dir_contents_and_dir的实现中都是调用unlinkat去删除这些符号链接
回到removePackageDataLIF中,接着调用schedulePackageCleaning来安排清理动作:
void schedulePackageCleaning(String packageName, int userId, boolean andCode) {
final Message msg = mHandler.obtainMessage(START_CLEANING_PACKAGE,
userId, andCode ? 1 : 0, packageName);
if (mSystemReady) {
msg.sendToTarget();
} else {
if (mPostSystemReadyMessages == null) {
mPostSystemReadyMessages = new ArrayList<>();
}
mPostSystemReadyMessages.add(msg);
}
}
这里向PackageHandler发送START_CLEANING_PACKAGE消息,会调用mSettings.addPackageToCleanLPw。接着来看removePackageDataLIF方法:
synchronized (mPackages) {
boolean installedStateChanged = false;
if (deletedPs != null) {
if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL);
clearDefaultBrowserIfNeeded(packageName);
mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName);
removedAppId = mSettings.removePackageLPw(packageName);
if (outInfo != null) {
outInfo.removedAppId = removedAppId;
}
updatePermissionsLPw(deletedPs.name, null, 0);
if (deletedPs.sharedUser != null) {
for (int userId : UserManagerService.getInstance().getUserIds()) {
final int userIdToKill = mSettings.updateSharedUserPermsLPw(deletedPs,
userId);
if (userIdToKill == UserHandle.USER_ALL
|| userIdToKill >= UserHandle.USER_SYSTEM) {
// If gids changed for this user, kill all affected packages.
mHandler.post(new Runnable() {
@Override
public void run() {
// This has to happen with no lock held.
killApplication(deletedPs.name, deletedPs.appId,
KILL_APP_REASON_GIDS_CHANGED);
}
});
break;
}
}
}
clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL);
}
if (allUserHandles != null && outInfo != null && outInfo.origUsers != null) {
if (DEBUG_REMOVE) {
Slog.d(TAG, "Propagating install state across downgrade");
}
for (int userId : allUserHandles) {
final boolean installed = ArrayUtils.contains(outInfo.origUsers, userId);
if (DEBUG_REMOVE) {
Slog.d(TAG, " user " + userId + " => " + installed);
}
if (installed != ps.getInstalled(userId)) {
installedStateChanged = true;
}
ps.setInstalled(installed, userId);
}
}
}
if (writeSettings) {
mSettings.writeLPr();
}
if (installedStateChanged) {
mSettings.writeKernelMappingLPr(ps);
}
}
if (removedAppId != -1) {
removeKeystoreDataIfNeeded(UserHandle.USER_ALL, removedAppId);
}
这里首先从Settings中删除PackageSettings的信息:
int removePackageLPw(String name) {
final PackageSetting p = mPackages.get(name);
if (p != null) {
mPackages.remove(name);
removeInstallerPackageStatus(name);
if (p.sharedUser != null) {
p.sharedUser.removePackage(p);
if (p.sharedUser.packages.size() == 0) {
mSharedUsers.remove(p.sharedUser.name);
removeUserIdLPw(p.sharedUser.userId);
return p.sharedUser.userId;
}
} else {
removeUserIdLPw(p.appId);
return p.appId;
}
}
return -1;
}
private void removeInstallerPackageStatus(String packageName) {
// Check if the package to be removed is an installer package.
if (!mInstallerPackages.contains(packageName)) {
return;
}
for (int i = 0; i < mPackages.size(); i++) {
final PackageSetting ps = mPackages.valueAt(i);
final String installerPackageName = ps.getInstallerPackageName();
if (installerPackageName != null
&& installerPackageName.equals(packageName)) {
ps.setInstallerPackageName(null);
ps.isOrphaned = true;
}
}
mInstallerPackages.remove(packageName);
}
removePackageLPw首先从mPackages这个map中删除PackageSettings信息,如果不存在sharedUser,则从mUserIds这个数组中删除对应的Package UID信息;如果存在sharedUser,则首先检查这个sharedUser是否所有的package都已经被卸载了,如果都被卸载了,这个sharedUser也就可以删除。然后removePackageDataLI调用updatePermissionsLPw去检查mPermissionTrees和mPermissions两个数组中的权限是否是被删除的Package提供,如果有,则删除。Settings的updateSharedUserPermsLPw方法用于清除sharedUser不用的gid信息,防止权限泄露
private void updatePermissionsLPw(String changingPkg,
PackageParser.Package pkgInfo, String replaceVolumeUuid, int flags) {
// Make sure there are no dangling permission trees.
Iterator it = mSettings.mPermissionTrees.values().iterator();
while (it.hasNext()) {
final BasePermission bp = it.next();
if (bp.packageSetting == null) {
// We may not yet have parsed the package, so just see if
// we still know about its settings.
bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
}
if (bp.packageSetting == null) {
Slog.w(TAG, "Removing dangling permission tree: " + bp.name
+ " from package " + bp.sourcePackage);
it.remove();
} else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
Slog.i(TAG, "Removing old permission tree: " + bp.name
+ " from package " + bp.sourcePackage);
flags |= UPDATE_PERMISSIONS_ALL;
it.remove();
}
}
}
// Make sure all dynamic permissions have been assigned to a package,
// and make sure there are no dangling permissions.
it = mSettings.mPermissions.values().iterator();
while (it.hasNext()) {
final BasePermission bp = it.next();
if (bp.type == BasePermission.TYPE_DYNAMIC) {
if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
+ bp.name + " pkg=" + bp.sourcePackage
+ " info=" + bp.pendingInfo);
if (bp.packageSetting == null && bp.pendingInfo != null) {
final BasePermission tree = findPermissionTreeLP(bp.name);
if (tree != null && tree.perm != null) {
bp.packageSetting = tree.packageSetting;
bp.perm = new PackageParser.Permission(tree.perm.owner,
new PermissionInfo(bp.pendingInfo));
bp.perm.info.packageName = tree.perm.info.packageName;
bp.perm.info.name = bp.name;
bp.uid = tree.uid;
}
}
}
if (bp.packageSetting == null) {
// We may not yet have parsed the package, so just see if
// we still know about its settings.
bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage);
}
if (bp.packageSetting == null) {
Slog.w(TAG, "Removing dangling permission: " + bp.name
+ " from package " + bp.sourcePackage);
it.remove();
} else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) {
if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) {
Slog.i(TAG, "Removing old permission: " + bp.name
+ " from package " + bp.sourcePackage);
flags |= UPDATE_PERMISSIONS_ALL;
it.remove();
}
}
}
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "grantPermissions");
// Now update the permissions for all packages, in particular
// replace the granted permissions of the system packages.
if ((flags&UPDATE_PERMISSIONS_ALL) != 0) {
for (PackageParser.Package pkg : mPackages.values()) {
if (pkg != pkgInfo) {
// Only replace for packages on requested volume
final String volumeUuid = getVolumeUuidForPackage(pkg);
final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_ALL) != 0)
&& Objects.equals(replaceVolumeUuid, volumeUuid);
grantPermissionsLPw(pkg, replace, changingPkg);
}
}
}
if (pkgInfo != null) {
// Only replace for packages on requested volume
final String volumeUuid = getVolumeUuidForPackage(pkgInfo);
final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_PKG) != 0)
&& Objects.equals(replaceVolumeUuid, volumeUuid);
grantPermissionsLPw(pkgInfo, replace, changingPkg);
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
循环的从要被卸载的Package所在的sharedUser组中找被申请的权限是否还被同一组的其它package使用,如果没有使用者,就从sharedUser的grantedPermissions删除。clearPackagePreferredActivitiesLPw与AMS相关,我们留到以后再来介绍。在removePackageDataLIF方法最好调用Settings.writeLPr()方法将改动的信息写到Package.xml中。到这里,我们前面所说的deleteInstalledPackageLIF方法中的第一步已经完成,来看第二部分createInstallArgsForExisting:
if (ps.parentPackageName == null) {
if (deleteCodeAndResources && (outInfo != null)) {
outInfo.args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));
if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.args);
}
}
private InstallArgs createInstallArgsForExisting(int installFlags, String codePath,
String resourcePath, String[] instructionSets) {
final boolean isInAsec;
if (installOnExternalAsec(installFlags)) {
/* Apps on SD card are always in ASEC containers. */
isInAsec = true;
} else if (installForwardLocked(installFlags)
&& !codePath.startsWith(mDrmAppPrivateInstallDir.getAbsolutePath())) {
/*
* Forward-locked apps are only in ASEC containers if they're the
* new style
*/
isInAsec = true;
} else {
isInAsec = false;
}
if (isInAsec) {
return new AsecInstallArgs(codePath, instructionSets,
installOnExternalAsec(installFlags), installForwardLocked(installFlags));
} else {
return new FileInstallArgs(codePath, resourcePath, instructionSets);
}
}
这里根据安装目录的不同,分别构造FileInstallArgs和AsecInstallArgs来完成code和resource资源的清除。这里我们主要介绍卸载内部存储空间上面的APK,来看FileInstallArgs的doPostDeleteLI方法:
boolean doPostDeleteLI(boolean delete) {
// XXX err, shouldn't we respect the delete flag?
cleanUpResourcesLI();
return true;
}
void cleanUpResourcesLI() {
// Try enumerating all code paths before deleting
List allCodePaths = Collections.EMPTY_LIST;
if (codeFile != null && codeFile.exists()) {
try {
final PackageLite pkg = PackageParser.parsePackageLite(codeFile, 0);
allCodePaths = pkg.getAllCodePaths();
} catch (PackageParserException e) {
// Ignored; we tried our best
}
}
cleanUp();
removeDexFiles(allCodePaths, instructionSets);
}
cleanUpResourcesLI方法中首先调用cleanUp方法去删除code、resource以及library文件:
private boolean cleanUp() {
if (codeFile == null || !codeFile.exists()) {
return false;
}
removeCodePathLI(codeFile);
if (resourceFile != null && !FileUtils.contains(codeFile, resourceFile)) {
resourceFile.delete();
}
return true;
}
void removeCodePathLI(File codePath) {
if (codePath.isDirectory()) {
try {
mInstaller.rmPackageDir(codePath.getAbsolutePath());
} catch (InstallerException e) {
Slog.w(TAG, "Failed to remove code path", e);
}
} else {
codePath.delete();
}
}
//InstalldNativeService.rmPackageDir
binder::Status InstalldNativeService::rmPackageDir(const std::string& packageDir) {
ENFORCE_UID(AID_SYSTEM);
std::lock_guard lock(mLock);
if (validate_apk_path(packageDir.c_str())) {
return error("Invalid path " + packageDir);
}
if (delete_dir_contents_and_dir(packageDir) != 0) {
return error("Failed to delete " + packageDir);
}
return ok();
}
然后cleanUpResourcesLI调用installd的rmdex方法去删除存在/data/dalvik-cache文件:
void removeDexFiles(List allCodePaths, String[] instructionSets) {
if (!allCodePaths.isEmpty()) {
if (instructionSets == null) {
throw new IllegalStateException("instructionSet == null");
}
String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
for (String codePath : allCodePaths) {
for (String dexCodeInstructionSet : dexCodeInstructionSets) {
try {
mInstaller.rmdex(codePath, dexCodeInstructionSet);
} catch (InstallerException ignored) {
}
}
}
}
}
//InstalldNativeService::rmdex
binder::Status InstalldNativeService::rmdex(const std::string& codePath,
const std::string& instructionSet) {
ENFORCE_UID(AID_SYSTEM);
std::lock_guard lock(mLock);
char dex_path[PKG_PATH_MAX];
const char* path = codePath.c_str();
const char* instruction_set = instructionSet.c_str();
if (validate_apk_path(path) && validate_system_app_path(path)) {
return error("Invalid path " + codePath);
}
if (!create_cache_path(dex_path, path, instruction_set)) {
return error("Failed to create cache path for " + codePath);
}
ALOGV("unlink %s\n", dex_path);
if (unlink(dex_path) < 0) {
// It's ok if we don't have a dalvik cache path. Report error only when the path exists
// but could not be unlinked.
if (errno != ENOENT) {
return error(StringPrintf("Failed to unlink %s", dex_path));
}
}
return ok();
}
create_cache_path依据path构造/data/dalvik-cache下的文件目录,调用unlink去删除文件。到这里卸载APK的deletePackageAsUser函数就已经分析完了。这时会通过observer把卸载结果返回给UninstallAppProgress。