APK的卸载时我们都会调用到PckageManagerService的deletePackage来删除APK,下面就分析下PKMS删除APK的具体流程。
首先总结卸载非系统APK主要做了哪几件事:
1. 从PKMS内部变量mPackages去除APK,同时从PKMS内部变量中移除APK的Avtivity、Service等信息。
2.删除data下apk产生的数据及目录
3. 删除data分区下产生的APK数据以及dex文件
* The key steps in deleting a package are
* deleting the package information in internal structures like mPackages,
* deleting the packages base directories through installd
* updating mSettings to reflect current status
* persisting settings for later use
* sending a broadcast if necessary
删除APK首先调用的方法是deletePackage()
public void deletePackage(final String packageName,
final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DELETE_PACKAGES, null);
Preconditions.checkNotNull(packageName);
Preconditions.checkNotNull(observer);
final int uid = Binder.getCallingUid();
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);
}
//判断该用户id是否被限制卸载应用
if (isUserRestricted(userId, UserManager.DISALLOW_UNINSTALL_APPS)) {
try {
observer.onPackageDeleted(packageName,
PackageManager.DELETE_FAILED_USER_RESTRICTED, null);
} catch (RemoteException re) {
}
return;
}
//判断APK是否会阻止用户进行卸载
if (!deleteAllUsers && getBlockUninstallForUser(packageName, userId)) {
try {
observer.onPackageDeleted(packageName,
PackageManager.DELETE_FAILED_OWNER_BLOCKED, null);
} catch (RemoteException re) {
}
return;
}
if (DEBUG_REMOVE) {
Slog.d(TAG, "deletePackageAsUser: pkg=" + packageName + " user=" + userId
+ " deleteAllUsers: " + deleteAllUsers );
}
//异步卸载apk
// Queue up an async operation since the package deletion may take a little while.
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
int returnCode;
if (!deleteAllUsers) {
//只卸载单个用户的APK
returnCode = deletePackageX(packageName, userId, deleteFlags);
} else {
//手机所有用户都卸载
int[] blockUninstallUserIds = getBlockUninstallForUsers(packageName, users);
// If nobody is blocking uninstall, proceed with delete for all users
if (ArrayUtils.isEmpty(blockUninstallUserIds)) {
returnCode = deletePackageX(packageName, userId, deleteFlags);
} else {
//若有APK对用户ID限制卸载,则对能卸载的用户挨个进行卸载
// 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(packageName, userId, userFlags);
if (returnCode != PackageManager.DELETE_SUCCEEDED) {
Slog.w(TAG, "Package delete failed for user " + userId
+ ", returnCode " + returnCode);
}
}
}
// The app has only been marked uninstalled for certain users.
// We still need to report that delete was blocked
returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED;
}
}
try {
observer.onPackageDeleted(packageName, returnCode, null);
} catch (RemoteException e) {
Log.i(TAG, "Observer no longer exists.");
} //end catch
} //end run
});
}
deletePackage()判断
1. 该userId是否被限制卸载APK
2. APK是否现在被该用户卸载
若userId具有卸载该APK的权限,则调用Handler线程执行卸载操作,调用deletePackageX()函数
private int deletePackageX(String packageName, int userId, int deleteFlags) {
final PackageRemovedInfo info = new PackageRemovedInfo();
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;
//保存仍然安装该APK的用户ID
// 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;
}
allUsers = sUserManager.getUserIds();
info.origUsers = uninstalledPs.queryInstalledUsers(allUsers, true);
}
final int freezeUser;
if (isUpdatedSystemApp(uninstalledPs)
&& ((deleteFlags & PackageManager.DELETE_SYSTEM_APP) == 0)) {
// We're downgrading a system app, which will apply to all users, so
// freeze them all during the downgrade
freezeUser = UserHandle.USER_ALL;
} else {
freezeUser = removeUser;
}
synchronized (mInstallLock) {
if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId);
try (PackageFreezer freezer = freezePackageForDelete(packageName, freezeUser,
deleteFlags, "deletePackageX")) {
res = deletePackageLIF(packageName, UserHandle.of(removeUser), true, allUsers,
deleteFlags | REMOVE_CHATTY, info, true, null);
}
synchronized (mPackages) {
if (res) {
mEphemeralApplicationRegistry.onPackageUninstalledLPw(uninstalledPs.pkg);
}
}
}
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();
// Delete the resources here after sending the broadcast to let
// other processes clean up before deleting resources.
if (info.args != null) {
synchronized (mInstallLock) {
info.args.doPostDeleteLI(true);
}
}
return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;
}
1.调用deletePackageLIF()卸载APK
2.成功卸载之后发送广播通知APK已经卸载
3.调用安装安装函数的doPostDeleteLI(),主要是删除一些资源文件,后续会分析。
下面先分析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;
}
if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageLI: " + packageName + " user " + user);
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)) {
if (DEBUG_REMOVE) {
Slog.d(TAG, "Uninstalled child package:" + packageName + " for user:"
+ ((user == null) ? UserHandle.USER_ALL : user));
}
final int removedUserId = (user != null) ? user.getIdentifier()
: UserHandle.USER_ALL;
if (!clearPackageStateForUserLIF(ps, removedUserId, outInfo)) {
return false;
}
markPackageUninstalledForUserLPw(ps, user);
scheduleWritePackageRestrictionsLocked(user);
return true;
}
}
//只卸载单个用户下的APK
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) {
//若该APK仍然被其他用户安装,则只需清除卸载用户的数据
// Other user still have this package installed, so all
// we need to do is clear this user's data and save that
// it is uninstalled.
if (DEBUG_REMOVE) Slog.d(TAG, "Still installed by other users");
if (!clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo)) {
return false;
}
scheduleWritePackageRestrictionsLocked(user);
return true;
} else {
//若已经没有用户安装了APK,则完全删除APK
// We need to set it back to 'installed' so the uninstall
// broadcasts will be sent correctly.
if (DEBUG_REMOVE) Slog.d(TAG, "Not installed by other users, full delete");
ps.setInstalled(true, user.getIdentifier());
}
} else {
//若是系统APK,则只清除用户数据
// This is a system app, so we assume that the
// other users still have this package installed, so all
// we need to do is clear this user's data and save that
// it is uninstalled.
if (DEBUG_REMOVE) Slog.d(TAG, "Deleting system app");
if (!clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo)) {
return false;
}
scheduleWritePackageRestrictionsLocked(user);
return true;
}
}
//如卸载APK有子APK,则需要卸载子APK
// If we are deleting a composite package for all users, keep track
// of result for each child.
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();
childInfo.removedPackage = childPackageName;
outInfo.removedChildPackages.put(childPackageName, childInfo);
PackageSetting childPs = mSettings.peekPackageLPr(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);
// When an updated system application is deleted we delete the existing resources
// as well and fall back to existing code in system partition
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);
}
// Take a note whether we deleted the package for all users
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 we uninstalled an update to a system app there may be some
// child packages that appeared as they are declared in the system
// app but were not declared in the update.
if (isSystemApp(ps)) {
synchronized (mPackages) {
PackageSetting updatedPs = mSettings.peekPackageLPr(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.peekPackageLPr(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()做的几件事
1.调用clearPackageStateForUserLIF清除用户数据,针对与是否是系统APK,以及多用户的场景做不同的操作。
2.若是系统APK,调用deleteSystemPackageLIF()继续卸载资源等
若是用户安装的APK,调用deleteInstalledPackageLIF()继续卸载代码及资源
clearPackageStateForUserLIF()函数如下:
private boolean clearPackageStateForUserLIF(PackageSetting ps, int userId, PackageRemovedInfo outInfo) { final PackageParser.Package pkg; synchronized (mPackages) { pkg = mPackages.get(ps.name); } final int[] userIds = (userId == UserHandle.USER_ALL) ? sUserManager.getUserIds() : new int[] {userId}; for (int nextUserId : userIds) { if (DEBUG_REMOVE) { Slog.d(TAG, "Updating package:" + ps.name + " install state for user:" + nextUserId); } //删除data下APK产生的内容、APK配置表、KeyStore数据 destroyAppDataLIF(pkg, userId, StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE); destroyAppProfilesLIF(pkg, userId); removeKeystoreDataIfNeeded(nextUserId, ps.appId); schedulePackageCleaning(ps.name, nextUserId, false); synchronized (mPackages) { if (clearPackagePreferredActivitiesLPw(ps.name, nextUserId)) {
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; } } } } //从PKMS内部变量mPackages去除APK,同时从PKMS内部变量中移除APK的Avtivity、Service等信息。 // Delete package data from internal structures and also remove data if flag is set removePackageDataLIF(ps, allUserHandles, outInfo, flags, writeSettings); //删除子APK数据 // Delete the child packages data final int childCount = (ps.childPackageNames != null) ? ps.childPackageNames.size() : 0; for (int i = 0; i < childCount; i++) { PackageSetting childPs; synchronized (mPackages) { childPs = mSettings.peekPackageLPr(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); } } //创建InstallArgs,保存在outInfo.args,后面会调用其onPostDelete方法删除APK文件和dex文件等。 // Delete application code and resources only for parent packages 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; }
scheduleWritePackageRestrictionsLocked(nextUserId); } resetUserChangesToRuntimePermissionsAndFlagsLPw(ps, nextUserId); } } if (outInfo != null) { outInfo.removedPackage = ps.name; outInfo.removedAppId = ps.appId; outInfo.removedUsers = userIds; } return true; }
主要调用了destroyAppDataLIF()、destroyAppProfilesLIF()、removeKeystoreDataIfNeeded()分别删除data下APK产生的内容、APK配置表、KeyStore数据这几个方法都会调用到insatlld进程进行删除文件。这里不进行分析。
APK产生的文件删除完了,下面就是删除具体的APK了,先分析删除用户安装的APK方法deleteInstalledPackageLIF(),方法如下:
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; } } } } //从PKMS内部变量mPackages去除APK,同时从PKMS内部变量中移除APK的Avtivity、Service等信息。 // Delete package data from internal structures and also remove data if flag is set removePackageDataLIF(ps, allUserHandles, outInfo, flags, writeSettings); //删除子APK数据 // Delete the child packages data final int childCount = (ps.childPackageNames != null) ? ps.childPackageNames.size() : 0; for (int i = 0; i < childCount; i++) { PackageSetting childPs; synchronized (mPackages) { childPs = mSettings.peekPackageLPr(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); } } //创建InstallArgs,保存在outInfo.args,后面会调用其onPostDelete方法删除APK文件和dex文件等。 // Delete application code and resources only for parent packages 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; }
1.调用removePackageDataLIF删除APK下产生的data目录,从PKMS内部变量mPackages去除APK,同时从PKMS内部变量中移除APK的Avtivity、Service等信息
2.删除子APK的data目录。从PKMS内部变量mPackages去除APK,同时从PKMS内部变量中移除APK的Avtivity、Service等信息3.创建InstallArgs,保存在outInfo.args,其实就是创建了FileInstallArgs或AsecInstallArgs,后面会调用其onPostDelete方法删除APK文件和dex文件等
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); // Retrieve object to delete permissions for shared user later on 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.removedUsers = deletedPs != null ? deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true) : null; } } //从PKMS内部变量mPackages去除APK,同时从PKMS内部变量中移除APK的Avtivity、Service等信息。 removePackageLI(ps, (flags & REMOVE_CHATTY) != 0); //如需不需要保存数据,则直接删除APK下相应的data目录。 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); } // writer synchronized (mPackages) { if (deletedPs != null) { if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) { clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL); clearDefaultBrowserIfNeeded(packageName); if (outInfo != null) { mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName); outInfo.removedAppId = mSettings.removePackageLPw(packageName); } //清除和APK相关的权限 updatePermissionsLPw(deletedPs.name, null, 0); if (deletedPs.sharedUser != null) { // Remove permissions associated with package. Since runtime // permissions are per user we have to kill the removed package // or packages running under the shared user of the removed // package if revoking the permissions requested only by the removed // package is successful and this causes a change in gids. 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); } // make sure to preserve per-user disabled state if this removal was just // a downgrade of a system app to the factory package 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); } ps.setInstalled(installed, userId); } } } // can downgrade to reader if (writeSettings) { // Save settings now mSettings.writeLPr(); } } if (outInfo != null) { // A user ID was deleted here. Go through all users and remove it // from KeyStore. removeKeystoreDataIfNeeded(UserHandle.USER_ALL, outInfo.removedAppId); } }
主要调用了removePackageLI()方法删除数据从removepackageLI()方法看出,先是从mPackages中删除了该APK,然后调用cleanPackageDataStructuresLILPw()从内部变量mActivities、mProviders中删除该APK的Activity、service信息。private void removePackageLI(PackageParser.Package pkg, boolean chatty) { // Remove the parent package setting PackageSetting ps = (PackageSetting) pkg.mExtras; if (ps != null) { removePackageLI(ps, chatty); } // Remove the child package setting final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; for (int i = 0; i < childCount; i++) { PackageParser.Package childPkg = pkg.childPackages.get(i); ps = (PackageSetting) childPkg.mExtras; if (ps != null) { removePackageLI(ps, chatty); } } } void removePackageLI(PackageSetting ps, boolean chatty) { if (DEBUG_INSTALL) { if (chatty) Log.d(TAG, "Removing package " + ps.name); } // writer synchronized (mPackages) { mPackages.remove(ps.name); final PackageParser.Package pkg = ps.pkg; if (pkg != null) { cleanPackageDataStructuresLILPw(pkg, chatty); } } }
下面分析删除系统APK的方法deleteSystemPackageLIF(),如下:
删除系统APK分为几步private boolean deleteSystemPackageLIF(PackageParser.Package deletedPkg, PackageSetting deletedPs, int[] allUserHandles, int flags, PackageRemovedInfo outInfo, boolean writeSettings) { if (deletedPs.parentPackageName != null) { Slog.w(TAG, "Attempt to delete child system package " + deletedPkg.packageName); return false; } final boolean applyUserRestrictions = (allUserHandles != null) && (outInfo.origUsers != null); final PackageSetting disabledPs; // 获取system APP是否有升级过,若系统APK没有升级过,则退出卸载 // Confirm if the system package has been updated // An updated system app can be deleted. This will also have to restore // the system pkg from system partition // reader synchronized (mPackages) { disabledPs = mSettings.getDisabledSystemPkgLPr(deletedPs.name); } if (DEBUG_REMOVE) Slog.d(TAG, "deleteSystemPackageLI: newPs=" + deletedPkg.packageName + " disabledPs=" + disabledPs); if (disabledPs == null) { Slog.w(TAG, "Attempt to delete unknown system package "+ deletedPkg.packageName); return false; } else if (DEBUG_REMOVE) { Slog.d(TAG, "Deleting system pkg from data partition"); } if (DEBUG_REMOVE) { if (applyUserRestrictions) { Slog.d(TAG, "Remembering install states:"); for (int userId : allUserHandles) { final boolean finstalled = ArrayUtils.contains(outInfo.origUsers, userId); Slog.d(TAG, " u=" + userId + " inst=" + finstalled); } } } // 若系统APK有升级过,那么卸载APK则是先卸载更新后的APK,然后安装原有预置的APK // Delete the updated package outInfo.isRemovedPackageSystemUpdate = true; if (outInfo.removedChildPackages != null) { final int childCount = (deletedPs.childPackageNames != null) ? deletedPs.childPackageNames.size() : 0; for (int i = 0; i < childCount; i++) { String childPackageName = deletedPs.childPackageNames.get(i); if (disabledPs.childPackageNames != null && disabledPs.childPackageNames .contains(childPackageName)) { PackageRemovedInfo childInfo = outInfo.removedChildPackages.get( childPackageName); if (childInfo != null) { childInfo.isRemovedPackageSystemUpdate = true; } } } } if (disabledPs.versionCode < deletedPs.versionCode) { // Delete data for downgrades flags &= ~PackageManager.DELETE_KEEP_DATA; } else { // Preserve data by setting flag flags |= PackageManager.DELETE_KEEP_DATA; } //卸载更新后的APK boolean ret = deleteInstalledPackageLIF(deletedPs, true, flags, allUserHandles, outInfo, writeSettings, disabledPs.pkg); if (!ret) { return false; } // writer synchronized (mPackages) { // Reinstate the old system package enableSystemPackageLPw(disabledPs.pkg); // Remove any native libraries from the upgraded package. removeNativeBinariesLI(deletedPs); } // 重新安装旧的APK // Install the system package if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs); int parseFlags = mDefParseFlags | PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR; if (locationIsPrivileged(disabledPs.codePath)) { parseFlags |= PackageParser.PARSE_IS_PRIVILEGED; } final PackageParser.Package newPkg; try { newPkg = scanPackageTracedLI(disabledPs.codePath, parseFlags, SCAN_NO_PATHS, 0, null); } catch (PackageManagerException e) { Slog.w(TAG, "Failed to restore system package:" + deletedPkg.packageName + ": " + e.getMessage()); return false; } prepareAppDataAfterInstallLIF(newPkg); // writer synchronized (mPackages) { PackageSetting ps = mSettings.mPackages.get(newPkg.packageName); // Propagate the permissions state as we do not want to drop on the floor // runtime permissions. The update permissions method below will take // care of removing obsolete permissions and grant install permissions. ps.getPermissionsState().copyFrom(deletedPs.getPermissionsState()); updatePermissionsLPw(newPkg.packageName, newPkg, UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG); if (applyUserRestrictions) { if (DEBUG_REMOVE) { Slog.d(TAG, "Propagating install state across reinstall"); } for (int userId : allUserHandles) { final boolean installed = ArrayUtils.contains(outInfo.origUsers, userId); if (DEBUG_REMOVE) { Slog.d(TAG, " user " + userId + " => " + installed); } ps.setInstalled(installed, userId); mSettings.writeRuntimePermissionsForUserLPr(userId, false); } // Regardless of writeSettings we need to ensure that this restriction // state propagation is persisted mSettings.writeAllUsersPackageRestrictionsLPr(); } // can downgrade to reader here if (writeSettings) { mSettings.writeLPr(); } } return true; }
1.判断系统APK是否有升级过,若没有升级过,则推出卸载,不进行任何操作
2.若系统APK进行过升级,则卸载升级之后的APK,重新安装就的预置在系统中的APK。
下面回到deletePackageX()方法,前面该方法最后会调用doPostDeleteLI(),以下以卸载内部存储的FileInstallArgs为例,其doPostDeleteLI()方法如下:
boolean doPostDeleteLI(boolean delete) { // XXX err, shouldn't we respect the delete flag? cleanUpResourcesLI(); return true; }
private void cleanUpResourcesLI(List<String> allCodePaths) { cleanUp(); removeDexFiles(allCodePaths, instructionSets); }
private boolean cleanUp() { if (codeFile == null || !codeFile.exists()) { return false; } removeCodePathLI(codeFile); if (resourceFile != null && !FileUtils.contains(codeFile, resourceFile)) { resourceFile.delete(); } return true; }
private void removeDexFiles(List<String> 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) { } } } } }
doPostDeleteLI()方法中通过installd分别删除了code文件已经产生的dex文件。至此APK卸载完成