主页 > 游戏开发  > 

Android15am命令APP安装流程

Android15am命令APP安装流程
一. PM 安装命令

使用命令

pm install -r    xxx.apk

 pm命令安装app 会触发PackageManagerShellCommand 中runInstall()方法

frameworks/base/services/core/java/com/android/server/pm/PackageManagerShellCommand.java

1. onCommand 函数:

    public int onCommand(String cmd) {         if (cmd == null) {             return handleDefaultCommands(cmd);         }

        final PrintWriter pw = getOutPrintWriter();         try {             switch (cmd) {

                case "install":                     return runInstall();

}

2. runInstall 函数:

    private int runInstall() throws RemoteException {

        //UNSUPPORTED_INSTALL_CMD_OPTS 就是参数:Set.of( "--multi-package");

        //相当于isMultiPackage 为true         return doRunInstall(makeInstallParams(UNSUPPORTED_INSTALL_CMD_OPTS));     }

3. makeInstallParams 函数:

解析参数:

    private InstallParams makeInstallParams(Set<String> unsupportedOptions) {

        // MODE_FULL_INSTALL:安装会话的模式,其暂存的 APK 应该完全替换目标应用的任何现有 APK。         final SessionParams sessionParams = new SessionParams(SessionParams.MODE_FULL_INSTALL);

        final InstallParams params = new InstallParams();

        params.sessionParams = sessionParams;         // Allowlist all permissions by default         sessionParams.installFlags |= PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;         // Set package source to other by default. Can be overridden by "--package-source"

       // 默认将包源设置为其他。可以通过“--package-source”覆盖         sessionParams.setPackageSource(PackageInstaller.PACKAGE_SOURCE_OTHER);

        // Encodes one of the states:         //  1. Install request explicitly specified --staged, then value will be true.         //  2. Install request explicitly specified --non-staged, then value will be false.         //  3. Install request did not specify either --staged or --non-staged, then for APEX         //      installs the value will be true, and for apk installs it will be false.

        // 对以下状态之一进行编码:         //  1. 安装请求明确指定 --staged,则值为 true。         //  2. 安装请求明确指定 --non-staged,则值为 false。         //  3. 安装请求未指定 --staged 或 --non-staged,则对于 APEX         //      安装,则值为 true,对于 apk 安装,则值为 false。         Boolean staged = null;

        String opt;         boolean replaceExisting = true;         boolean forceNonStaged = false;         while ((opt = getNextOption()) != null) {             if (unsupportedOptions.contains(opt)) {                 throw new IllegalArgumentException("Unsupported option " + opt);             }             switch (opt) {                 case "-r": // ignore                     break;                 case "-R":                     replaceExisting = false;                     break;                 case "-i":                     params.installerPackageName = getNextArg();                     if (params.installerPackageName == null) {                         throw new IllegalArgumentException("Missing installer package");                     }                     break;                 case "-t":                     sessionParams.installFlags |= PackageManager.INSTALL_ALLOW_TEST;                     break;                 case "-f":                     sessionParams.installFlags |= PackageManager.INSTALL_INTERNAL;                     break;                 case "-d":                     sessionParams.installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;                     break;                 case "-g":                     sessionParams.installFlags |=                             PackageManager.INSTALL_GRANT_ALL_REQUESTED_PERMISSIONS;                     break;                 case "--restrict-permissions":                     sessionParams.installFlags &=                             ~PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;                     break;                 case "--dont-kill":                     sessionParams.installFlags |= PackageManager.INSTALL_DONT_KILL_APP;                     break;                 case "--originating-uri":                     sessionParams.originatingUri = Uri.parse(getNextArg());                     break;                 case "--referrer":                     sessionParams.referrerUri = Uri.parse(getNextArg());                     break;                 case "-p":                     sessionParams.mode = SessionParams.MODE_INHERIT_EXISTING;                     sessionParams.appPackageName = getNextArg();                     if (sessionParams.appPackageName == null) {                         throw new IllegalArgumentException("Missing inherit package name");                     }                     break;                 case "--pkg":                     sessionParams.appPackageName = getNextArg();                     if (sessionParams.appPackageName == null) {                         throw new IllegalArgumentException("Missing package name");                     }                     break;                 case "-S":                     final long sizeBytes = Long.parseLong(getNextArg());                     if (sizeBytes <= 0) {                         throw new IllegalArgumentException("Size must be positive");                     }                     sessionParams.setSize(sizeBytes);                     break;                 case "--abi":                     sessionParams.abiOverride = checkAbiArgument(getNextArg());                     break;                 case "--ephemeral":                 case "--instant":                 case "--instantapp":                     sessionParams.setInstallAsInstantApp(true /*isInstantApp*/);                     break;                 case "--full":                     sessionParams.setInstallAsInstantApp(false /*isInstantApp*/);                     break;                 case "--preload":                     sessionParams.setInstallAsVirtualPreload();                     break;                 case "--user":                     params.userId = UserHandle.parseUserArg(getNextArgRequired());                     break;                 case "--install-location":                     sessionParams.installLocation = Integer.parseInt(getNextArg());                     break;                 case "--install-reason":                     sessionParams.installReason = Integer.parseInt(getNextArg());                     break;                 case "--update-ownership":                     if (params.installerPackageName == null) {                         // Enabling update ownership enforcement needs an installer. Since the                         // default installer is null when using adb install, that effectively                         // disable this enforcement.                         params.installerPackageName = "com.android.shell";                     }                     sessionParams.installFlags |= PackageManager.INSTALL_REQUEST_UPDATE_OWNERSHIP;                     break;                 case "--force-uuid":                     sessionParams.installFlags |= PackageManager.INSTALL_FORCE_VOLUME_UUID;                     sessionParams.volumeUuid = getNextArg();                     if ("internal".equals(sessionParams.volumeUuid)) {                         sessionParams.volumeUuid = null;                     }                     break;                 case "--force-sdk": // ignore                     break;                 case "--apex":                     sessionParams.setInstallAsApex();                     break;                 case "--force-non-staged":                     forceNonStaged = true;                     break;                 case "--multi-package":                     sessionParams.setMultiPackage();                     break;                 case "--staged":                     staged = true;                     break;                 case "--non-staged":                     staged = false;                     break;                 case "--force-queryable":                     sessionParams.setForceQueryable();                     break;                 case "--enable-rollback":                     if (params.installerPackageName == null) {                         // com.android.shell has the TEST_MANAGE_ROLLBACKS                         // permission needed to enable rollback for non-module                         // packages, which is likely what the user wants when                         // enabling rollback through the shell command. Set                         // the installer to com.android.shell if no installer                         // has been provided so that the user doesn't have to                         // remember to set it themselves.                         params.installerPackageName = "com.android.shell";                     }                     int rollbackStrategy = PackageManager.ROLLBACK_DATA_POLICY_RESTORE;                     try {                         rollbackStrategy = Integer.parseInt(peekNextArg());                         if (rollbackStrategy < PackageManager.ROLLBACK_DATA_POLICY_RESTORE                                 || rollbackStrategy > PackageManager.ROLLBACK_DATA_POLICY_RETAIN) {                             throw new IllegalArgumentException(                                     rollbackStrategy + " is not a valid rollback data policy.");                         }                         getNextArg(); // pop the argument                     } catch (NumberFormatException e) {                         // not followed by a number assume ROLLBACK_DATA_POLICY_RESTORE.                     }                     sessionParams.setEnableRollback(true, rollbackStrategy);                     break;                 case "--rollback-impact-level":                     if (!Flags.recoverabilityDetection()) {                         throw new IllegalArgumentException("Unknown option " + opt);                     }                     int rollbackImpactLevel = Integer.parseInt(peekNextArg());                     if (rollbackImpactLevel < PackageManager.ROLLBACK_USER_IMPACT_LOW                             || rollbackImpactLevel                                     > PackageManager.ROLLBACK_USER_IMPACT_ONLY_MANUAL) {                         throw new IllegalArgumentException(                             rollbackImpactLevel + " is not a valid rollback impact level.");                     }                     sessionParams.setRollbackImpactLevel(rollbackImpactLevel);                 case "--staged-ready-timeout":                     params.stagedReadyTimeoutMs = Long.parseLong(getNextArgRequired());                     break;                 case "--skip-verification":                     sessionParams.installFlags |= PackageManager.INSTALL_DISABLE_VERIFICATION;                     break;                 case "--skip-enable":                     sessionParams.setApplicationEnabledSettingPersistent();                     break;                 case "--bypass-low-target-sdk-block":                     sessionParams.installFlags |=                             PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK;                     break;                 case "--ignore-dexopt-profile":                     sessionParams.installFlags |= PackageManager.INSTALL_IGNORE_DEXOPT_PROFILE;                     break;                 case "--package-source":                     sessionParams.setPackageSource(Integer.parseInt(getNextArg()));                     break;                 case "--dexopt-compiler-filter":                     sessionParams.dexoptCompilerFilter = getNextArgRequired();                     // An early check that throws IllegalArgumentException if the compiler filter is                     // invalid.                     new DexoptParams.Builder(ReasonMapping.REASON_INSTALL)                             .setCompilerFilter(sessionParams.dexoptCompilerFilter)                             .build();                     break;                 default:                     throw new IllegalArgumentException("Unknown option " + opt);             }         }         if (staged == null) {             staged = (sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0;         }         if (replaceExisting) {             sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;         }         if (forceNonStaged) {             sessionParams.isStaged = false;             sessionParams.developmentInstallFlags |=                     PackageManager.INSTALL_DEVELOPMENT_FORCE_NON_STAGED_APEX_UPDATE;         } else if (staged) {             sessionParams.setStaged();         }         if ((sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0                 && (sessionParams.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0                 && sessionParams.rollbackDataPolicy == PackageManager.ROLLBACK_DATA_POLICY_WIPE) {             throw new IllegalArgumentException("Data policy 'wipe' is not supported for apex.");         }         return params;     }

 4. doRunInstall 函数:

    private int doRunInstall(final InstallParams params) throws RemoteException {         final PrintWriter pw = getOutPrintWriter();

        // 默认为:UserHandle.USER_ALL

        int requestUserId = params.userId;         if (requestUserId != UserHandle.USER_ALL && requestUserId != UserHandle.USER_CURRENT) {             UserManagerInternal umi =                     LocalServices.getService(UserManagerInternal.class);             UserInfo userInfo = umi.getUserInfo(requestUserId);             if (userInfo == null) {                 pw.println("Failure [user " + requestUserId + " doesn't exist]");                 return 1;             }         }

        final boolean isStreaming = params.sessionParams.dataLoaderParams != null;         final boolean isApex =                 (params.sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0;         final boolean installArchived =                 (params.sessionParams.installFlags & PackageManager.INSTALL_ARCHIVED) != 0;

       // 将剩余的参数变成集合.

        ArrayList<String> args = getRemainingArgs();

        final boolean fromStdIn = args.isEmpty() || STDIN_PATH.equals(args.get(0));         final boolean hasSplits = args.size() > 1;

        if (fromStdIn && params.sessionParams.sizeBytes == -1) {             pw.println("Error: must either specify a package size or an APK file");             return 1;         }

        //默认情况下都不会满足

        if (isApex && hasSplits) {             pw.println("Error: can't specify SPLIT(s) for APEX");             return 1;         }

        //默认情况下都不会满足

        if (installArchived) {             if (hasSplits) {                 pw.println("Error: can't have SPLIT(s) for Archival install");                 return 1;             }         }

        if (!isStreaming) {             if (fromStdIn && hasSplits) {                 pw.println("Error: can't specify SPLIT(s) along with STDIN");                 return 1;             }

            if (args.isEmpty()) {                 args.add(STDIN_PATH);             } else {

               //默认会设置参数的大小.                 setParamsSize(params, args);             }         }

        //创建session

        final int sessionId = doCreateSession(params.sessionParams,                 params.installerPackageName, params.userId);         boolean abandonSession = true;         try {             if (isStreaming) {                 if (doAddFiles(sessionId, args, params.sessionParams.sizeBytes, isApex,                         installArchived) != PackageInstaller.STATUS_SUCCESS) {                     return 1;                 }             } else {                 if (doWriteSplits(sessionId, args, params.sessionParams.sizeBytes, isApex)                         != PackageInstaller.STATUS_SUCCESS) {                     return 1;                 }             }

            //安装应用开发.             if (doCommitSession(sessionId, false /*logSuccess*/)                     != PackageInstaller.STATUS_SUCCESS) {                 return 1;             }             abandonSession = false;

            if (params.sessionParams.isStaged && params.stagedReadyTimeoutMs > 0) {                 return doWaitForStagedSessionReady(sessionId, params.stagedReadyTimeoutMs, pw);             }

            pw.println("Success");             return 0;         } finally {             if (abandonSession) {                 try {                     doAbandonSession(sessionId, false /*logSuccess*/);                 } catch (Exception ignore) {                 }             }         }     }

 5. setParamsSize 函数:

    private void setParamsSize(InstallParams params, List<String> inPaths) {         if (params.sessionParams.sizeBytes != -1 || STDIN_PATH.equals(inPaths.get(0))) {             return;         }

        long sessionSize = 0;

        ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();         for (String inPath : inPaths) {

            // 获取到apk的路径             final ParcelFileDescriptor fd = openFileForSystem(inPath, "r");             if (fd == null) {                 getErrPrintWriter().println("Error: Can't open file: " + inPath);                 throw new IllegalArgumentException("Error: Can't open file: " + inPath);             }             try {

               //解析此apk内容。                 ParseResult<ApkLite> apkLiteResult = ApkLiteParseUtils.parseApkLite(                         input.reset(), fd.getFileDescriptor(), inPath, 0);                 if (apkLiteResult.isError()) {

                   //解析失败,报异常。                     throw new IllegalArgumentException(                             "Error: Failed to parse APK file: " + inPath + ": "                                     + apkLiteResult.getErrorMessage(),                             apkLiteResult.getException());                 }

                //获取到ApkLite 对象                 final ApkLite apkLite = apkLiteResult.getResult();                 final PackageLite pkgLite = new PackageLite(null, apkLite.getPath(), apkLite,                         null /* splitNames */, null /* isFeatureSplits */,                         null /* usesSplitNames */, null /* configForSplit */,                         null /* splitApkPaths */, null /* splitRevisionCodes */,                         apkLite.getTargetSdkVersion(), null /* requiredSplitTypes */,                         null /* splitTypes */);

                 //计算安装文件大小。                 sessionSize += InstallLocationUtils.calculateInstalledSize(pkgLite,                         params.sessionParams.abiOverride, fd.getFileDescriptor());             } catch (IOException e) {                 getErrPrintWriter().println("Error: Failed to parse APK file: " + inPath);                 throw new IllegalArgumentException(                         "Error: Failed to parse APK file: " + inPath, e);             } finally {                 try {                     fd.close();                 } catch (IOException e) {                 }             }         }

        //将计算文件大小存入。

        params.sessionParams.setSize(sessionSize);     }

6. openFileForSystem 函数:

    /**      * Helper for just system services to ask the shell to open an output file.      * @hide      */     public ParcelFileDescriptor openFileForSystem(String path, String mode) {         if (DEBUG) Slog.d(TAG, "openFileForSystem: " + path + " mode=" + mode);         try {

           //获取文件,并且具有可打开的权限。             ParcelFileDescriptor pfd = getShellCallback().openFile(path,                     "u:r:system_server:s0", mode);             if (pfd != null) {                 if (DEBUG) Slog.d(TAG, "Got file: " + pfd);

                //获取到此文件                 return pfd;             }         } catch (RuntimeException e) {             if (DEBUG) Slog.d(TAG, "Failure opening file: " + e.getMessage());             getErrPrintWriter().println("Failure opening file: " + e.getMessage());         }         if (DEBUG) Slog.d(TAG, "Error: Unable to open file: " + path);

         //否则就获取不到文件.         getErrPrintWriter().println("Error: Unable to open file: " + path);

        String suggestedPath = "/data/local/tmp/";         if (path == null || !path.startsWith(suggestedPath)) {             getErrPrintWriter().println("Consider using a file under " + suggestedPath);         }         return null;     }

 7. doCreateSession 函数:

    private int doCreateSession(SessionParams params, String installerPackageName, int userId)             throws RemoteException {

        //默认是USER_ALL         if (userId == UserHandle.USER_ALL) {             params.installFlags |= PackageManager.INSTALL_ALL_USERS;         }         final int translatedUserId =                 translateUserId(userId, UserHandle.USER_SYSTEM, "doCreateSession");

       // 创建createSession         final int sessionId = mInterface.getPackageInstaller()                 .createSession(params, installerPackageName, null /*installerAttributionTag*/,                         translatedUserId);         return sessionId;     }

8. createSession 函数:

frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java 

    @Override     public int createSession(SessionParams params, String installerPackageName,             String callingAttributionTag, int userId) {         try {             if (params.dataLoaderParams != null                     && mContext.checkCallingOrSelfPermission(Manifest.permission.USE_INSTALLER_V2)                     != PackageManager.PERMISSION_GRANTED) {                 throw new SecurityException("You need the "                         + "com.android.permission.USE_INSTALLER_V2 permission "                         + "to use a data loader");             }

            // Draft sessions cannot be created through the public API.             params.installFlags &= ~PackageManager.INSTALL_UNARCHIVE_DRAFT;             return createSessionInternal(params, installerPackageName, callingAttributionTag,                     Binder.getCallingUid(), userId);         } catch (IOException e) {             throw ExceptionUtils.wrap(e);         }     }

9. createSessionInternal 函数:

    int createSessionInternal(SessionParams params, String installerPackageName,             String installerAttributionTag, int callingUid, int userId)             throws IOException {         final Computer snapshot = mPm.snapshotComputer();         snapshot.enforceCrossUserPermission(callingUid, userId, true, true, "createSession");

        if (mPm.isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {

            // 若包含DISALLOW_INSTALL_APPS, 说明是禁止安装,则直接报错。             throw new SecurityException("User restriction prevents installing");         }

        // INSTALL_REASON_ROLLBACK allows an app to be rolled back without requiring the ROLLBACK         // capability; ensure if this is set as the install reason the app has one of the necessary         // signature permissions to perform the rollback.         if (params.installReason == PackageManager.INSTALL_REASON_ROLLBACK) {

         //安装原因是INSTALL_REASON_ROLLBACK             if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_ROLLBACKS)                     != PackageManager.PERMISSION_GRANTED &&                     mContext.checkCallingOrSelfPermission(Manifest.permission.TEST_MANAGE_ROLLBACKS)                     != PackageManager.PERMISSION_GRANTED) {

                //若没有授权,直接抛出异常。                 throw new SecurityException(                         "INSTALL_REASON_ROLLBACK requires the MANAGE_ROLLBACKS permission or the "                                 + "TEST_MANAGE_ROLLBACKS permission");             }         }

        // App package name and label length is restricted so that really long strings aren't         // written to disk.         if (params.appPackageName != null && !isValidPackageName(params.appPackageName)) {

            //若包名是无效的,直接将包名设置为null.             params.appPackageName = null;         }

        params.appLabel = TextUtils.trimToSize(params.appLabel,                 PackageItemInfo.MAX_SAFE_LABEL_LENGTH);

        // Validate requested installer package name.         if (params.installerPackageName != null && !isValidPackageName(                 params.installerPackageName)) {

           // 若安装包名是无效的,直接直接设置为null             params.installerPackageName = null;         }

        // Validate installer package name.         if (installerPackageName != null && !isValidPackageName(installerPackageName)) {             installerPackageName = null;         }

        String requestedInstallerPackageName =                 params.installerPackageName != null ? params.installerPackageName                         : installerPackageName;

        if (PackageManagerServiceUtils.isRootOrShell(callingUid)                 || PackageInstallerSession.isSystemDataLoaderInstallation(params)                 || PackageManagerServiceUtils.isAdoptedShell(callingUid, mContext)) {             params.installFlags |= PackageManager.INSTALL_FROM_ADB;             // adb installs can override the installingPackageName, but not the             // initiatingPackageName

           //安装来源于adb             installerPackageName = SHELL_PACKAGE_NAME;         } else {             if (callingUid != SYSTEM_UID) {                 // The supplied installerPackageName must always belong to the calling app.

                //若调用者不是system,则要检查权限。                 mAppOps.checkPackage(callingUid, installerPackageName);             }             // Only apps with INSTALL_PACKAGES are allowed to set an installer that is not the             // caller.             if (!TextUtils.equals(requestedInstallerPackageName, installerPackageName)) {                 if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES)                         != PackageManager.PERMISSION_GRANTED) {

                    // 若请求安装包名和安装包名不一致,

                    // 需要判断是否有INSTALL_PACKAGES权限,若没有的话,进行权限检查。                     mAppOps.checkPackage(callingUid, requestedInstallerPackageName);                 }             }

           //移除 FLAG:INSTALL_FROM_ADB,INSTALL_ALL_USERS,INSTALL_ARCHIVED

            params.installFlags &= ~PackageManager.INSTALL_FROM_ADB;             params.installFlags &= ~PackageManager.INSTALL_ALL_USERS;             params.installFlags &= ~PackageManager.INSTALL_ARCHIVED;

            //增加flag:INSTALL_REPLACE_EXISTING             params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;             if ((params.installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0                     && !mPm.isCallerVerifier(snapshot, callingUid)) {                 params.installFlags &= ~PackageManager.INSTALL_VIRTUAL_PRELOAD;             }             if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_TEST_ONLY_PACKAGE)                     != PackageManager.PERMISSION_GRANTED) {                 params.installFlags &= ~PackageManager.INSTALL_ALLOW_TEST;             }

            // developmentInstallFlags can ony be set by shell or root.             params.developmentInstallFlags = 0;         }

        String originatingPackageName = null;         if (params.originatingUid != SessionParams.UID_UNKNOWN                 && params.originatingUid != callingUid) {             String[] packages = snapshot.getPackagesForUid(params.originatingUid);             if (packages != null && packages.length > 0) {                 // Choose an arbitrary representative package in the case of a shared UID.                 originatingPackageName = packages[0];             }         }

        if (Build.IS_DEBUGGABLE || PackageManagerServiceUtils.isSystemOrRoot(callingUid)) {             params.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;         } else {             params.installFlags &= ~PackageManager.INSTALL_ALLOW_DOWNGRADE;         }

        if (mDisableVerificationForUid != INVALID_UID) {             if (callingUid == mDisableVerificationForUid) {                 params.installFlags |= PackageManager.INSTALL_DISABLE_VERIFICATION;             } else {                 // Clear the flag if current calling uid doesn't match the requested uid.                 params.installFlags &= ~PackageManager.INSTALL_DISABLE_VERIFICATION;             }             // Reset the field as this is a one-off request.             mDisableVerificationForUid = INVALID_UID;         } else if ((params.installFlags & ADB_DEV_MODE) != ADB_DEV_MODE) {             // Only tools under specific conditions (test app installed through ADB, and             // verification disabled flag specified) can disable verification.             params.installFlags &= ~PackageManager.INSTALL_DISABLE_VERIFICATION;         }

        if (Flags.rollbackLifetime()) {             if (params.rollbackLifetimeMillis > 0) {                 if ((params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) {                     throw new IllegalArgumentException(                             "Can't set rollbackLifetimeMillis when rollback is not enabled");                 }                 if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_ROLLBACKS)                         != PackageManager.PERMISSION_GRANTED) {                     throw new SecurityException(                             "Setting rollback lifetime requires the MANAGE_ROLLBACKS permission");                 }             } else if (params.rollbackLifetimeMillis < 0) {                 throw new IllegalArgumentException("rollbackLifetimeMillis can't be negative.");             }         }

        if (Flags.recoverabilityDetection()) {             if (params.rollbackImpactLevel == PackageManager.ROLLBACK_USER_IMPACT_HIGH                     || params.rollbackImpactLevel                     == PackageManager.ROLLBACK_USER_IMPACT_ONLY_MANUAL) {                 if ((params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) {                     throw new IllegalArgumentException(                             "Can't set rollbackImpactLevel when rollback is not enabled");                 }                 if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_ROLLBACKS)                         != PackageManager.PERMISSION_GRANTED) {                     throw new SecurityException(                             "Setting rollbackImpactLevel requires the MANAGE_ROLLBACKS permission");                 }             } else if (params.rollbackImpactLevel < 0) {                 throw new IllegalArgumentException("rollbackImpactLevel can't be negative.");             }         }

        boolean isApex = (params.installFlags & PackageManager.INSTALL_APEX) != 0;         if (isApex) {             if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGE_UPDATES)                     == PackageManager.PERMISSION_DENIED                     && mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES)                     == PackageManager.PERMISSION_DENIED) {                 throw new SecurityException("Not allowed to perform APEX updates");             }         } else if (params.isStaged) {             mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, TAG);         }

        if (isApex) {             if (!mApexManager.isApexSupported()) {                 throw new IllegalArgumentException(                     "This device doesn't support the installation of APEX files");             }             if (params.isMultiPackage) {                 throw new IllegalArgumentException("A multi-session can't be set as APEX.");             }             if (PackageManagerServiceUtils.isSystemOrRootOrShell(callingUid)                     || mBypassNextAllowedApexUpdateCheck) {                 params.installFlags |= PackageManager.INSTALL_DISABLE_ALLOWED_APEX_UPDATE_CHECK;             } else {                 // Only specific APEX updates (installed through ADB, or for CTS tests) can disable                 // allowed APEX update check.                 params.installFlags &= ~PackageManager.INSTALL_DISABLE_ALLOWED_APEX_UPDATE_CHECK;             }         }

        if ((params.installFlags & PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK) != 0                 && !PackageManagerServiceUtils.isSystemOrRootOrShell(callingUid)                 && !Build.IS_DEBUGGABLE                 && !PackageManagerServiceUtils.isAdoptedShell(callingUid, mContext)) {             // If the bypass flag is set, but not running as system root or shell then remove             // the flag             params.installFlags &= ~PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK;         }

        params.installFlags &= ~PackageManager.INSTALL_UNARCHIVE;         if (isArchivingEnabled() && params.appPackageName != null) {             PackageStateInternal ps = mPm.snapshotComputer().getPackageStateInternal(                     params.appPackageName, SYSTEM_UID);             if (ps != null                     && PackageArchiver.isArchived(ps.getUserStateOrDefault(userId))                     && PackageArchiver.getResponsibleInstallerPackage(ps)                             .equals(requestedInstallerPackageName)) {                 params.installFlags |= PackageManager.INSTALL_UNARCHIVE;             }         }

        if ((params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0                 && !PackageManagerServiceUtils.isSystemOrRootOrShell(callingUid)                 && (snapshot.getFlagsForUid(callingUid) & ApplicationInfo.FLAG_SYSTEM)                 == 0) {             throw new SecurityException(                     "Only system apps could use the PackageManager.INSTALL_INSTANT_APP flag.");         }

        if (params.isStaged && !PackageManagerServiceUtils.isSystemOrRootOrShell(callingUid)) {             if (!mBypassNextStagedInstallerCheck                     && !isStagedInstallerAllowed(requestedInstallerPackageName)) {                 throw new SecurityException("Installer not allowed to commit staged install");             }         }         if (isApex && !PackageManagerServiceUtils.isSystemOrRootOrShell(callingUid)) {             if (!mBypassNextStagedInstallerCheck                     && !isStagedInstallerAllowed(requestedInstallerPackageName)) {                 throw new SecurityException(                         "Installer not allowed to commit non-staged APEX install");             }         }

        mBypassNextStagedInstallerCheck = false;         mBypassNextAllowedApexUpdateCheck = false;

        if (!params.isMultiPackage) {             var hasInstallGrantRuntimePermissions = mContext.checkCallingOrSelfPermission(                     Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS)                     == PackageManager.PERMISSION_GRANTED;

            // Only system components can circumvent runtime permissions when installing.             if ((params.installFlags & PackageManager.INSTALL_GRANT_ALL_REQUESTED_PERMISSIONS) != 0                     && !hasInstallGrantRuntimePermissions) {                 throw new SecurityException("You need the "                         + Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS                         + " permission to use the"                         + " PackageManager.INSTALL_GRANT_ALL_REQUESTED_PERMISSIONS flag");             }

            var permissionStates = params.getPermissionStates();             if (!permissionStates.isEmpty()) {                 if (!hasInstallGrantRuntimePermissions) {                     for (int index = 0; index < permissionStates.size(); index++) {                         var permissionName = permissionStates.keyAt(index);                         if (!INSTALLER_CHANGEABLE_APP_OP_PERMISSIONS.contains(permissionName)) {                             throw new SecurityException("You need the "                                     + Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS                                     + " permission to grant runtime permissions for a session");                         }                     }                 }             }

            // Defensively resize giant app icons             if (params.appIcon != null) {                 final ActivityManager am = (ActivityManager) mContext.getSystemService(                         Context.ACTIVITY_SERVICE);                 final int iconSize = am.getLauncherLargeIconSize();                 if ((params.appIcon.getWidth() > iconSize * 2)                         || (params.appIcon.getHeight() > iconSize * 2)) {                     params.appIcon = Bitmap.createScaledBitmap(params.appIcon, iconSize, iconSize,                             true);                 }             }

            switch (params.mode) {                 case SessionParams.MODE_FULL_INSTALL:                 case SessionParams.MODE_INHERIT_EXISTING:                     break;                 default:                     throw new IllegalArgumentException("Invalid install mode: " + params.mode);             }

            // If caller requested explicit location, validity check it, otherwise             // resolve the best internal or adopted location.             if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {                 if (!InstallLocationUtils.fitsOnInternal(mContext, params)) {                     throw new IOException("No suitable internal storage available");                 }             } else if ((params.installFlags & PackageManager.INSTALL_FORCE_VOLUME_UUID) != 0) {                 // For now, installs to adopted media are treated as internal from                 // an install flag point-of-view.                 params.installFlags |= PackageManager.INSTALL_INTERNAL;             } else {                 params.installFlags |= PackageManager.INSTALL_INTERNAL;

                // Resolve best location for install, based on combination of                 // requested install flags, delta size, and manifest settings.                 final long ident = Binder.clearCallingIdentity();                 try {                     params.volumeUuid = InstallLocationUtils.resolveInstallVolume(mContext, params);                 } finally {                     Binder.restoreCallingIdentity(ident);                 }             }         }

        int requestedInstallerPackageUid = INVALID_UID;         if (requestedInstallerPackageName != null) {             requestedInstallerPackageUid = snapshot.getPackageUid(requestedInstallerPackageName,                     0 /* flags */, userId);         }         if (requestedInstallerPackageUid == INVALID_UID) {             // Requested installer package is invalid, reset it             requestedInstallerPackageName = null;         }

        final int sessionId;         final PackageInstallerSession session;         synchronized (mSessions) {             // Check that the installer does not have too many active sessions.             final int activeCount = getSessionCount(mSessions, callingUid);             if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES)                     == PackageManager.PERMISSION_GRANTED) {                 if (activeCount >= MAX_ACTIVE_SESSIONS_WITH_PERMISSION) {                     throw new IllegalStateException(                             "Too many active sessions for UID " + callingUid);                 }             } else if (activeCount >= MAX_ACTIVE_SESSIONS_NO_PERMISSION) {                 throw new IllegalStateException(                         "Too many active sessions for UID " + callingUid);             }             final int historicalCount = mHistoricalSessionsByInstaller.get(callingUid);             if (historicalCount >= MAX_HISTORICAL_SESSIONS) {                 throw new IllegalStateException(                         "Too many historical sessions for UID " + callingUid);             }             final int existingDraftSessionId =                     getExistingDraftSessionId(requestedInstallerPackageUid, params, userId);

            sessionId = existingDraftSessionId != SessionInfo.INVALID_ID ? existingDraftSessionId                     : allocateSessionIdLocked();         }

        final long createdMillis = System.currentTimeMillis();         // We're staging to exactly one location         File stageDir = null;         String stageCid = null;         if (!params.isMultiPackage) {             if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {                 stageDir = buildSessionDir(sessionId, params);             } else {                 stageCid = buildExternalStageCid(sessionId);             }         }

        // reset the force queryable param if it's not called by an approved caller.         if (params.forceQueryableOverride) {             if (!PackageManagerServiceUtils.isRootOrShell(callingUid)) {                 params.forceQueryableOverride = false;             }         }

        final var dpmi = LocalServices.getService(DevicePolicyManagerInternal.class);         if (dpmi != null && dpmi.isUserOrganizationManaged(userId)) {             params.installFlags |= PackageManager.INSTALL_FROM_MANAGED_USER_OR_PROFILE;         }

        if (isApex || mContext.checkCallingOrSelfPermission(                 Manifest.permission.ENFORCE_UPDATE_OWNERSHIP) == PackageManager.PERMISSION_DENIED) {             params.installFlags &= ~PackageManager.INSTALL_REQUEST_UPDATE_OWNERSHIP;         }

        InstallSource installSource = InstallSource.create(installerPackageName,                 originatingPackageName, requestedInstallerPackageName, requestedInstallerPackageUid,                 requestedInstallerPackageName, installerAttributionTag, params.packageSource);         session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this,                 mSilentUpdatePolicy, mInstallThread.getLooper(), mStagingManager, sessionId,                 userId, callingUid, installSource, params, createdMillis, 0L, stageDir, stageCid,                 null, null, false, false, false, false, null, SessionInfo.INVALID_ID,                 false, false, false, PackageManager.INSTALL_UNKNOWN, "", null);

        synchronized (mSessions) {             mSessions.put(sessionId, session);         }         mPm.addInstallerPackageName(session.getInstallSource());

        mCallbacks.notifySessionCreated(session.sessionId, session.userId);

        mSettingsWriteRequest.schedule();         if (LOGD) {             Slog.d(TAG, "Created session id=" + sessionId + " staged=" + params.isStaged);         }         return sessionId;     }

标签:

Android15am命令APP安装流程由讯客互联游戏开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Android15am命令APP安装流程

上一篇

下一篇
flowable中用户相关api