Android PackageInstaller/Package
2023-04-07 本文已影响0人
行走中的3卡
Android API33 为例,看看 installExistingPackageAsUser 的逻辑,
注意它传的参数 userId 和 packageName。
毫无疑问,肯定是在PMS 里执行
package com.android.server.pm;
public class PackageManagerService implements PackageSender, TestUtilityService {
/**
* @hide
*/
@Override
public int installExistingPackageAsUser(String packageName, int userId, int installFlags,
int installReason, List<String> whiteListedPermissions) {
return mInstallPackageHelper.installExistingPackageAsUser(packageName, userId, installFlags,
installReason, whiteListedPermissions, null);
}
可以看出,实际上委托给 InstallPackageHelper 进行的
InstallPackageHelper .java里的逻辑
package com.android.server.pm;
final class InstallPackageHelper {
public int installExistingPackageAsUser(@Nullable String packageName, @UserIdInt int userId,
@PackageManager.InstallFlags int installFlags,
@PackageManager.InstallReason int installReason,
@Nullable List<String> allowlistedRestrictedPermissions,
@Nullable IntentSender intentSender) {
if (DEBUG_INSTALL) {
Log.v(TAG, "installExistingPackageAsUser package=" + packageName + " userId=" + userId
+ " installFlags=" + installFlags + " installReason=" + installReason
+ " allowlistedRestrictedPermissions=" + allowlistedRestrictedPermissions);
}
final int callingUid = Binder.getCallingUid();
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES)
!= PackageManager.PERMISSION_GRANTED
&& mContext.checkCallingOrSelfPermission(
android.Manifest.permission.INSTALL_EXISTING_PACKAGES)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Neither user " + callingUid + " nor current process has "
+ android.Manifest.permission.INSTALL_PACKAGES + ".");
}
PackageSetting pkgSetting;
final Computer preLockSnapshot = mPm.snapshotComputer();
preLockSnapshot.enforceCrossUserPermission(callingUid, userId,
true /* requireFullPermission */, true /* checkShell */,
"installExistingPackage for user " + userId);
if (mPm.isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
return PackageManager.INSTALL_FAILED_USER_RESTRICTED;
}
final long callingId = Binder.clearCallingIdentity();
try {
boolean installed = false;
final boolean instantApp =
(installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
final boolean fullApp =
(installFlags & PackageManager.INSTALL_FULL_APP) != 0;
// writer
synchronized (mPm.mLock) {
final Computer snapshot = mPm.snapshotComputer();
pkgSetting = mPm.mSettings.getPackageLPr(packageName);
if (pkgSetting == null) {
return PackageManager.INSTALL_FAILED_INVALID_URI;
}
if (!snapshot.canViewInstantApps(callingUid, UserHandle.getUserId(callingUid))) {
// only allow the existing package to be used if it's installed as a full
// application for at least one user
boolean installAllowed = false;
for (int checkUserId : mPm.mUserManager.getUserIds()) {
installAllowed = !pkgSetting.getInstantApp(checkUserId);
if (installAllowed) {
break;
}
}
if (!installAllowed) {
return PackageManager.INSTALL_FAILED_INVALID_URI;
}
}
if (!pkgSetting.getInstalled(userId)) {
pkgSetting.setInstalled(true, userId);
pkgSetting.setHidden(false, userId);
pkgSetting.setInstallReason(installReason, userId);
pkgSetting.setUninstallReason(PackageManager.UNINSTALL_REASON_UNKNOWN, userId);
pkgSetting.setFirstInstallTime(System.currentTimeMillis(), userId);
mPm.mSettings.writePackageRestrictionsLPr(userId);
mPm.mSettings.writeKernelMappingLPr(pkgSetting);
installed = true;
} else if (fullApp && pkgSetting.getInstantApp(userId)) {
// upgrade app from instant to full; we don't allow app downgrade
installed = true;
}
ScanPackageUtils.setInstantAppForUser(mPm.mInjector, pkgSetting, userId, instantApp,
fullApp);
}
if (installed) {
if (pkgSetting.getPkg() != null) {
final PermissionManagerServiceInternal.PackageInstalledParams.Builder
permissionParamsBuilder =
new PermissionManagerServiceInternal.PackageInstalledParams.Builder();
if ((installFlags & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS)
!= 0) {
permissionParamsBuilder.setAllowlistedRestrictedPermissions(
pkgSetting.getPkg().getRequestedPermissions());
}
mPm.mPermissionManager.onPackageInstalled(pkgSetting.getPkg(),
Process.INVALID_UID /* previousAppId */,
permissionParamsBuilder.build(), userId);
synchronized (mPm.mInstallLock) {
// We don't need to freeze for a brand new install
mAppDataHelper.prepareAppDataAfterInstallLIF(pkgSetting.getPkg());
}
}
mPm.sendPackageAddedForUser(mPm.snapshotComputer(), packageName, pkgSetting, userId,
DataLoaderType.NONE);
synchronized (mPm.mLock) {
mPm.updateSequenceNumberLP(pkgSetting, new int[]{ userId });
}
// start async restore with no post-install since we finish install here
PackageInstalledInfo res = new PackageInstalledInfo(
PackageManager.INSTALL_SUCCEEDED);
res.mPkg = pkgSetting.getPkg();
res.mNewUsers = new int[]{ userId };
PostInstallData postInstallData =
new PostInstallData(null, res, () -> {
mPm.restorePermissionsAndUpdateRolesForNewUserInstall(packageName,
userId);
if (intentSender != null) {
onRestoreComplete(res.mReturnCode, mContext, intentSender);
}
});
restoreAndPostInstall(userId, res, postInstallData);
}
} finally {
Binder.restoreCallingIdentity(callingId);
}
return PackageManager.INSTALL_SUCCEEDED;
这里注意一下这个pkgSetting,它是通过 packageName进行获取到的。
pkgSetting = mPm.mSettings.getPackageLPr(packageName);
可以猜测到,不同的用户(userId) 可以使用 主用户 的应用包 进行安装,
并且 共用同一个 pkgSetting ,在另一个用户安装后,设置:
pkgSetting.setInstalled(true, userId);
pkgSetting.setHidden(false, userId);
参考文献:
http://liuwangshu.cn/framework/pms/1-packageinstaller-initialize.html
https://www.jianshu.com/p/e41fb7081a76