Android6.0 PackageManagerService卸载应用
2016-11-21 17:05
369 查看
PKMS中卸载应用是通过deletePackage函数来执行,这个函数主要是调用了一些Observer回调,然后调用了deletePackageX函数。
我们来看下deletePackageX函数,主要是调用deletePackageLI函数继续执行,关键当返回的info不为空就调用info.args.doPostDeleteLI(true)删除应用。
我们来看deletePackageLI函数,如果只有data,直接调用removePackageDataLI函数。如果是系统应用调用deleteSystemPackageLI,不是调用deleteInstalledPackageLI函数。
卸载系统应用,最后也是调用deleteInstalledPackageLI来完成卸载的,我们来看下这个函数。
我们先看removePackageDataLI函数,就是删除各种资源,但是我们没看到删除apk文件。
我们再来看deleteInstalledPackageLI函数,最后一段代码,
我们来看下这个函数,如果不是安装在sd卡上,最后新建一个FileInstallArgs对象。
最后返回到deletePackageX函数,最后调用如下代码,直接到FileInstallArgs的doPostDeleteLI函数。
doPostDeleteLI函数如下:
cleanUpResourcesLI函数会删除资源和代码文件,dex文件
void cleanUpResourcesLI() {
// Try enumerating all code paths before deleting
List<String> 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);
}cleanUp函数就是删除apk文件。
private boolean cleanUp() {
if (codeFile == null || !codeFile.exists()) {
return false;
}
if (codeFile.isDirectory()) {
mInstaller.rmPackageDir(codeFile.getAbsolutePath());
} else {
codeFile.delete();
}
if (resourceFile != null && !FileUtils.contains(codeFile, resourceFile)) {
resourceFile.delete();
}
return true;
}
public void deletePackage(final String packageName, final IPackageDeleteObserver2 observer, final int userId, final int flags) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.DELETE_PACKAGES, null); Preconditions.checkNotNull(packageName); Preconditions.checkNotNull(observer); final int uid = Binder.getCallingUid(); if (UserHandle.getUserId(uid) != userId) { mContext.enforceCallingPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, "deletePackage for user " + userId); } if (isUserRestricted(userId, UserManager.DISALLOW_UNINSTALL_APPS)) { try { observer.onPackageDeleted(packageName,//回调 PackageManager.DELETE_FAILED_USER_RESTRICTED, null); } catch (RemoteException re) { } return; } boolean uninstallBlocked = false; if ((flags & PackageManager.DELETE_ALL_USERS) != 0) { int[] users = sUserManager.getUserIds(); for (int i = 0; i < users.length; ++i) { if (getBlockUninstallForUser(packageName, users[i])) { uninstallBlocked = true; break; } } } else { uninstallBlocked = getBlockUninstallForUser(packageName, userId); } if (uninstallBlocked) { 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); } // Queue up an async operation since the package deletion may take a little while. mHandler.post(new Runnable() {//异步调用deletePackageX函数 public void run() { mHandler.removeCallbacks(this); final int returnCode = deletePackageX(packageName, userId, flags); if (observer != null) { try { observer.onPackageDeleted(packageName, returnCode, null); } catch (RemoteException e) { Log.i(TAG, "Observer no longer exists."); } //end catch } //end if } //end run }); }
我们来看下deletePackageX函数,主要是调用deletePackageLI函数继续执行,关键当返回的info不为空就调用info.args.doPostDeleteLI(true)删除应用。
private int deletePackageX(String packageName, int userId, int flags) { ...... synchronized (mInstallLock) { if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId); res = deletePackageLI(packageName, removeForUser, true, allUsers, perUserInstalled, flags | REMOVE_CHATTY, info, true); systemUpdate = info.isRemovedPackageSystemUpdate; if (res && !systemUpdate && mPackages.get(packageName) == null) { removedForAllUsers = true; } if (DEBUG_REMOVE) Slog.d(TAG, "delete res: systemUpdate=" + systemUpdate + " removedForAllUsers=" + removedForAllUsers); } ...... // 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);//删除资源、apk等 } } return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR; }
我们来看deletePackageLI函数,如果只有data,直接调用removePackageDataLI函数。如果是系统应用调用deleteSystemPackageLI,不是调用deleteInstalledPackageLI函数。
private boolean deletePackageLI(String packageName, UserHandle user, boolean deleteCodeAndResources, int[] allUserHandles, boolean[] perUserInstalled, int flags, PackageRemovedInfo outInfo, boolean writeSettings) { ...... if (dataOnly) { // Delete application data first if (DEBUG_REMOVE) Slog.d(TAG, "Removing package data only"); removePackageDataLI(ps, null, null, outInfo, flags, writeSettings); return 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 = deleteSystemPackageLI(ps, allUserHandles, perUserInstalled, flags, outInfo, writeSettings); } else { if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package:" + ps.name); // Kill application pre-emptively especially for apps on sd. killApplication(packageName, ps.appId, "uninstall pkg"); ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags, allUserHandles, perUserInstalled, outInfo, writeSettings); } return ret; }
卸载系统应用
为什么会有卸载系统应用呢,当我们调用scanPackageLI扫描目录时有时候失败,也需要调用deletePackageLI来删除apk,这个时候就会有系统应用了。private boolean deleteSystemPackageLI(PackageSetting newPs, int[] allUserHandles, boolean[] perUserInstalled, int flags, PackageRemovedInfo outInfo, boolean writeSettings) { final boolean applyUserRestrictions = (allUserHandles != null) && (perUserInstalled != null); PackageSetting disabledPs = null; // 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(newPs.name); } if (DEBUG_REMOVE) Slog.d(TAG, "deleteSystemPackageLI: newPs=" + newPs + " disabledPs=" + disabledPs); if (disabledPs == null) { Slog.w(TAG, "Attempt to delete unknown system package "+ newPs.name); return false; } else if (DEBUG_REMOVE) { Slog.d(TAG, "Deleting system pkg from data partition"); } // Delete the updated package outInfo.isRemovedPackageSystemUpdate = true; if (disabledPs.versionCode < newPs.versionCode) { // Delete data for downgrades flags &= ~PackageManager.DELETE_KEEP_DATA;//是否保留资源 } else { // Preserve data by setting flag flags |= PackageManager.DELETE_KEEP_DATA; } boolean ret = deleteInstalledPackageLI(newPs, true, flags,//卸载apk allUserHandles, perUserInstalled, outInfo, writeSettings); if (!ret) { return false; } // writer synchronized (mPackages) { // Reinstate the old system package mSettings.enableSystemPackageLPw(newPs.name); // Remove any native libraries from the upgraded package. NativeLibraryHelper.removeNativeBinariesLI(newPs.legacyNativeLibraryPathString); } // Install the system package int parseFlags = PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM; if (locationIsPrivileged(disabledPs.codePath)) { parseFlags |= PackageParser.PARSE_IS_PRIVILEGED; } final PackageParser.Package newPkg; try { newPkg = scanPackageLI(disabledPs.codePath, parseFlags, SCAN_NO_PATHS, 0, null);//重新apk扫描目录 } catch (PackageManagerException e) { Slog.w(TAG, "Failed to restore system package:" + newPs.name + ": " + e.getMessage()); return false; } // 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(newPs.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 i = 0; i < allUserHandles.length; i++) { if (DEBUG_REMOVE) { Slog.d(TAG, " user " + allUserHandles[i] + " => " + perUserInstalled[i]); } ps.setInstalled(perUserInstalled[i], allUserHandles[i]); mSettings.writeRuntimePermissionsForUserLPr(allUserHandles[i], 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();//更新packages.xml } } return true; }
卸载系统应用,最后也是调用deleteInstalledPackageLI来完成卸载的,我们来看下这个函数。
卸载普通应用
卸载普通应用就直接调用了deleteInstalledPackageLI函数private boolean deleteInstalledPackageLI(PackageSetting ps, boolean deleteCodeAndResources, int flags, int[] allUserHandles, boolean[] perUserInstalled, PackageRemovedInfo outInfo, boolean writeSettings) { if (outInfo != null) { outInfo.uid = ps.appId; } // Delete package data from internal structures and also remove data if flag is set removePackageDataLI(ps, allUserHandles, perUserInstalled, outInfo, flags, writeSettings); // Delete application code and resources 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; }
我们先看removePackageDataLI函数,就是删除各种资源,但是我们没看到删除apk文件。
private void removePackageDataLI(PackageSetting ps, int[] allUserHandles, boolean[] perUserInstalled, PackageRemovedInfo outInfo, int flags, boolean writeSettings) { String packageName = ps.name; if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + ps); removePackageLI(ps, (flags&REMOVE_CHATTY) != 0); // Retrieve object to delete permissions for shared user later on final PackageSetting deletedPs; // reader synchronized (mPackages) { deletedPs = mSettings.mPackages.get(packageName); if (outInfo != null) { outInfo.removedPackage = packageName; outInfo.removedUsers = deletedPs != null ? deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true) : null; } } if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) { removeDataDirsLI(ps.volumeUuid, packageName);// 卸载data目录 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); } 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_OWNER) { // 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 && perUserInstalled != null) { if (DEBUG_REMOVE) { Slog.d(TAG, "Propagating install state across downgrade"); } for (int i = 0; i < allUserHandles.length; i++) { if (DEBUG_REMOVE) { Slog.d(TAG, " user " + allUserHandles[i] + " => " + perUserInstalled[i]); } ps.setInstalled(perUserInstalled[i], allUserHandles[i]); } } } // can downgrade to reader if (writeSettings) { // Save settings now mSettings.writeLPr();//更新packages.xml } } if (outInfo != null) { // A user ID was deleted here. Go through all users and remove it // from KeyStore. removeKeystoreDataIfNeeded(UserHandle.USER_ALL, outInfo.removedAppId); }
我们再来看deleteInstalledPackageLI函数,最后一段代码,
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); }
我们来看下这个函数,如果不是安装在sd卡上,最后新建一个FileInstallArgs对象。
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); } }
最后返回到deletePackageX函数,最后调用如下代码,直接到FileInstallArgs的doPostDeleteLI函数。
if (info.args != null) { synchronized (mInstallLock) { info.args.doPostDeleteLI(true); } }
doPostDeleteLI函数如下:
boolean doPostDeleteLI(boolean delete) { // XXX err, shouldn't we respect the delete flag? cleanUpResourcesLI(); return true; }
cleanUpResourcesLI函数会删除资源和代码文件,dex文件
void cleanUpResourcesLI() {
// Try enumerating all code paths before deleting
List<String> 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);
}cleanUp函数就是删除apk文件。
private boolean cleanUp() {
if (codeFile == null || !codeFile.exists()) {
return false;
}
if (codeFile.isDirectory()) {
mInstaller.rmPackageDir(codeFile.getAbsolutePath());
} else {
codeFile.delete();
}
if (resourceFile != null && !FileUtils.contains(codeFile, resourceFile)) {
resourceFile.delete();
}
return true;
}
相关文章推荐
- Android应用管理四 -- APK包的安装、卸载和优化(PackageManagerService)
- Android6.0 PackageManagerService(PMS)-卸载
- Android Fk-PKMS(2) PackageManagerService之应用的安装与卸载
- Android5.1--APK包的安装、卸载和优化(PackageManagerService)(一)
- Android5.1--APK包的安装、卸载和优化(PackageManagerService)
- Android6.0 PackageManagerService(PMS)-安装
- Android5.1--APK包的安装、卸载和优化(PackageManagerService)(二)
- Android 系统启动时 PackageManagerService 对应用组件信息表的构建过程
- PackageManagerService(Android5.1)深入分析(三)扫描应用目录
- PackageManagerService——掌管APP的安装、卸载和查询
- Android应用框架之PackageManagerService
- Android L-preview PackageManagerService启动、安装和卸载分析
- PackageManagerService(Android5.1)深入分析(四)安装应用
- Android6.0 PackageManagerService 安装lib
- Android6.0 PackageManagerService(PMS)-简介
- Android6.0 PackageManagerService的mSettings、mPackages变量分析
- PackageManagerService源码分析之安装应用(四)
- Android5.1--APK包的安装、卸载和优化(PackageManagerService)(三)
- Android PackageManagerService分析三:卸载APK