Android15am命令APP安装流程
- 游戏开发
- 2025-09-22 05:06:01

一. PM 安装命令
使用命令
pm install -r xxx.apk
pm命令安装app 会触发PackageManagerShellCommand 中runInstall()方法
frameworks/base/services/core/java/com/android/server/pm/PackageManagerShellCommand.java1. 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