美文网首页
Android PackageInstaller/Package

Android PackageInstaller/Package

作者: 行走中的3卡 | 来源:发表于2023-04-07 23:39 被阅读0次

Android API33 为例,看看 installExistingPackageAsUser 的逻辑,
注意它传的参数 userIdpackageName

毫无疑问,肯定是在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

相关文章

网友评论

      本文标题:Android PackageInstaller/Package

      本文链接:https://www.haomeiwen.com/subject/bpycrdtx.html