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;
}
deletePackageX()完成几件事情
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(),方法如下:
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;
}
deleteInstalledPackageLIF()做的几件事
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()方法删除数据
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);
}
}
}
从removepackageLI()方法看出,先是从mPackages中删除了该APK,然后调用cleanPackageDataStructuresLILPw()从内部变量mActivities、mProviders中删除该APK的Activity、service信息。
下面分析删除系统APK的方法deleteSystemPackageLIF(),如下:
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;
}
删除系统APK分为几步
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卸载完成