Android PackageManagerService(五)卸载流程详解

从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主要顺序

  • destroyAppDataLeafLIF
  • destroyAppData
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。
 

你可能感兴趣的:(【Android系统】)