Loading services/core/java/com/android/server/pm/DeletePackageHelper.java +2 −1 Original line number Diff line number Diff line Loading @@ -271,7 +271,8 @@ final class DeletePackageHelper { // other processes clean up before deleting resources. synchronized (mPm.mInstallLock) { if (info.mArgs != null) { mRemovePackageHelper.cleanUpResources(info.mArgs); mRemovePackageHelper.cleanUpResources(info.mArgs.mCodeFile, info.mArgs.mInstructionSets); } boolean reEnableStub = false; Loading services/core/java/com/android/server/pm/InstallArgs.java +3 −16 Original line number Diff line number Diff line Loading @@ -70,10 +70,9 @@ final class InstallArgs { UserHandle user, String[] instructionSets, String abiOverride, String[] installGrantPermissions, List<String> allowlistedRestrictedPermissions, int autoRevokePermissionsMode, String traceMethod, int traceCookie, SigningDetails signingDetails, int installReason, int installScenario, boolean forceQueryableOverride, int dataLoaderType, int packageSource) { int autoRevokePermissionsMode, String traceMethod, int traceCookie, SigningDetails signingDetails, int installReason, int installScenario, boolean forceQueryableOverride, int dataLoaderType, int packageSource) { mOriginInfo = originInfo; mMoveInfo = moveInfo; mInstallFlags = installFlags; Loading @@ -96,18 +95,6 @@ final class InstallArgs { mPackageSource = packageSource; } /** New install */ InstallArgs(InstallingSession params) { this(params.mOriginInfo, params.mMoveInfo, params.mObserver, params.mInstallFlags, params.mInstallSource, params.mVolumeUuid, params.getUser(), null /*instructionSets*/, params.mPackageAbiOverride, params.mGrantedRuntimePermissions, params.mAllowlistedRestrictedPermissions, params.mAutoRevokePermissionsMode, params.mTraceMethod, params.mTraceCookie, params.mSigningDetails, params.mInstallReason, params.mInstallScenario, params.mForceQueryableOverride, params.mDataLoaderType, params.mPackageSource); } /** * Create args that describe an existing installed package. Typically used * when cleaning up old installs, or used as a move source. Loading services/core/java/com/android/server/pm/InstallPackageHelper.java +255 −251 File changed.Preview size limit exceeded, changes collapsed. Show changes services/core/java/com/android/server/pm/InstallRequest.java +382 −5 Original line number Diff line number Diff line Loading @@ -16,12 +16,389 @@ package com.android.server.pm; import static android.content.pm.PackageManager.INSTALL_REASON_UNKNOWN; import static android.content.pm.PackageManager.INSTALL_SCENARIO_DEFAULT; import static com.android.server.pm.PackageManagerService.TAG; import android.annotation.NonNull; import android.annotation.Nullable; import android.apex.ApexInfo; import android.app.AppOpsManager; import android.content.pm.DataLoaderType; import android.content.pm.IPackageInstallObserver2; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.SigningDetails; import android.net.Uri; import android.os.UserHandle; import android.util.ExceptionUtils; import android.util.Slog; import com.android.server.pm.pkg.AndroidPackage; import java.io.File; import java.util.ArrayList; import java.util.List; final class InstallRequest { public final InstallArgs mArgs; public final PackageInstalledInfo mInstallResult; private final int mUserId; @Nullable private final InstallArgs mInstallArgs; @NonNull private final PackageInstalledInfo mInstalledInfo; @Nullable private Runnable mPostInstallRunnable; @Nullable private PackageRemovedInfo mRemovedInfo; // New install InstallRequest(InstallingSession params) { mUserId = params.getUser().getIdentifier(); mInstallArgs = new InstallArgs(params.mOriginInfo, params.mMoveInfo, params.mObserver, params.mInstallFlags, params.mInstallSource, params.mVolumeUuid, params.getUser(), null /*instructionSets*/, params.mPackageAbiOverride, params.mGrantedRuntimePermissions, params.mAllowlistedRestrictedPermissions, params.mAutoRevokePermissionsMode, params.mTraceMethod, params.mTraceCookie, params.mSigningDetails, params.mInstallReason, params.mInstallScenario, params.mForceQueryableOverride, params.mDataLoaderType, params.mPackageSource); mInstalledInfo = new PackageInstalledInfo(); } // Install existing package as user InstallRequest(int userId, int returnCode, AndroidPackage pkg, int[] newUsers, Runnable runnable) { mUserId = userId; mInstallArgs = null; mInstalledInfo = new PackageInstalledInfo(); mInstalledInfo.mReturnCode = returnCode; mInstalledInfo.mPkg = pkg; mInstalledInfo.mNewUsers = newUsers; mPostInstallRunnable = runnable; } private static class PackageInstalledInfo { String mName; int mUid = -1; // The set of users that originally had this package installed. int[] mOrigUsers; // The set of users that now have this package installed. int[] mNewUsers; AndroidPackage mPkg; int mReturnCode; String mReturnMsg; String mInstallerPackageName; // The set of packages consuming this shared library or null if no consumers exist. ArrayList<AndroidPackage> mLibraryConsumers; PackageFreezer mFreezer; // In some error cases we want to convey more info back to the observer String mOrigPackage; String mOrigPermission; // The ApexInfo returned by ApexManager#installPackage, used by rebootless APEX install ApexInfo mApexInfo; } public String getName() { return mInstalledInfo.mName; } public String getReturnMsg() { return mInstalledInfo.mReturnMsg; } public OriginInfo getOriginInfo() { return mInstallArgs == null ? null : mInstallArgs.mOriginInfo; } public PackageRemovedInfo getRemovedInfo() { return mRemovedInfo; } public String getOrigPackage() { return mInstalledInfo.mOrigPackage; } public String getOrigPermission() { return mInstalledInfo.mOrigPermission; } @Nullable public File getCodeFile() { return mInstallArgs == null ? null : mInstallArgs.mCodeFile; } @Nullable public String getCodePath() { return (mInstallArgs != null && mInstallArgs.mCodeFile != null) ? mInstallArgs.mCodeFile.getAbsolutePath() : null; } @Nullable public String getAbiOverride() { return mInstallArgs == null ? null : mInstallArgs.mAbiOverride; } public int getReturnCode() { return mInstalledInfo.mReturnCode; } @Nullable public IPackageInstallObserver2 getObserver() { return mInstallArgs == null ? null : mInstallArgs.mObserver; } public boolean isMoveInstall() { return mInstallArgs != null && mInstallArgs.mMoveInfo != null; } @Nullable public String getMoveToUuid() { return (mInstallArgs != null && mInstallArgs.mMoveInfo != null) ? mInstallArgs.mMoveInfo.mToUuid : null; } @Nullable public String getMovePackageName() { return (mInstallArgs != null && mInstallArgs.mMoveInfo != null) ? mInstallArgs.mMoveInfo.mPackageName : null; } @Nullable public String getMoveFromCodePath() { return (mInstallArgs != null && mInstallArgs.mMoveInfo != null) ? mInstallArgs.mMoveInfo.mFromCodePath : null; } @Nullable public File getOldCodeFile() { return (mRemovedInfo != null && mRemovedInfo.mArgs != null) ? mRemovedInfo.mArgs.mCodeFile : null; } @Nullable public String[] getOldInstructionSet() { return (mRemovedInfo != null && mRemovedInfo.mArgs != null) ? mRemovedInfo.mArgs.mInstructionSets : null; } public UserHandle getUser() { return new UserHandle(mUserId); } public int getUserId() { return mUserId; } public int getInstallFlags() { return mInstallArgs == null ? 0 : mInstallArgs.mInstallFlags; } public int getInstallReason() { return mInstallArgs == null ? INSTALL_REASON_UNKNOWN : mInstallArgs.mInstallReason; } @Nullable public String getVolumeUuid() { return mInstallArgs == null ? null : mInstallArgs.mVolumeUuid; } public AndroidPackage getPkg() { return mInstalledInfo.mPkg; } @Nullable public String getTraceMethod() { return mInstallArgs == null ? null : mInstallArgs.mTraceMethod; } public int getTraceCookie() { return mInstallArgs == null ? 0 : mInstallArgs.mTraceCookie; } public boolean isUpdate() { return mRemovedInfo != null && mRemovedInfo.mRemovedPackage != null; } @Nullable public String getRemovedPackage() { return mRemovedInfo != null ? mRemovedInfo.mRemovedPackage : null; } public boolean isInstallForExistingUser() { return mInstallArgs == null; } @Nullable public InstallSource getInstallSource() { return mInstallArgs == null ? null : mInstallArgs.mInstallSource; } @Nullable public String getInstallerPackageName() { return (mInstallArgs != null && mInstallArgs.mInstallSource != null) ? mInstallArgs.mInstallSource.installerPackageName : null; } public int getDataLoaderType() { return mInstallArgs == null ? DataLoaderType.NONE : mInstallArgs.mDataLoaderType; } public int getSignatureSchemeVersion() { return mInstallArgs == null ? SigningDetails.SignatureSchemeVersion.UNKNOWN : mInstallArgs.mSigningDetails.getSignatureSchemeVersion(); } @NonNull public SigningDetails getSigningDetails() { return mInstallArgs == null ? SigningDetails.UNKNOWN : mInstallArgs.mSigningDetails; } @Nullable public Uri getOriginUri() { return mInstallArgs == null ? null : Uri.fromFile(mInstallArgs.mOriginInfo.mResolvedFile); } public ApexInfo getApexInfo() { return mInstalledInfo.mApexInfo; } public String getSourceInstallerPackageName() { return mInstallArgs.mInstallSource.installerPackageName; } public boolean isRollback() { return mInstallArgs != null && mInstallArgs.mInstallReason == PackageManager.INSTALL_REASON_ROLLBACK; } public int[] getNewUsers() { return mInstalledInfo.mNewUsers; } public int[] getOriginUsers() { return mInstalledInfo.mOrigUsers; } public int getUid() { return mInstalledInfo.mUid; } @Nullable public String[] getInstallGrantPermissions() { return mInstallArgs == null ? null : mInstallArgs.mInstallGrantPermissions; } public ArrayList<AndroidPackage> getLibraryConsumers() { return mInstalledInfo.mLibraryConsumers; } @Nullable public List<String> getAllowlistedRestrictedPermissions() { return mInstallArgs == null ? null : mInstallArgs.mAllowlistedRestrictedPermissions; } public int getAutoRevokePermissionsMode() { return mInstallArgs == null ? AppOpsManager.MODE_DEFAULT : mInstallArgs.mAutoRevokePermissionsMode; } public int getPackageSource() { return mInstallArgs == null ? PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED : mInstallArgs.mPackageSource; } public int getInstallScenario() { return mInstallArgs == null ? INSTALL_SCENARIO_DEFAULT : mInstallArgs.mInstallScenario; } public boolean isForceQueryableOverride() { return mInstallArgs != null && mInstallArgs.mForceQueryableOverride; } public void closeFreezer() { if (mInstalledInfo.mFreezer != null) { mInstalledInfo.mFreezer.close(); } } public void runPostInstallRunnable() { if (mPostInstallRunnable != null) { mPostInstallRunnable.run(); } } public void setCodeFile(File codeFile) { if (mInstallArgs != null) { mInstallArgs.mCodeFile = codeFile; } } public void setError(int code, String msg) { setReturnCode(code); setReturnMessage(msg); Slog.w(TAG, msg); } public void setError(String msg, PackageManagerException e) { mInstalledInfo.mReturnCode = e.error; setReturnMessage(ExceptionUtils.getCompleteMessage(msg, e)); Slog.w(TAG, msg, e); } public void setReturnCode(int returnCode) { mInstalledInfo.mReturnCode = returnCode; } public void setReturnMessage(String returnMsg) { mInstalledInfo.mReturnMsg = returnMsg; } public void setApexInfo(ApexInfo apexInfo) { mInstalledInfo.mApexInfo = apexInfo; } public void setPkg(AndroidPackage pkg) { mInstalledInfo.mPkg = pkg; } public void setUid(int uid) { mInstalledInfo.mUid = uid; } public void setNewUsers(int[] newUsers) { mInstalledInfo.mNewUsers = newUsers; } public void setOriginPackage(String originPackage) { mInstalledInfo.mOrigPackage = originPackage; } public void setOriginPermission(String originPermission) { mInstalledInfo.mOrigPermission = originPermission; } public void setInstallerPackageName(String installerPackageName) { mInstalledInfo.mInstallerPackageName = installerPackageName; } public void setName(String packageName) { mInstalledInfo.mName = packageName; } public void setOriginUsers(int[] userIds) { mInstalledInfo.mOrigUsers = userIds; } public void setFreezer(PackageFreezer freezer) { mInstalledInfo.mFreezer = freezer; } public void setRemovedInfo(PackageRemovedInfo removedInfo) { mRemovedInfo = removedInfo; } InstallRequest(InstallArgs args, PackageInstalledInfo res) { mArgs = args; mInstallResult = res; public void setLibraryConsumers(ArrayList<AndroidPackage> libraryConsumers) { mInstalledInfo.mLibraryConsumers = libraryConsumers; } } services/core/java/com/android/server/pm/InstallingSession.java +49 −50 Original line number Diff line number Diff line Loading @@ -253,68 +253,69 @@ class InstallingSession { } private void processPendingInstall() { InstallArgs args = new InstallArgs(this); InstallRequest installRequest = new InstallRequest(this); if (mRet == PackageManager.INSTALL_SUCCEEDED) { mRet = copyApk(args); mRet = copyApk(installRequest); } if (mRet == PackageManager.INSTALL_SUCCEEDED) { F2fsUtils.releaseCompressedBlocks( mPm.mContext.getContentResolver(), new File(args.getCodePath())); mPm.mContext.getContentResolver(), new File(installRequest.getCodePath())); } installRequest.setReturnCode(mRet); if (mParentInstallingSession != null) { mParentInstallingSession.tryProcessInstallRequest(args, mRet); mParentInstallingSession.tryProcessInstallRequest(installRequest); } else { PackageInstalledInfo res = new PackageInstalledInfo(mRet); // Queue up an async operation since the package installation may take a little while. mPm.mHandler.post(() -> processInstallRequests( res.mReturnCode == PackageManager.INSTALL_SUCCEEDED /* success */, Collections.singletonList(new InstallRequest(args, res)))); mRet == PackageManager.INSTALL_SUCCEEDED /* success */, Collections.singletonList(installRequest))); } } private int copyApk(InstallArgs args) { private int copyApk(InstallRequest request) { if (mMoveInfo == null) { return copyApkForFileInstall(args); return copyApkForFileInstall(request); } else { return copyApkForMoveInstall(args); return copyApkForMoveInstall(request); } } private int copyApkForFileInstall(InstallArgs args) { private int copyApkForFileInstall(InstallRequest request) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk"); try { if (mOriginInfo.mStaged) { if (DEBUG_INSTALL) { Slog.d(TAG, mOriginInfo.mFile + " already staged; skipping copy"); } args.mCodeFile = mOriginInfo.mFile; request.setCodeFile(mOriginInfo.mFile); return PackageManager.INSTALL_SUCCEEDED; } try { final boolean isEphemeral = (mInstallFlags & PackageManager.INSTALL_INSTANT_APP) != 0; args.mCodeFile = mPm.mInstallerService.allocateStageDirLegacy(mVolumeUuid, isEphemeral); request.setCodeFile( mPm.mInstallerService.allocateStageDirLegacy(mVolumeUuid, isEphemeral)); } catch (IOException e) { Slog.w(TAG, "Failed to create copy file: " + e); return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; } int ret = PackageManagerServiceUtils.copyPackage( mOriginInfo.mFile.getAbsolutePath(), args.mCodeFile); mOriginInfo.mFile.getAbsolutePath(), request.getCodeFile()); if (ret != PackageManager.INSTALL_SUCCEEDED) { Slog.e(TAG, "Failed to copy package"); return ret; } final boolean isIncremental = isIncrementalPath(args.mCodeFile.getAbsolutePath()); final File libraryRoot = new File(args.mCodeFile, LIB_DIR_NAME); final boolean isIncremental = isIncrementalPath( request.getCodeFile().getAbsolutePath()); final File libraryRoot = new File(request.getCodeFile(), LIB_DIR_NAME); NativeLibraryHelper.Handle handle = null; try { handle = NativeLibraryHelper.Handle.create(args.mCodeFile); handle = NativeLibraryHelper.Handle.create(request.getCodeFile()); ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot, args.mAbiOverride, isIncremental); request.getAbiOverride(), isIncremental); } catch (IOException e) { Slog.e(TAG, "Copying native libraries failed", e); ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; Loading @@ -328,7 +329,7 @@ class InstallingSession { } } private int copyApkForMoveInstall(InstallArgs args) { private int copyApkForMoveInstall(InstallRequest request) { if (DEBUG_INSTALL) { Slog.d(TAG, "Moving " + mMoveInfo.mPackageName + " from " + mMoveInfo.mFromUuid + " to " + mMoveInfo.mToUuid); Loading @@ -345,8 +346,9 @@ class InstallingSession { } final String toPathName = new File(mMoveInfo.mFromCodePath).getName(); args.mCodeFile = new File(Environment.getDataAppDirectory(mMoveInfo.mToUuid), toPathName); if (DEBUG_INSTALL) Slog.d(TAG, "codeFile after move is " + args.mCodeFile); request.setCodeFile( new File(Environment.getDataAppDirectory(mMoveInfo.mToUuid), toPathName)); if (DEBUG_INSTALL) Slog.d(TAG, "codeFile after move is " + request.getCodeFile()); return PackageManager.INSTALL_SUCCEEDED; } Loading Loading @@ -460,7 +462,7 @@ class InstallingSession { List<InstallRequest> apexInstallRequests = new ArrayList<>(); List<InstallRequest> apkInstallRequests = new ArrayList<>(); for (InstallRequest request : installRequests) { if ((request.mArgs.mInstallFlags & PackageManager.INSTALL_APEX) != 0) { if ((request.getInstallFlags() & PackageManager.INSTALL_APEX) != 0) { apexInstallRequests.add(request); } else { apkInstallRequests.add(request); Loading @@ -485,7 +487,7 @@ class InstallingSession { // processInstallRequestAsync. In that case just notify the observer about the // failure. InstallRequest request = apexInstallRequests.get(0); mPm.notifyInstallObserver(request.mInstallResult, request.mArgs.mObserver); mPm.notifyInstallObserver(request); } return; } Loading @@ -496,28 +498,25 @@ class InstallingSession { private void processApkInstallRequests(boolean success, List<InstallRequest> installRequests) { if (success) { for (InstallRequest request : installRequests) { if (request.mInstallResult.mReturnCode != PackageManager.INSTALL_SUCCEEDED) { cleanUpForFailedInstall(request.mArgs); if (request.getReturnCode() != PackageManager.INSTALL_SUCCEEDED) { cleanUpForFailedInstall(request); } } mInstallPackageHelper.installPackagesTraced(installRequests); for (InstallRequest request : installRequests) { doPostInstall(request.mInstallResult.mReturnCode, request.mArgs); doPostInstall(request); } } for (InstallRequest request : installRequests) { mInstallPackageHelper.restoreAndPostInstall(request.mArgs.mUser.getIdentifier(), request.mInstallResult, new PostInstallData(request.mArgs, request.mInstallResult, null)); mInstallPackageHelper.restoreAndPostInstall(request); } } private void doPostInstall(int status, InstallArgs args) { private void doPostInstall(InstallRequest request) { if (mMoveInfo != null) { if (status == PackageManager.INSTALL_SUCCEEDED) { if (request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED) { mRemovePackageHelper.cleanUpForMoveInstall(mMoveInfo.mFromUuid, mMoveInfo.mPackageName, mMoveInfo.mFromCodePath); } else { Loading @@ -525,18 +524,18 @@ class InstallingSession { mMoveInfo.mPackageName, mMoveInfo.mFromCodePath); } } else { if (status != PackageManager.INSTALL_SUCCEEDED) { mRemovePackageHelper.removeCodePath(args.mCodeFile); if (request.getReturnCode() != PackageManager.INSTALL_SUCCEEDED) { mRemovePackageHelper.removeCodePath(request.getCodeFile()); } } } private void cleanUpForFailedInstall(InstallArgs args) { if (args.mMoveInfo != null) { mRemovePackageHelper.cleanUpForMoveInstall(args.mMoveInfo.mToUuid, args.mMoveInfo.mPackageName, args.mMoveInfo.mFromCodePath); private void cleanUpForFailedInstall(InstallRequest request) { if (request.isMoveInstall()) { mRemovePackageHelper.cleanUpForMoveInstall(request.getMoveToUuid(), request.getMovePackageName(), request.getMoveFromCodePath()); } else { mRemovePackageHelper.removeCodePath(args.mCodeFile); mRemovePackageHelper.removeCodePath(request.getCodeFile()); } } Loading @@ -560,7 +559,7 @@ class InstallingSession { InstallRequest request = requests.get(0); try { // Should directory scanning logic be moved to ApexManager for better test coverage? final File dir = request.mArgs.mOriginInfo.mResolvedFile; final File dir = request.getOriginInfo().mResolvedFile; final File[] apexes = dir.listFiles(); if (apexes == null) { throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, Loading @@ -580,7 +579,7 @@ class InstallingSession { // The newly installed APEX will not be reverted even if // processApkInstallRequests() fails. Need a way to keep info stored in apexd // and PMS in sync in the face of install failures. request.mInstallResult.mApexInfo = apexInfo; request.setApexInfo(apexInfo); mPm.mHandler.post(() -> processApkInstallRequests(true, requests)); return; } else { Loading @@ -588,10 +587,10 @@ class InstallingSession { } } } catch (PackageManagerException e) { request.mInstallResult.setError("APEX installation failed", e); request.setError("APEX installation failed", e); } PackageManagerService.invalidatePackageInfoCache(); mPm.notifyInstallObserver(request.mInstallResult, request.mArgs.mObserver); mPm.notifyInstallObserver(request); } /** Loading @@ -600,7 +599,7 @@ class InstallingSession { */ private class MultiPackageInstallingSession { private final List<InstallingSession> mChildInstallingSessions; private final Map<InstallArgs, Integer> mCurrentState; private final Map<InstallRequest, Integer> mCurrentState; @NonNull final PackageManagerService mPm; final UserHandle mUser; Loading Loading @@ -636,8 +635,8 @@ class InstallingSession { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } public void tryProcessInstallRequest(InstallArgs args, int currentStatus) { mCurrentState.put(args, currentStatus); public void tryProcessInstallRequest(InstallRequest request) { mCurrentState.put(request, request.getReturnCode()); if (mCurrentState.size() != mChildInstallingSessions.size()) { return; } Loading @@ -651,9 +650,9 @@ class InstallingSession { } } final List<InstallRequest> installRequests = new ArrayList<>(mCurrentState.size()); for (Map.Entry<InstallArgs, Integer> entry : mCurrentState.entrySet()) { installRequests.add(new InstallRequest(entry.getKey(), new PackageInstalledInfo(completeStatus))); for (Map.Entry<InstallRequest, Integer> entry : mCurrentState.entrySet()) { entry.getKey().setReturnCode(completeStatus); installRequests.add(entry.getKey()); } int finalCompleteStatus = completeStatus; mPm.mHandler.post(() -> processInstallRequests( Loading Loading
services/core/java/com/android/server/pm/DeletePackageHelper.java +2 −1 Original line number Diff line number Diff line Loading @@ -271,7 +271,8 @@ final class DeletePackageHelper { // other processes clean up before deleting resources. synchronized (mPm.mInstallLock) { if (info.mArgs != null) { mRemovePackageHelper.cleanUpResources(info.mArgs); mRemovePackageHelper.cleanUpResources(info.mArgs.mCodeFile, info.mArgs.mInstructionSets); } boolean reEnableStub = false; Loading
services/core/java/com/android/server/pm/InstallArgs.java +3 −16 Original line number Diff line number Diff line Loading @@ -70,10 +70,9 @@ final class InstallArgs { UserHandle user, String[] instructionSets, String abiOverride, String[] installGrantPermissions, List<String> allowlistedRestrictedPermissions, int autoRevokePermissionsMode, String traceMethod, int traceCookie, SigningDetails signingDetails, int installReason, int installScenario, boolean forceQueryableOverride, int dataLoaderType, int packageSource) { int autoRevokePermissionsMode, String traceMethod, int traceCookie, SigningDetails signingDetails, int installReason, int installScenario, boolean forceQueryableOverride, int dataLoaderType, int packageSource) { mOriginInfo = originInfo; mMoveInfo = moveInfo; mInstallFlags = installFlags; Loading @@ -96,18 +95,6 @@ final class InstallArgs { mPackageSource = packageSource; } /** New install */ InstallArgs(InstallingSession params) { this(params.mOriginInfo, params.mMoveInfo, params.mObserver, params.mInstallFlags, params.mInstallSource, params.mVolumeUuid, params.getUser(), null /*instructionSets*/, params.mPackageAbiOverride, params.mGrantedRuntimePermissions, params.mAllowlistedRestrictedPermissions, params.mAutoRevokePermissionsMode, params.mTraceMethod, params.mTraceCookie, params.mSigningDetails, params.mInstallReason, params.mInstallScenario, params.mForceQueryableOverride, params.mDataLoaderType, params.mPackageSource); } /** * Create args that describe an existing installed package. Typically used * when cleaning up old installs, or used as a move source. Loading
services/core/java/com/android/server/pm/InstallPackageHelper.java +255 −251 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/core/java/com/android/server/pm/InstallRequest.java +382 −5 Original line number Diff line number Diff line Loading @@ -16,12 +16,389 @@ package com.android.server.pm; import static android.content.pm.PackageManager.INSTALL_REASON_UNKNOWN; import static android.content.pm.PackageManager.INSTALL_SCENARIO_DEFAULT; import static com.android.server.pm.PackageManagerService.TAG; import android.annotation.NonNull; import android.annotation.Nullable; import android.apex.ApexInfo; import android.app.AppOpsManager; import android.content.pm.DataLoaderType; import android.content.pm.IPackageInstallObserver2; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.SigningDetails; import android.net.Uri; import android.os.UserHandle; import android.util.ExceptionUtils; import android.util.Slog; import com.android.server.pm.pkg.AndroidPackage; import java.io.File; import java.util.ArrayList; import java.util.List; final class InstallRequest { public final InstallArgs mArgs; public final PackageInstalledInfo mInstallResult; private final int mUserId; @Nullable private final InstallArgs mInstallArgs; @NonNull private final PackageInstalledInfo mInstalledInfo; @Nullable private Runnable mPostInstallRunnable; @Nullable private PackageRemovedInfo mRemovedInfo; // New install InstallRequest(InstallingSession params) { mUserId = params.getUser().getIdentifier(); mInstallArgs = new InstallArgs(params.mOriginInfo, params.mMoveInfo, params.mObserver, params.mInstallFlags, params.mInstallSource, params.mVolumeUuid, params.getUser(), null /*instructionSets*/, params.mPackageAbiOverride, params.mGrantedRuntimePermissions, params.mAllowlistedRestrictedPermissions, params.mAutoRevokePermissionsMode, params.mTraceMethod, params.mTraceCookie, params.mSigningDetails, params.mInstallReason, params.mInstallScenario, params.mForceQueryableOverride, params.mDataLoaderType, params.mPackageSource); mInstalledInfo = new PackageInstalledInfo(); } // Install existing package as user InstallRequest(int userId, int returnCode, AndroidPackage pkg, int[] newUsers, Runnable runnable) { mUserId = userId; mInstallArgs = null; mInstalledInfo = new PackageInstalledInfo(); mInstalledInfo.mReturnCode = returnCode; mInstalledInfo.mPkg = pkg; mInstalledInfo.mNewUsers = newUsers; mPostInstallRunnable = runnable; } private static class PackageInstalledInfo { String mName; int mUid = -1; // The set of users that originally had this package installed. int[] mOrigUsers; // The set of users that now have this package installed. int[] mNewUsers; AndroidPackage mPkg; int mReturnCode; String mReturnMsg; String mInstallerPackageName; // The set of packages consuming this shared library or null if no consumers exist. ArrayList<AndroidPackage> mLibraryConsumers; PackageFreezer mFreezer; // In some error cases we want to convey more info back to the observer String mOrigPackage; String mOrigPermission; // The ApexInfo returned by ApexManager#installPackage, used by rebootless APEX install ApexInfo mApexInfo; } public String getName() { return mInstalledInfo.mName; } public String getReturnMsg() { return mInstalledInfo.mReturnMsg; } public OriginInfo getOriginInfo() { return mInstallArgs == null ? null : mInstallArgs.mOriginInfo; } public PackageRemovedInfo getRemovedInfo() { return mRemovedInfo; } public String getOrigPackage() { return mInstalledInfo.mOrigPackage; } public String getOrigPermission() { return mInstalledInfo.mOrigPermission; } @Nullable public File getCodeFile() { return mInstallArgs == null ? null : mInstallArgs.mCodeFile; } @Nullable public String getCodePath() { return (mInstallArgs != null && mInstallArgs.mCodeFile != null) ? mInstallArgs.mCodeFile.getAbsolutePath() : null; } @Nullable public String getAbiOverride() { return mInstallArgs == null ? null : mInstallArgs.mAbiOverride; } public int getReturnCode() { return mInstalledInfo.mReturnCode; } @Nullable public IPackageInstallObserver2 getObserver() { return mInstallArgs == null ? null : mInstallArgs.mObserver; } public boolean isMoveInstall() { return mInstallArgs != null && mInstallArgs.mMoveInfo != null; } @Nullable public String getMoveToUuid() { return (mInstallArgs != null && mInstallArgs.mMoveInfo != null) ? mInstallArgs.mMoveInfo.mToUuid : null; } @Nullable public String getMovePackageName() { return (mInstallArgs != null && mInstallArgs.mMoveInfo != null) ? mInstallArgs.mMoveInfo.mPackageName : null; } @Nullable public String getMoveFromCodePath() { return (mInstallArgs != null && mInstallArgs.mMoveInfo != null) ? mInstallArgs.mMoveInfo.mFromCodePath : null; } @Nullable public File getOldCodeFile() { return (mRemovedInfo != null && mRemovedInfo.mArgs != null) ? mRemovedInfo.mArgs.mCodeFile : null; } @Nullable public String[] getOldInstructionSet() { return (mRemovedInfo != null && mRemovedInfo.mArgs != null) ? mRemovedInfo.mArgs.mInstructionSets : null; } public UserHandle getUser() { return new UserHandle(mUserId); } public int getUserId() { return mUserId; } public int getInstallFlags() { return mInstallArgs == null ? 0 : mInstallArgs.mInstallFlags; } public int getInstallReason() { return mInstallArgs == null ? INSTALL_REASON_UNKNOWN : mInstallArgs.mInstallReason; } @Nullable public String getVolumeUuid() { return mInstallArgs == null ? null : mInstallArgs.mVolumeUuid; } public AndroidPackage getPkg() { return mInstalledInfo.mPkg; } @Nullable public String getTraceMethod() { return mInstallArgs == null ? null : mInstallArgs.mTraceMethod; } public int getTraceCookie() { return mInstallArgs == null ? 0 : mInstallArgs.mTraceCookie; } public boolean isUpdate() { return mRemovedInfo != null && mRemovedInfo.mRemovedPackage != null; } @Nullable public String getRemovedPackage() { return mRemovedInfo != null ? mRemovedInfo.mRemovedPackage : null; } public boolean isInstallForExistingUser() { return mInstallArgs == null; } @Nullable public InstallSource getInstallSource() { return mInstallArgs == null ? null : mInstallArgs.mInstallSource; } @Nullable public String getInstallerPackageName() { return (mInstallArgs != null && mInstallArgs.mInstallSource != null) ? mInstallArgs.mInstallSource.installerPackageName : null; } public int getDataLoaderType() { return mInstallArgs == null ? DataLoaderType.NONE : mInstallArgs.mDataLoaderType; } public int getSignatureSchemeVersion() { return mInstallArgs == null ? SigningDetails.SignatureSchemeVersion.UNKNOWN : mInstallArgs.mSigningDetails.getSignatureSchemeVersion(); } @NonNull public SigningDetails getSigningDetails() { return mInstallArgs == null ? SigningDetails.UNKNOWN : mInstallArgs.mSigningDetails; } @Nullable public Uri getOriginUri() { return mInstallArgs == null ? null : Uri.fromFile(mInstallArgs.mOriginInfo.mResolvedFile); } public ApexInfo getApexInfo() { return mInstalledInfo.mApexInfo; } public String getSourceInstallerPackageName() { return mInstallArgs.mInstallSource.installerPackageName; } public boolean isRollback() { return mInstallArgs != null && mInstallArgs.mInstallReason == PackageManager.INSTALL_REASON_ROLLBACK; } public int[] getNewUsers() { return mInstalledInfo.mNewUsers; } public int[] getOriginUsers() { return mInstalledInfo.mOrigUsers; } public int getUid() { return mInstalledInfo.mUid; } @Nullable public String[] getInstallGrantPermissions() { return mInstallArgs == null ? null : mInstallArgs.mInstallGrantPermissions; } public ArrayList<AndroidPackage> getLibraryConsumers() { return mInstalledInfo.mLibraryConsumers; } @Nullable public List<String> getAllowlistedRestrictedPermissions() { return mInstallArgs == null ? null : mInstallArgs.mAllowlistedRestrictedPermissions; } public int getAutoRevokePermissionsMode() { return mInstallArgs == null ? AppOpsManager.MODE_DEFAULT : mInstallArgs.mAutoRevokePermissionsMode; } public int getPackageSource() { return mInstallArgs == null ? PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED : mInstallArgs.mPackageSource; } public int getInstallScenario() { return mInstallArgs == null ? INSTALL_SCENARIO_DEFAULT : mInstallArgs.mInstallScenario; } public boolean isForceQueryableOverride() { return mInstallArgs != null && mInstallArgs.mForceQueryableOverride; } public void closeFreezer() { if (mInstalledInfo.mFreezer != null) { mInstalledInfo.mFreezer.close(); } } public void runPostInstallRunnable() { if (mPostInstallRunnable != null) { mPostInstallRunnable.run(); } } public void setCodeFile(File codeFile) { if (mInstallArgs != null) { mInstallArgs.mCodeFile = codeFile; } } public void setError(int code, String msg) { setReturnCode(code); setReturnMessage(msg); Slog.w(TAG, msg); } public void setError(String msg, PackageManagerException e) { mInstalledInfo.mReturnCode = e.error; setReturnMessage(ExceptionUtils.getCompleteMessage(msg, e)); Slog.w(TAG, msg, e); } public void setReturnCode(int returnCode) { mInstalledInfo.mReturnCode = returnCode; } public void setReturnMessage(String returnMsg) { mInstalledInfo.mReturnMsg = returnMsg; } public void setApexInfo(ApexInfo apexInfo) { mInstalledInfo.mApexInfo = apexInfo; } public void setPkg(AndroidPackage pkg) { mInstalledInfo.mPkg = pkg; } public void setUid(int uid) { mInstalledInfo.mUid = uid; } public void setNewUsers(int[] newUsers) { mInstalledInfo.mNewUsers = newUsers; } public void setOriginPackage(String originPackage) { mInstalledInfo.mOrigPackage = originPackage; } public void setOriginPermission(String originPermission) { mInstalledInfo.mOrigPermission = originPermission; } public void setInstallerPackageName(String installerPackageName) { mInstalledInfo.mInstallerPackageName = installerPackageName; } public void setName(String packageName) { mInstalledInfo.mName = packageName; } public void setOriginUsers(int[] userIds) { mInstalledInfo.mOrigUsers = userIds; } public void setFreezer(PackageFreezer freezer) { mInstalledInfo.mFreezer = freezer; } public void setRemovedInfo(PackageRemovedInfo removedInfo) { mRemovedInfo = removedInfo; } InstallRequest(InstallArgs args, PackageInstalledInfo res) { mArgs = args; mInstallResult = res; public void setLibraryConsumers(ArrayList<AndroidPackage> libraryConsumers) { mInstalledInfo.mLibraryConsumers = libraryConsumers; } }
services/core/java/com/android/server/pm/InstallingSession.java +49 −50 Original line number Diff line number Diff line Loading @@ -253,68 +253,69 @@ class InstallingSession { } private void processPendingInstall() { InstallArgs args = new InstallArgs(this); InstallRequest installRequest = new InstallRequest(this); if (mRet == PackageManager.INSTALL_SUCCEEDED) { mRet = copyApk(args); mRet = copyApk(installRequest); } if (mRet == PackageManager.INSTALL_SUCCEEDED) { F2fsUtils.releaseCompressedBlocks( mPm.mContext.getContentResolver(), new File(args.getCodePath())); mPm.mContext.getContentResolver(), new File(installRequest.getCodePath())); } installRequest.setReturnCode(mRet); if (mParentInstallingSession != null) { mParentInstallingSession.tryProcessInstallRequest(args, mRet); mParentInstallingSession.tryProcessInstallRequest(installRequest); } else { PackageInstalledInfo res = new PackageInstalledInfo(mRet); // Queue up an async operation since the package installation may take a little while. mPm.mHandler.post(() -> processInstallRequests( res.mReturnCode == PackageManager.INSTALL_SUCCEEDED /* success */, Collections.singletonList(new InstallRequest(args, res)))); mRet == PackageManager.INSTALL_SUCCEEDED /* success */, Collections.singletonList(installRequest))); } } private int copyApk(InstallArgs args) { private int copyApk(InstallRequest request) { if (mMoveInfo == null) { return copyApkForFileInstall(args); return copyApkForFileInstall(request); } else { return copyApkForMoveInstall(args); return copyApkForMoveInstall(request); } } private int copyApkForFileInstall(InstallArgs args) { private int copyApkForFileInstall(InstallRequest request) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk"); try { if (mOriginInfo.mStaged) { if (DEBUG_INSTALL) { Slog.d(TAG, mOriginInfo.mFile + " already staged; skipping copy"); } args.mCodeFile = mOriginInfo.mFile; request.setCodeFile(mOriginInfo.mFile); return PackageManager.INSTALL_SUCCEEDED; } try { final boolean isEphemeral = (mInstallFlags & PackageManager.INSTALL_INSTANT_APP) != 0; args.mCodeFile = mPm.mInstallerService.allocateStageDirLegacy(mVolumeUuid, isEphemeral); request.setCodeFile( mPm.mInstallerService.allocateStageDirLegacy(mVolumeUuid, isEphemeral)); } catch (IOException e) { Slog.w(TAG, "Failed to create copy file: " + e); return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; } int ret = PackageManagerServiceUtils.copyPackage( mOriginInfo.mFile.getAbsolutePath(), args.mCodeFile); mOriginInfo.mFile.getAbsolutePath(), request.getCodeFile()); if (ret != PackageManager.INSTALL_SUCCEEDED) { Slog.e(TAG, "Failed to copy package"); return ret; } final boolean isIncremental = isIncrementalPath(args.mCodeFile.getAbsolutePath()); final File libraryRoot = new File(args.mCodeFile, LIB_DIR_NAME); final boolean isIncremental = isIncrementalPath( request.getCodeFile().getAbsolutePath()); final File libraryRoot = new File(request.getCodeFile(), LIB_DIR_NAME); NativeLibraryHelper.Handle handle = null; try { handle = NativeLibraryHelper.Handle.create(args.mCodeFile); handle = NativeLibraryHelper.Handle.create(request.getCodeFile()); ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot, args.mAbiOverride, isIncremental); request.getAbiOverride(), isIncremental); } catch (IOException e) { Slog.e(TAG, "Copying native libraries failed", e); ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; Loading @@ -328,7 +329,7 @@ class InstallingSession { } } private int copyApkForMoveInstall(InstallArgs args) { private int copyApkForMoveInstall(InstallRequest request) { if (DEBUG_INSTALL) { Slog.d(TAG, "Moving " + mMoveInfo.mPackageName + " from " + mMoveInfo.mFromUuid + " to " + mMoveInfo.mToUuid); Loading @@ -345,8 +346,9 @@ class InstallingSession { } final String toPathName = new File(mMoveInfo.mFromCodePath).getName(); args.mCodeFile = new File(Environment.getDataAppDirectory(mMoveInfo.mToUuid), toPathName); if (DEBUG_INSTALL) Slog.d(TAG, "codeFile after move is " + args.mCodeFile); request.setCodeFile( new File(Environment.getDataAppDirectory(mMoveInfo.mToUuid), toPathName)); if (DEBUG_INSTALL) Slog.d(TAG, "codeFile after move is " + request.getCodeFile()); return PackageManager.INSTALL_SUCCEEDED; } Loading Loading @@ -460,7 +462,7 @@ class InstallingSession { List<InstallRequest> apexInstallRequests = new ArrayList<>(); List<InstallRequest> apkInstallRequests = new ArrayList<>(); for (InstallRequest request : installRequests) { if ((request.mArgs.mInstallFlags & PackageManager.INSTALL_APEX) != 0) { if ((request.getInstallFlags() & PackageManager.INSTALL_APEX) != 0) { apexInstallRequests.add(request); } else { apkInstallRequests.add(request); Loading @@ -485,7 +487,7 @@ class InstallingSession { // processInstallRequestAsync. In that case just notify the observer about the // failure. InstallRequest request = apexInstallRequests.get(0); mPm.notifyInstallObserver(request.mInstallResult, request.mArgs.mObserver); mPm.notifyInstallObserver(request); } return; } Loading @@ -496,28 +498,25 @@ class InstallingSession { private void processApkInstallRequests(boolean success, List<InstallRequest> installRequests) { if (success) { for (InstallRequest request : installRequests) { if (request.mInstallResult.mReturnCode != PackageManager.INSTALL_SUCCEEDED) { cleanUpForFailedInstall(request.mArgs); if (request.getReturnCode() != PackageManager.INSTALL_SUCCEEDED) { cleanUpForFailedInstall(request); } } mInstallPackageHelper.installPackagesTraced(installRequests); for (InstallRequest request : installRequests) { doPostInstall(request.mInstallResult.mReturnCode, request.mArgs); doPostInstall(request); } } for (InstallRequest request : installRequests) { mInstallPackageHelper.restoreAndPostInstall(request.mArgs.mUser.getIdentifier(), request.mInstallResult, new PostInstallData(request.mArgs, request.mInstallResult, null)); mInstallPackageHelper.restoreAndPostInstall(request); } } private void doPostInstall(int status, InstallArgs args) { private void doPostInstall(InstallRequest request) { if (mMoveInfo != null) { if (status == PackageManager.INSTALL_SUCCEEDED) { if (request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED) { mRemovePackageHelper.cleanUpForMoveInstall(mMoveInfo.mFromUuid, mMoveInfo.mPackageName, mMoveInfo.mFromCodePath); } else { Loading @@ -525,18 +524,18 @@ class InstallingSession { mMoveInfo.mPackageName, mMoveInfo.mFromCodePath); } } else { if (status != PackageManager.INSTALL_SUCCEEDED) { mRemovePackageHelper.removeCodePath(args.mCodeFile); if (request.getReturnCode() != PackageManager.INSTALL_SUCCEEDED) { mRemovePackageHelper.removeCodePath(request.getCodeFile()); } } } private void cleanUpForFailedInstall(InstallArgs args) { if (args.mMoveInfo != null) { mRemovePackageHelper.cleanUpForMoveInstall(args.mMoveInfo.mToUuid, args.mMoveInfo.mPackageName, args.mMoveInfo.mFromCodePath); private void cleanUpForFailedInstall(InstallRequest request) { if (request.isMoveInstall()) { mRemovePackageHelper.cleanUpForMoveInstall(request.getMoveToUuid(), request.getMovePackageName(), request.getMoveFromCodePath()); } else { mRemovePackageHelper.removeCodePath(args.mCodeFile); mRemovePackageHelper.removeCodePath(request.getCodeFile()); } } Loading @@ -560,7 +559,7 @@ class InstallingSession { InstallRequest request = requests.get(0); try { // Should directory scanning logic be moved to ApexManager for better test coverage? final File dir = request.mArgs.mOriginInfo.mResolvedFile; final File dir = request.getOriginInfo().mResolvedFile; final File[] apexes = dir.listFiles(); if (apexes == null) { throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, Loading @@ -580,7 +579,7 @@ class InstallingSession { // The newly installed APEX will not be reverted even if // processApkInstallRequests() fails. Need a way to keep info stored in apexd // and PMS in sync in the face of install failures. request.mInstallResult.mApexInfo = apexInfo; request.setApexInfo(apexInfo); mPm.mHandler.post(() -> processApkInstallRequests(true, requests)); return; } else { Loading @@ -588,10 +587,10 @@ class InstallingSession { } } } catch (PackageManagerException e) { request.mInstallResult.setError("APEX installation failed", e); request.setError("APEX installation failed", e); } PackageManagerService.invalidatePackageInfoCache(); mPm.notifyInstallObserver(request.mInstallResult, request.mArgs.mObserver); mPm.notifyInstallObserver(request); } /** Loading @@ -600,7 +599,7 @@ class InstallingSession { */ private class MultiPackageInstallingSession { private final List<InstallingSession> mChildInstallingSessions; private final Map<InstallArgs, Integer> mCurrentState; private final Map<InstallRequest, Integer> mCurrentState; @NonNull final PackageManagerService mPm; final UserHandle mUser; Loading Loading @@ -636,8 +635,8 @@ class InstallingSession { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } public void tryProcessInstallRequest(InstallArgs args, int currentStatus) { mCurrentState.put(args, currentStatus); public void tryProcessInstallRequest(InstallRequest request) { mCurrentState.put(request, request.getReturnCode()); if (mCurrentState.size() != mChildInstallingSessions.size()) { return; } Loading @@ -651,9 +650,9 @@ class InstallingSession { } } final List<InstallRequest> installRequests = new ArrayList<>(mCurrentState.size()); for (Map.Entry<InstallArgs, Integer> entry : mCurrentState.entrySet()) { installRequests.add(new InstallRequest(entry.getKey(), new PackageInstalledInfo(completeStatus))); for (Map.Entry<InstallRequest, Integer> entry : mCurrentState.entrySet()) { entry.getKey().setReturnCode(completeStatus); installRequests.add(entry.getKey()); } int finalCompleteStatus = completeStatus; mPm.mHandler.post(() -> processInstallRequests( Loading