Android PackageManagerService分析三:卸载APK

这一章我们介绍APK的卸载过程,从前一章分析安装APK的过程,我们应该大致了解这里的卸载的过程如下:

1.从PMS的内部结构上删除acitivity、service、provider等信息

2.删除code、library和resource等信息

3.调用installd删除/data/data/packageName以及/data/dalvik-cache下面的文件

4.更新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方法: public void deletePackageAsUser(final String packageName,final IPackageDeleteObserver observer,final int userId, final int flags) {mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES, null);final int uid = Binder.getCallingUid();if (isUserRestricted(userId, UserManager.DISALLOW_UNINSTALL_APPS)) {try {observer.packageDeleted(packageName, PackageManager.DELETE_FAILED_USER_RESTRICTED);} catch (RemoteException re) {}return;}mHandler.post(new Runnable() {public void run() {mHandler.removeCallbacks(this);final int returnCode = deletePackageX(packageName, userId, flags);if (observer != null) {try {observer.packageDeleted(packageName, returnCode);} catch (RemoteException e) {Log.i(TAG, "Observer no longer exists.");} //end catch} //end if} //end run});}

在deletePackageAsUser方法中,首先做权限检查,然后就调用deletePackageX方法去执行卸载任务:

private int deletePackageX(String packageName, int userId, int flags) {final PackageRemovedInfo info = new PackageRemovedInfo();final boolean res;boolean removedForAllUsers = false;boolean systemUpdate = false;int[] allUsers;boolean[] perUserInstalled;synchronized (mPackages) {PackageSetting ps = mSettings.mPackages.get(packageName);allUsers = sUserManager.getUserIds();perUserInstalled = new boolean[allUsers.length];for (int i = 0; i < allUsers.length; i++) {perUserInstalled[i] = ps != null ? ps.getInstalled(allUsers[i]) : false;}}synchronized (mInstallLock) {res = deletePackageLI(packageName,(flags & PackageManager.DELETE_ALL_USERS) != 0? UserHandle.ALL : new UserHandle(userId),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);}if (res) {info.sendBroadcast(true, systemUpdate, removedForAllUsers);}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的情况,来看deletePackageLI的实现: private boolean deletePackageLI(String packageName, UserHandle user,boolean deleteCodeAndResources, int[] allUserHandles, boolean[] perUserInstalled,int flags, PackageRemovedInfo outInfo,boolean writeSettings) {PackageSetting ps;boolean dataOnly = false;int removeUser = -1;int appId = -1;synchronized (mPackages) {ps = mSettings.mPackages.get(packageName);if (ps == null) {Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");return false;}if ((!isSystemApp(ps) || (flags&PackageManager.DELETE_SYSTEM_APP) != 0) && user != null&& user.getIdentifier() != UserHandle.USER_ALL) {ps.setUserState(user.getIdentifier(),COMPONENT_ENABLED_STATE_DEFAULT,false, //installedtrue, //stoppedtrue, //notLaunchedfalse, //blockednull, null, null);if (!isSystemApp(ps)) {if (ps.isAnyInstalled(sUserManager.getUserIds())) {} else {removeUser = user.getIdentifier();appId = ps.appId;mSettings.writePackageRestrictionsLPr(removeUser);}}}boolean ret = false;mSettings.mKeySetManager.removeAppKeySetData(packageName);if (isSystemApp(ps)) {ret = deleteSystemPackageLI(ps, allUserHandles, perUserInstalled,flags, outInfo, writeSettings);} else {// 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;}在deletePackageLI函数中根据是否是systemApp调用不同的流程,如果是systemApp,则调用deleteSystemPackageLI完成卸载;如果非systemApp,则调用deleteInstalledPackageLI完成卸载,当然在卸载之前,首先会调用AMS的killApplication方法先让这个APP停止运行。我们主要介绍非systemApp的卸载过程,来看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;}removePackageDataLI(ps, allUserHandles, perUserInstalled, outInfo, flags, writeSettings);if (deleteCodeAndResources && (outInfo != null)) {outInfo.args = createInstallArgs(packageFlagsToInstallFlags(ps), ps.codePathString,ps.resourcePathString, ps.nativeLibraryPathString);}return true;}在deleteInstalledPackageLI方法中,分为两步去卸载应用:第一步删除/data/data下面的数据目录,并从PMS的内部数据结构上清除当前卸载的package信息;第二步就删除code和resource文件。我们先来看第一步: private void removePackageDataLI(PackageSetting ps,int[] allUserHandles, boolean[] perUserInstalled,PackageRemovedInfo outInfo, int flags, boolean writeSettings) {String packageName = ps.name;removePackageLI(ps, (flags&REMOVE_CHATTY) != 0);final PackageSetting deletedPs;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(packageName);schedulePackageCleaning(packageName, UserHandle.USER_ALL, true);}你并不一定会从此拥有更美好的人生,

Android PackageManagerService分析三:卸载APK

相关文章:

你感兴趣的文章:

标签云: