1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.pm; 18 19 import static android.content.pm.Flags.disallowSdkLibsToBeApps; 20 import static android.content.pm.PackageManager.APP_METADATA_SOURCE_APK; 21 import static android.content.pm.PackageManager.APP_METADATA_SOURCE_INSTALLER; 22 import static android.content.pm.PackageManager.APP_METADATA_SOURCE_UNKNOWN; 23 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 24 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 25 import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS; 26 import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_PERMISSION_GROUP; 27 import static android.content.pm.PackageManager.INSTALL_FAILED_DEPRECATED_SDK_VERSION; 28 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE; 29 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION; 30 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION_GROUP; 31 import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK; 32 import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; 33 import static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED; 34 import static android.content.pm.PackageManager.INSTALL_FAILED_SESSION_INVALID; 35 import static android.content.pm.PackageManager.INSTALL_FAILED_TEST_ONLY; 36 import static android.content.pm.PackageManager.INSTALL_FAILED_UID_CHANGED; 37 import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE; 38 import static android.content.pm.PackageManager.INSTALL_STAGED; 39 import static android.content.pm.PackageManager.INSTALL_SUCCEEDED; 40 import static android.content.pm.PackageManager.PROPERTY_ANDROID_SAFETY_LABEL; 41 import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN; 42 import static android.content.pm.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V4; 43 import static android.content.pm.parsing.ApkLiteParseUtils.isApkFile; 44 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; 45 import static android.os.incremental.IncrementalManager.isIncrementalPath; 46 import static android.os.storage.StorageManager.FLAG_STORAGE_CE; 47 import static android.os.storage.StorageManager.FLAG_STORAGE_DE; 48 import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL; 49 50 import static com.android.server.pm.InstructionSets.getAppDexInstructionSets; 51 import static com.android.server.pm.PackageManagerException.INTERNAL_ERROR_ARCHIVE_NO_INSTALLER_TITLE; 52 import static com.android.server.pm.PackageManagerService.APP_METADATA_FILE_NAME; 53 import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION; 54 import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL; 55 import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING; 56 import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE; 57 import static com.android.server.pm.PackageManagerService.DEBUG_UPGRADE; 58 import static com.android.server.pm.PackageManagerService.DEBUG_VERIFY; 59 import static com.android.server.pm.PackageManagerService.MIN_INSTALLABLE_TARGET_SDK; 60 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; 61 import static com.android.server.pm.PackageManagerService.POST_INSTALL; 62 import static com.android.server.pm.PackageManagerService.SCAN_AS_APEX; 63 import static com.android.server.pm.PackageManagerService.SCAN_AS_APK_IN_APEX; 64 import static com.android.server.pm.PackageManagerService.SCAN_AS_FACTORY; 65 import static com.android.server.pm.PackageManagerService.SCAN_AS_FULL_APP; 66 import static com.android.server.pm.PackageManagerService.SCAN_AS_INSTANT_APP; 67 import static com.android.server.pm.PackageManagerService.SCAN_AS_ODM; 68 import static com.android.server.pm.PackageManagerService.SCAN_AS_OEM; 69 import static com.android.server.pm.PackageManagerService.SCAN_AS_PRIVILEGED; 70 import static com.android.server.pm.PackageManagerService.SCAN_AS_PRODUCT; 71 import static com.android.server.pm.PackageManagerService.SCAN_AS_STOPPED_SYSTEM_APP; 72 import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM; 73 import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM_EXT; 74 import static com.android.server.pm.PackageManagerService.SCAN_AS_VENDOR; 75 import static com.android.server.pm.PackageManagerService.SCAN_AS_VIRTUAL_PRELOAD; 76 import static com.android.server.pm.PackageManagerService.SCAN_BOOTING; 77 import static com.android.server.pm.PackageManagerService.SCAN_DONT_KILL_APP; 78 import static com.android.server.pm.PackageManagerService.SCAN_DROP_CACHE; 79 import static com.android.server.pm.PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE; 80 import static com.android.server.pm.PackageManagerService.SCAN_IGNORE_FROZEN; 81 import static com.android.server.pm.PackageManagerService.SCAN_INITIAL; 82 import static com.android.server.pm.PackageManagerService.SCAN_MOVE; 83 import static com.android.server.pm.PackageManagerService.SCAN_NEW_INSTALL; 84 import static com.android.server.pm.PackageManagerService.SCAN_NO_DEX; 85 import static com.android.server.pm.PackageManagerService.SCAN_REQUIRE_KNOWN; 86 import static com.android.server.pm.PackageManagerService.SCAN_UPDATE_SIGNATURE; 87 import static com.android.server.pm.PackageManagerService.TAG; 88 import static com.android.server.pm.PackageManagerServiceUtils.comparePackageSignatures; 89 import static com.android.server.pm.PackageManagerServiceUtils.compareSignatures; 90 import static com.android.server.pm.PackageManagerServiceUtils.compressedFileExists; 91 import static com.android.server.pm.PackageManagerServiceUtils.deriveAbiOverride; 92 import static com.android.server.pm.PackageManagerServiceUtils.extractAppMetadataFromApk; 93 import static com.android.server.pm.PackageManagerServiceUtils.isInstalledByAdb; 94 import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo; 95 import static com.android.server.pm.PackageManagerServiceUtils.makeDirRecursive; 96 import static com.android.server.pm.SharedUidMigration.BEST_EFFORT; 97 98 import android.annotation.NonNull; 99 import android.annotation.Nullable; 100 import android.annotation.UserIdInt; 101 import android.apex.ApexInfo; 102 import android.app.AppOpsManager; 103 import android.app.ApplicationExitInfo; 104 import android.app.ApplicationPackageManager; 105 import android.app.BroadcastOptions; 106 import android.app.admin.DevicePolicyManagerInternal; 107 import android.app.backup.IBackupManager; 108 import android.content.ContentResolver; 109 import android.content.Context; 110 import android.content.Intent; 111 import android.content.IntentFilter; 112 import android.content.IntentSender; 113 import android.content.pm.ApplicationInfo; 114 import android.content.pm.ArchivedPackageParcel; 115 import android.content.pm.DataLoaderType; 116 import android.content.pm.Flags; 117 import android.content.pm.PackageInfo; 118 import android.content.pm.PackageInfoLite; 119 import android.content.pm.PackageInstaller; 120 import android.content.pm.PackageManager; 121 import android.content.pm.PermissionGroupInfo; 122 import android.content.pm.PermissionInfo; 123 import android.content.pm.SharedLibraryInfo; 124 import android.content.pm.Signature; 125 import android.content.pm.SigningDetails; 126 import android.content.pm.VerifierInfo; 127 import android.content.pm.dex.DexMetadataHelper; 128 import android.content.pm.parsing.result.ParseResult; 129 import android.content.pm.parsing.result.ParseTypeImpl; 130 import android.net.Uri; 131 import android.os.Binder; 132 import android.os.Build; 133 import android.os.Environment; 134 import android.os.FileUtils; 135 import android.os.Message; 136 import android.os.Process; 137 import android.os.RemoteException; 138 import android.os.SELinux; 139 import android.os.Trace; 140 import android.os.UserHandle; 141 import android.os.UserManager; 142 import android.os.incremental.IncrementalManager; 143 import android.os.incremental.IncrementalStorage; 144 import android.system.ErrnoException; 145 import android.system.Os; 146 import android.text.TextUtils; 147 import android.util.ArrayMap; 148 import android.util.ArraySet; 149 import android.util.EventLog; 150 import android.util.ExceptionUtils; 151 import android.util.Log; 152 import android.util.Pair; 153 import android.util.Slog; 154 import android.util.SparseArray; 155 import android.util.SparseIntArray; 156 157 import com.android.internal.annotations.GuardedBy; 158 import com.android.internal.content.F2fsUtils; 159 import com.android.internal.pm.parsing.PackageParser2; 160 import com.android.internal.pm.parsing.PackageParserException; 161 import com.android.internal.pm.parsing.pkg.AndroidPackageLegacyUtils; 162 import com.android.internal.pm.parsing.pkg.ParsedPackage; 163 import com.android.internal.pm.pkg.component.ComponentMutateUtils; 164 import com.android.internal.pm.pkg.component.ParsedActivity; 165 import com.android.internal.pm.pkg.component.ParsedInstrumentation; 166 import com.android.internal.pm.pkg.component.ParsedIntentInfo; 167 import com.android.internal.pm.pkg.component.ParsedPermission; 168 import com.android.internal.pm.pkg.component.ParsedPermissionGroup; 169 import com.android.internal.pm.pkg.parsing.ParsingPackageUtils; 170 import com.android.internal.security.VerityUtils; 171 import com.android.internal.util.ArrayUtils; 172 import com.android.internal.util.CollectionUtils; 173 import com.android.server.EventLogTags; 174 import com.android.server.SystemConfig; 175 import com.android.server.art.model.DexoptResult; 176 import com.android.server.criticalevents.CriticalEventLog; 177 import com.android.server.pm.dex.ArtManagerService; 178 import com.android.server.pm.dex.DexManager; 179 import com.android.server.pm.dex.DexoptOptions; 180 import com.android.server.pm.parsing.PackageCacher; 181 import com.android.server.pm.parsing.pkg.AndroidPackageUtils; 182 import com.android.server.pm.permission.Permission; 183 import com.android.server.pm.permission.PermissionManagerServiceInternal; 184 import com.android.server.pm.pkg.AndroidPackage; 185 import com.android.server.pm.pkg.PackageStateInternal; 186 import com.android.server.pm.pkg.SharedLibraryWrapper; 187 import com.android.server.rollback.RollbackManagerInternal; 188 import com.android.server.security.FileIntegrityService; 189 import com.android.server.utils.WatchedArrayMap; 190 import com.android.server.utils.WatchedLongSparseArray; 191 192 import dalvik.system.VMRuntime; 193 194 import java.io.File; 195 import java.io.FileInputStream; 196 import java.io.IOException; 197 import java.security.DigestException; 198 import java.security.DigestInputStream; 199 import java.security.MessageDigest; 200 import java.security.NoSuchAlgorithmException; 201 import java.security.PublicKey; 202 import java.security.cert.CertificateException; 203 import java.util.ArrayList; 204 import java.util.Arrays; 205 import java.util.Collections; 206 import java.util.HashSet; 207 import java.util.List; 208 import java.util.Map; 209 import java.util.Set; 210 import java.util.concurrent.ExecutorService; 211 212 final class InstallPackageHelper { 213 private final PackageManagerService mPm; 214 private final AppDataHelper mAppDataHelper; 215 private final BroadcastHelper mBroadcastHelper; 216 private final RemovePackageHelper mRemovePackageHelper; 217 private final DeletePackageHelper mDeletePackageHelper; 218 private final IncrementalManager mIncrementalManager; 219 private final ApexManager mApexManager; 220 private final DexManager mDexManager; 221 private final ArtManagerService mArtManagerService; 222 private final Context mContext; 223 private final PackageDexOptimizer mPackageDexOptimizer; 224 private final PackageAbiHelper mPackageAbiHelper; 225 private final SharedLibrariesImpl mSharedLibraries; 226 private final PackageManagerServiceInjector mInjector; 227 private final UpdateOwnershipHelper mUpdateOwnershipHelper; 228 229 // TODO(b/198166813): remove PMS dependency InstallPackageHelper(PackageManagerService pm, AppDataHelper appDataHelper, RemovePackageHelper removePackageHelper, DeletePackageHelper deletePackageHelper, BroadcastHelper broadcastHelper)230 InstallPackageHelper(PackageManagerService pm, 231 AppDataHelper appDataHelper, 232 RemovePackageHelper removePackageHelper, 233 DeletePackageHelper deletePackageHelper, 234 BroadcastHelper broadcastHelper) { 235 mPm = pm; 236 mInjector = pm.mInjector; 237 mAppDataHelper = appDataHelper; 238 mBroadcastHelper = broadcastHelper; 239 mRemovePackageHelper = removePackageHelper; 240 mDeletePackageHelper = deletePackageHelper; 241 mIncrementalManager = pm.mInjector.getIncrementalManager(); 242 mApexManager = pm.mInjector.getApexManager(); 243 mDexManager = pm.mInjector.getDexManager(); 244 mArtManagerService = pm.mInjector.getArtManagerService(); 245 mContext = pm.mInjector.getContext(); 246 mPackageDexOptimizer = pm.mInjector.getPackageDexOptimizer(); 247 mPackageAbiHelper = pm.mInjector.getAbiHelper(); 248 mSharedLibraries = pm.mInjector.getSharedLibrariesImpl(); 249 mUpdateOwnershipHelper = pm.mInjector.getUpdateOwnershipHelper(); 250 } 251 252 /** 253 * Commits the package scan and modifies system state. 254 * <p><em>WARNING:</em> The method may throw an exception in the middle 255 * of committing the package, leaving the system in an inconsistent state. 256 * This needs to be fixed so, once we get to this point, no errors are 257 * possible and the system is not left in an inconsistent state. 258 */ 259 @GuardedBy("mPm.mLock") commitReconciledScanResultLocked( @onNull ReconciledPackage reconciledPkg, int[] allUsers)260 private AndroidPackage commitReconciledScanResultLocked( 261 @NonNull ReconciledPackage reconciledPkg, int[] allUsers) { 262 final InstallRequest request = reconciledPkg.mInstallRequest; 263 // TODO(b/135203078): Move this even further away 264 ParsedPackage parsedPackage = request.getParsedPackage(); 265 if (parsedPackage != null && "android".equals(parsedPackage.getPackageName())) { 266 // TODO(b/135203078): Move this to initial parse 267 parsedPackage.setVersionCode(mPm.getSdkVersion()) 268 .setVersionCodeMajor(0); 269 } 270 271 final @PackageManagerService.ScanFlags int scanFlags = request.getScanFlags(); 272 final PackageSetting oldPkgSetting = request.getScanRequestOldPackageSetting(); 273 final PackageSetting originalPkgSetting = request.getScanRequestOriginalPackageSetting(); 274 final String realPkgName = request.getRealPackageName(); 275 final PackageSetting pkgSetting; 276 if (request.getScanRequestPackageSetting() != null) { 277 SharedUserSetting requestSharedUserSetting = mPm.mSettings.getSharedUserSettingLPr( 278 request.getScanRequestPackageSetting()); 279 SharedUserSetting resultSharedUserSetting = mPm.mSettings.getSharedUserSettingLPr( 280 request.getScannedPackageSetting()); 281 if (requestSharedUserSetting != null 282 && requestSharedUserSetting != resultSharedUserSetting) { 283 // shared user changed, remove from old shared user 284 requestSharedUserSetting.removePackage(request.getScanRequestPackageSetting()); 285 // Prune unused SharedUserSetting 286 if (mPm.mSettings.checkAndPruneSharedUserLPw(requestSharedUserSetting, false)) { 287 // Set the app ID in removed info for UID_REMOVED broadcasts 288 request.setRemovedAppId(requestSharedUserSetting.mAppId); 289 } 290 } 291 } 292 if (request.isExistingSettingCopied()) { 293 pkgSetting = request.getScanRequestPackageSetting(); 294 pkgSetting.updateFrom(request.getScannedPackageSetting()); 295 } else { 296 pkgSetting = request.getScannedPackageSetting(); 297 if (originalPkgSetting != null) { 298 mPm.mSettings.addRenamedPackageLPw( 299 AndroidPackageUtils.getRealPackageOrNull(parsedPackage, 300 pkgSetting.isSystem()), 301 originalPkgSetting.getPackageName()); 302 mPm.mTransferredPackages.add(originalPkgSetting.getPackageName()); 303 } else { 304 mPm.mSettings.removeRenamedPackageLPw(parsedPackage.getPackageName()); 305 } 306 } 307 SharedUserSetting sharedUserSetting = mPm.mSettings.getSharedUserSettingLPr(pkgSetting); 308 if (sharedUserSetting != null) { 309 sharedUserSetting.addPackage(pkgSetting); 310 if (parsedPackage.isLeavingSharedUser() 311 && SharedUidMigration.applyStrategy(BEST_EFFORT) 312 && sharedUserSetting.isSingleUser()) { 313 // Attempt the transparent shared UID migration 314 mPm.mSettings.convertSharedUserSettingsLPw(sharedUserSetting); 315 } 316 } 317 if (request.isForceQueryableOverride()) { 318 pkgSetting.setForceQueryableOverride(true); 319 } 320 321 InstallSource installSource = request.getInstallSource(); 322 final boolean isApex = (scanFlags & SCAN_AS_APEX) != 0; 323 final boolean pkgAlreadyExists = oldPkgSetting != null; 324 final String oldUpdateOwner = 325 pkgAlreadyExists ? oldPkgSetting.getInstallSource().mUpdateOwnerPackageName : null; 326 final String updateOwnerFromSysconfig = isApex || !pkgSetting.isSystem() ? null 327 : mPm.mInjector.getSystemConfig().getSystemAppUpdateOwnerPackageName( 328 parsedPackage.getPackageName()); 329 final boolean isUpdateOwnershipDenylisted = 330 mUpdateOwnershipHelper.isUpdateOwnershipDenylisted(parsedPackage.getPackageName()); 331 final boolean isUpdateOwnershipEnabled = oldUpdateOwner != null; 332 333 // For standard install (install via session), the installSource isn't null. 334 if (installSource != null) { 335 // If this is part of a standard install, set the initiating package name, else rely on 336 // previous device state. 337 if (!isInstalledByAdb(installSource.mInitiatingPackageName)) { 338 final PackageSetting ips = mPm.mSettings.getPackageLPr( 339 installSource.mInitiatingPackageName); 340 if (ips != null) { 341 installSource = installSource.setInitiatingPackageSignatures( 342 ips.getSignatures()); 343 } 344 } 345 346 // Handle the update ownership enforcement for APK 347 if (!isApex) { 348 // User installer UID as "current" userId if present; otherwise, use the userId 349 // from InstallRequest. 350 final int userId = installSource.mInstallerPackageUid != Process.INVALID_UID 351 ? UserHandle.getUserId(installSource.mInstallerPackageUid) 352 : request.getUserId(); 353 // Whether the parsedPackage is installed on the userId 354 // If the oldPkgSetting doesn't exist, this package isn't installed for all users. 355 final boolean isUpdate = pkgAlreadyExists && (userId >= UserHandle.USER_SYSTEM 356 // If userID >= 0, we could check via oldPkgSetting.getInstalled(userId). 357 ? oldPkgSetting.getInstalled(userId) 358 // When userId is -1 (USER_ALL) and it's not installed for any user, 359 // treat it as not installed. 360 : oldPkgSetting.getNotInstalledUserIds().length 361 <= (UserManager.isHeadlessSystemUserMode() ? 1 : 0)); 362 final boolean isRequestUpdateOwnership = (request.getInstallFlags() 363 & PackageManager.INSTALL_REQUEST_UPDATE_OWNERSHIP) != 0; 364 final boolean isSameUpdateOwner = 365 TextUtils.equals(oldUpdateOwner, installSource.mInstallerPackageName); 366 final boolean isInstallerUpdateOwnerDenylistProvider = 367 mUpdateOwnershipHelper.isUpdateOwnershipDenyListProvider( 368 installSource.mUpdateOwnerPackageName); 369 370 // Here we handle the update owner for the package, and the rules are: 371 // -. Only enabling update ownership enforcement on initial installation if the 372 // installer has requested. 373 // -. Once the installer changes and users agree to proceed, clear the update 374 // owner (package state in other users are taken into account as well). 375 if (!isUpdate) { 376 if (!isRequestUpdateOwnership 377 || isUpdateOwnershipDenylisted 378 || isInstallerUpdateOwnerDenylistProvider) { 379 installSource = installSource.setUpdateOwnerPackageName(null); 380 } else if ((!isUpdateOwnershipEnabled && pkgAlreadyExists) 381 || (isUpdateOwnershipEnabled && !isSameUpdateOwner)) { 382 installSource = installSource.setUpdateOwnerPackageName(null); 383 } 384 } else if (!isSameUpdateOwner 385 || !isUpdateOwnershipEnabled) { 386 installSource = installSource.setUpdateOwnerPackageName(null); 387 } 388 } 389 390 pkgSetting.setInstallSource(installSource); 391 // For non-standard install (addForInit), installSource is null. 392 } else if (pkgSetting.isSystem()) { 393 // We still honor the manifest attr if the system app wants to opt-out of it. 394 final boolean isSameUpdateOwner = isUpdateOwnershipEnabled 395 && TextUtils.equals(oldUpdateOwner, updateOwnerFromSysconfig); 396 397 // Here we handle the update owner for the system package, and the rules are: 398 // -. We use the update owner from sysconfig as the initial value. 399 // -. Once an app becomes to system app later via OTA, only retains the update 400 // owner if it's consistence with sysconfig. 401 // -. Clear the update owner when update owner changes from sysconfig. 402 if (!pkgAlreadyExists || isSameUpdateOwner) { 403 pkgSetting.setUpdateOwnerPackage(updateOwnerFromSysconfig); 404 } else { 405 pkgSetting.setUpdateOwnerPackage(null); 406 } 407 } 408 409 if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) { 410 boolean isFactory = (scanFlags & SCAN_AS_FACTORY) != 0; 411 pkgSetting.getPkgState().setApkInUpdatedApex(!isFactory); 412 } 413 414 pkgSetting.getPkgState().setApexModuleName(request.getApexModuleName()); 415 416 // TODO(toddke): Consider a method specifically for modifying the Package object 417 // post scan; or, moving this stuff out of the Package object since it has nothing 418 // to do with the package on disk. 419 // We need to have this here because addUserToSettingLPw() is sometimes responsible 420 // for creating the application ID. If we did this earlier, we would be saving the 421 // correct ID. 422 parsedPackage.setUid(pkgSetting.getAppId()); 423 final AndroidPackage pkg = parsedPackage.hideAsFinal(); 424 425 mPm.mSettings.writeUserRestrictionsLPw(pkgSetting, oldPkgSetting); 426 427 if (realPkgName != null) { 428 mPm.mTransferredPackages.add(pkg.getPackageName()); 429 } 430 431 if (reconciledPkg.mCollectedSharedLibraryInfos != null 432 || (oldPkgSetting != null 433 && !oldPkgSetting.getSharedLibraryDependencies().isEmpty())) { 434 // Reconcile if the new package or the old package uses shared libraries. 435 // It is possible that the old package uses shared libraries but the new one doesn't. 436 mSharedLibraries.executeSharedLibrariesUpdate(pkg, pkgSetting, null, null, 437 reconciledPkg.mCollectedSharedLibraryInfos, allUsers); 438 } 439 440 final KeySetManagerService ksms = mPm.mSettings.getKeySetManagerService(); 441 if (reconciledPkg.mRemoveAppKeySetData) { 442 ksms.removeAppKeySetDataLPw(pkg.getPackageName()); 443 } 444 if (reconciledPkg.mSharedUserSignaturesChanged) { 445 sharedUserSetting.signaturesChanged = Boolean.TRUE; 446 sharedUserSetting.signatures.mSigningDetails = reconciledPkg.mSigningDetails; 447 } 448 pkgSetting.setSigningDetails(reconciledPkg.mSigningDetails); 449 450 final int userId = request.getUserId(); 451 // Modify state for the given package setting 452 commitPackageSettings(pkg, pkgSetting, oldPkgSetting, reconciledPkg); 453 if (pkgSetting.getInstantApp(userId)) { 454 mPm.mInstantAppRegistry.addInstantApp(userId, pkgSetting.getAppId()); 455 } 456 457 if (!IncrementalManager.isIncrementalPath(pkgSetting.getPathString())) { 458 pkgSetting.setLoadingProgress(1f); 459 } 460 461 // TODO: passes the package name as an argument in a message to the handler for V+ 462 // so we don't need to rely on creating lambda objects so frequently. 463 if (UpdateOwnershipHelper.hasValidOwnershipDenyList(pkgSetting)) { 464 mPm.mHandler.post(() -> handleUpdateOwnerDenyList(pkgSetting)); 465 } 466 return pkg; 467 } 468 handleUpdateOwnerDenyList(PackageSetting pkgSetting)469 private void handleUpdateOwnerDenyList(PackageSetting pkgSetting) { 470 ArraySet<String> listItems = mUpdateOwnershipHelper.readUpdateOwnerDenyList(pkgSetting); 471 if (listItems != null && !listItems.isEmpty()) { 472 mUpdateOwnershipHelper.addToUpdateOwnerDenyList(pkgSetting.getPackageName(), 473 listItems); 474 SystemConfig config = SystemConfig.getInstance(); 475 synchronized (mPm.mLock) { 476 for (String unownedPackage : listItems) { 477 PackageSetting unownedSetting = mPm.mSettings.getPackageLPr(unownedPackage); 478 if (unownedSetting != null 479 && config.getSystemAppUpdateOwnerPackageName(unownedPackage) == null) { 480 unownedSetting.setUpdateOwnerPackage(null); 481 } 482 } 483 } 484 } 485 } 486 487 /** 488 * Adds a scanned package to the system. When this method is finished, the package will 489 * be available for query, resolution, etc... 490 */ commitPackageSettings(@onNull AndroidPackage pkg, @NonNull PackageSetting pkgSetting, @Nullable PackageSetting oldPkgSetting, ReconciledPackage reconciledPkg)491 private void commitPackageSettings(@NonNull AndroidPackage pkg, 492 @NonNull PackageSetting pkgSetting, @Nullable PackageSetting oldPkgSetting, 493 ReconciledPackage reconciledPkg) { 494 final String pkgName = pkg.getPackageName(); 495 final InstallRequest request = reconciledPkg.mInstallRequest; 496 final AndroidPackage oldPkg = request.getScanRequestOldPackage(); 497 final int scanFlags = request.getScanFlags(); 498 final boolean chatty = (request.getParseFlags() & ParsingPackageUtils.PARSE_CHATTY) != 0; 499 if (mPm.mCustomResolverComponentName != null 500 && mPm.mCustomResolverComponentName.getPackageName().equals(pkg.getPackageName())) { 501 mPm.setUpCustomResolverActivity(pkg, pkgSetting); 502 } 503 504 // When upgrading a package, clear the app metadata file path for the new package. 505 if (oldPkgSetting != null 506 && oldPkgSetting.getLastUpdateTime() < pkgSetting.getLastUpdateTime()) { 507 pkgSetting.setAppMetadataFilePath(null); 508 pkgSetting.setAppMetadataSource(APP_METADATA_SOURCE_UNKNOWN); 509 } 510 // If the app metadata file path is not null then this is a system app with a preloaded app 511 // metadata file on the system image. Do not reset the path and source if this is the 512 // case. 513 if (pkgSetting.getAppMetadataFilePath() == null) { 514 String dir = pkg.getPath(); 515 if (pkgSetting.isSystem()) { 516 dir = Environment.getDataDirectoryPath() + "/app-metadata/" + pkg.getPackageName(); 517 } 518 String appMetadataFilePath = dir + "/" + APP_METADATA_FILE_NAME; 519 if (request.hasAppMetadataFile()) { 520 pkgSetting.setAppMetadataFilePath(appMetadataFilePath); 521 if (Flags.aslInApkAppMetadataSource()) { 522 pkgSetting.setAppMetadataSource(APP_METADATA_SOURCE_INSTALLER); 523 } 524 } else if (Flags.aslInApkAppMetadataSource()) { 525 Map<String, PackageManager.Property> properties = pkg.getProperties(); 526 if (properties.containsKey(PROPERTY_ANDROID_SAFETY_LABEL)) { 527 // ASL file extraction is done in post-install 528 pkgSetting.setAppMetadataFilePath(appMetadataFilePath); 529 pkgSetting.setAppMetadataSource(APP_METADATA_SOURCE_APK); 530 } 531 } 532 } 533 534 if (pkg.getPackageName().equals("android")) { 535 mPm.setPlatformPackage(pkg, pkgSetting); 536 } 537 538 // writer 539 ArrayList<AndroidPackage> clientLibPkgs = 540 mSharedLibraries.commitSharedLibraryChanges(pkg, pkgSetting, 541 reconciledPkg.mAllowedSharedLibraryInfos, 542 reconciledPkg.getCombinedAvailablePackages(), scanFlags); 543 544 request.setLibraryConsumers(clientLibPkgs); 545 546 if ((scanFlags & SCAN_BOOTING) != 0) { 547 // No apps can run during boot scan, so they don't need to be frozen 548 } else if ((scanFlags & SCAN_DONT_KILL_APP) != 0) { 549 // Caller asked to not kill app, so it's probably not frozen 550 } else if ((scanFlags & SCAN_IGNORE_FROZEN) != 0) { 551 // Caller asked us to ignore frozen check for some reason; they 552 // probably didn't know the package name 553 } else { 554 // We're doing major surgery on this package, so it better be frozen 555 // right now to keep it from launching 556 mPm.snapshotComputer().checkPackageFrozen(pkgName); 557 } 558 559 final boolean isReplace = request.isInstallReplace(); 560 // Also need to kill any apps that are dependent on the library, except the case of 561 // installation of new version static shared library. 562 if (clientLibPkgs != null) { 563 if (pkg.getStaticSharedLibraryName() == null || isReplace) { 564 for (int i = 0; i < clientLibPkgs.size(); i++) { 565 AndroidPackage clientPkg = clientLibPkgs.get(i); 566 String packageName = clientPkg.getPackageName(); 567 mPm.killApplication(packageName, 568 clientPkg.getUid(), "update lib", 569 ApplicationExitInfo.REASON_DEPENDENCY_DIED); 570 } 571 } 572 } 573 574 // writer 575 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings"); 576 577 synchronized (mPm.mLock) { 578 // We don't expect installation to fail beyond this point 579 // Add the new setting to mSettings 580 mPm.mSettings.insertPackageSettingLPw(pkgSetting, pkg); 581 // Add the new setting to mPackages 582 mPm.mPackages.put(pkg.getPackageName(), pkg); 583 if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) { 584 mApexManager.registerApkInApex(pkg); 585 } 586 587 if ((mPm.isDeviceUpgrading() && pkgSetting.isSystem()) || isReplace) { 588 for (int userId : mPm.mUserManager.getUserIds()) { 589 pkgSetting.restoreComponentSettings(userId); 590 } 591 } 592 593 // Don't add keysets for APEX as their package settings are not persisted and will 594 // result in orphaned keysets. 595 if ((scanFlags & SCAN_AS_APEX) == 0) { 596 // Add the package's KeySets to the global KeySetManagerService 597 KeySetManagerService ksms = mPm.mSettings.getKeySetManagerService(); 598 ksms.addScannedPackageLPw(pkg); 599 } 600 601 final Computer snapshot = mPm.snapshotComputer(); 602 mPm.mComponentResolver.addAllComponents(pkg, chatty, mPm.mSetupWizardPackage, snapshot); 603 mPm.mAppsFilter.addPackage(snapshot, pkgSetting, isReplace, 604 (scanFlags & SCAN_DONT_KILL_APP) != 0 /* retainImplicitGrantOnReplace */); 605 mPm.addAllPackageProperties(pkg); 606 607 // Only verify app links for non-archival installations, otherwise there won't be any 608 // declared app links. 609 if (!request.isArchived()) { 610 if (oldPkgSetting == null || oldPkgSetting.getPkg() == null) { 611 mPm.mDomainVerificationManager.addPackage(pkgSetting, 612 request.getPreVerifiedDomains()); 613 } else { 614 mPm.mDomainVerificationManager.migrateState(oldPkgSetting, pkgSetting, 615 request.getPreVerifiedDomains()); 616 } 617 } 618 619 int collectionSize = ArrayUtils.size(pkg.getInstrumentations()); 620 StringBuilder r = null; 621 int i; 622 for (i = 0; i < collectionSize; i++) { 623 ParsedInstrumentation a = pkg.getInstrumentations().get(i); 624 ComponentMutateUtils.setPackageName(a, pkg.getPackageName()); 625 mPm.addInstrumentation(a.getComponentName(), a); 626 if (chatty) { 627 if (r == null) { 628 r = new StringBuilder(256); 629 } else { 630 r.append(' '); 631 } 632 r.append(a.getName()); 633 } 634 } 635 if (r != null) { 636 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Instrumentation: " + r); 637 } 638 639 final List<String> protectedBroadcasts = pkg.getProtectedBroadcasts(); 640 if (!protectedBroadcasts.isEmpty()) { 641 synchronized (mPm.mProtectedBroadcasts) { 642 mPm.mProtectedBroadcasts.addAll(protectedBroadcasts); 643 } 644 } 645 646 mPm.mPermissionManager.onPackageAdded(pkgSetting, 647 (scanFlags & SCAN_AS_INSTANT_APP) != 0, oldPkg); 648 } 649 650 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 651 } 652 installExistingPackageAsUser(@ullable String packageName, @UserIdInt int userId, @PackageManager.InstallFlags int installFlags, @PackageManager.InstallReason int installReason, @Nullable List<String> allowlistedRestrictedPermissions, @Nullable IntentSender intentSender)653 public Pair<Integer, IntentSender> installExistingPackageAsUser(@Nullable String packageName, 654 @UserIdInt int userId, @PackageManager.InstallFlags int installFlags, 655 @PackageManager.InstallReason int installReason, 656 @Nullable List<String> allowlistedRestrictedPermissions, 657 @Nullable IntentSender intentSender) { 658 if (DEBUG_INSTALL) { 659 Log.v(TAG, "installExistingPackageAsUser package=" + packageName + " userId=" + userId 660 + " installFlags=" + installFlags + " installReason=" + installReason 661 + " allowlistedRestrictedPermissions=" + allowlistedRestrictedPermissions); 662 } 663 664 final int callingUid = Binder.getCallingUid(); 665 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES) 666 != PackageManager.PERMISSION_GRANTED 667 && mContext.checkCallingOrSelfPermission( 668 android.Manifest.permission.INSTALL_EXISTING_PACKAGES) 669 != PackageManager.PERMISSION_GRANTED) { 670 throw new SecurityException("Neither user " + callingUid + " nor current process has " 671 + android.Manifest.permission.INSTALL_PACKAGES + "."); 672 } 673 PackageSetting pkgSetting; 674 final Computer preLockSnapshot = mPm.snapshotComputer(); 675 preLockSnapshot.enforceCrossUserPermission(callingUid, userId, 676 true /* requireFullPermission */, true /* checkShell */, 677 "installExistingPackage for user " + userId); 678 if (mPm.isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) { 679 return Pair.create(PackageManager.INSTALL_FAILED_USER_RESTRICTED, intentSender); 680 } 681 682 final long callingId = Binder.clearCallingIdentity(); 683 try { 684 boolean installed = false; 685 final boolean instantApp = 686 (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0; 687 final boolean fullApp = 688 (installFlags & PackageManager.INSTALL_FULL_APP) != 0; 689 690 // writer 691 synchronized (mPm.mLock) { 692 final Computer snapshot = mPm.snapshotComputer(); 693 pkgSetting = mPm.mSettings.getPackageLPr(packageName); 694 if (pkgSetting == null || pkgSetting.getPkg() == null) { 695 return Pair.create(PackageManager.INSTALL_FAILED_INVALID_URI, intentSender); 696 } 697 if (instantApp && (pkgSetting.isSystem() || pkgSetting.isUpdatedSystemApp())) { 698 return Pair.create(PackageManager.INSTALL_FAILED_INVALID_URI, intentSender); 699 } 700 if (!snapshot.canViewInstantApps(callingUid, UserHandle.getUserId(callingUid))) { 701 // only allow the existing package to be used if it's installed as a full 702 // application for at least one user 703 boolean installAllowed = false; 704 for (int checkUserId : mPm.mUserManager.getUserIds()) { 705 installAllowed = !pkgSetting.getInstantApp(checkUserId); 706 if (installAllowed) { 707 break; 708 } 709 } 710 if (!installAllowed) { 711 return Pair.create(PackageManager.INSTALL_FAILED_INVALID_URI, intentSender); 712 } 713 } 714 if (!pkgSetting.getInstalled(userId)) { 715 pkgSetting.setInstalled(true, userId); 716 pkgSetting.setHidden(false, userId); 717 pkgSetting.setInstallReason(installReason, userId); 718 pkgSetting.setUninstallReason(PackageManager.UNINSTALL_REASON_UNKNOWN, userId); 719 pkgSetting.setFirstInstallTime(System.currentTimeMillis(), userId); 720 // Clear any existing archive state. 721 mPm.mInstallerService.mPackageArchiver.clearArchiveState(pkgSetting, userId); 722 mPm.mSettings.writePackageRestrictionsLPr(userId); 723 mPm.mSettings.writeKernelMappingLPr(pkgSetting); 724 installed = true; 725 } else if (fullApp && pkgSetting.getInstantApp(userId)) { 726 // upgrade app from instant to full; we don't allow app downgrade 727 installed = true; 728 } 729 ScanPackageUtils.setInstantAppForUser(mPm.mInjector, pkgSetting, userId, instantApp, 730 fullApp); 731 } 732 733 if (installed) { 734 final String updateOwner = pkgSetting.getInstallSource().mUpdateOwnerPackageName; 735 final var dpmi = mInjector.getLocalService(DevicePolicyManagerInternal.class); 736 final boolean isFromManagedUserOrProfile = 737 dpmi != null && dpmi.isUserOrganizationManaged(userId); 738 // Here we handle the update owner when install existing package, and the rules are: 739 // -. Retain the update owner when enable a system app in managed user or profile. 740 // -. Retain the update owner if the installer is the same. 741 // -. Clear the update owner when update owner changes. 742 if (!preLockSnapshot.isCallerSameApp(updateOwner, callingUid) 743 && (!pkgSetting.isSystem() || !isFromManagedUserOrProfile)) { 744 pkgSetting.setUpdateOwnerPackage(null); 745 } 746 if (pkgSetting.getPkg() != null) { 747 final PermissionManagerServiceInternal.PackageInstalledParams.Builder 748 permissionParamsBuilder = 749 new PermissionManagerServiceInternal.PackageInstalledParams.Builder(); 750 if ((installFlags & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) 751 != 0) { 752 permissionParamsBuilder.setAllowlistedRestrictedPermissions( 753 new ArrayList<>(pkgSetting.getPkg().getRequestedPermissions())); 754 } 755 mPm.mPermissionManager.onPackageInstalled(pkgSetting.getPkg(), 756 Process.INVALID_UID /* previousAppId */, 757 permissionParamsBuilder.build(), userId); 758 759 try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { 760 // We don't need to freeze for a brand new install 761 mAppDataHelper.prepareAppDataPostCommitLIF( 762 pkgSetting, /* previousAppId= */0, new int[] { userId }); 763 } 764 } 765 // TODO(b/278553670) Store archive state for the user. 766 boolean isArchived = (pkgSetting.getPkg() == null); 767 mBroadcastHelper.sendPackageAddedForUser(mPm.snapshotComputer(), packageName, 768 pkgSetting, userId, isArchived, DataLoaderType.NONE, 769 mPm.mAppPredictionServicePackage); 770 synchronized (mPm.mLock) { 771 mPm.updateSequenceNumberLP(pkgSetting, new int[]{ userId }); 772 } 773 // start async restore with no post-install since we finish install here 774 775 final IntentSender onCompleteSender = intentSender; 776 intentSender = null; 777 778 InstallRequest request = new InstallRequest(userId, 779 PackageManager.INSTALL_SUCCEEDED, pkgSetting.getPkg(), new int[]{ userId }, 780 () -> { 781 mPm.restorePermissionsAndUpdateRolesForNewUserInstall(packageName, 782 userId); 783 if (onCompleteSender != null) { 784 onInstallComplete(PackageManager.INSTALL_SUCCEEDED, mContext, 785 onCompleteSender); 786 } 787 }, pkgSetting.getAppId(), callingUid, pkgSetting.isSystem()); 788 restoreAndPostInstall(request); 789 } 790 } finally { 791 Binder.restoreCallingIdentity(callingId); 792 } 793 794 return Pair.create(PackageManager.INSTALL_SUCCEEDED, intentSender); 795 } 796 onInstallComplete(int returnCode, Context context, IntentSender target)797 static void onInstallComplete(int returnCode, Context context, IntentSender target) { 798 Intent fillIn = new Intent(); 799 fillIn.putExtra(PackageInstaller.EXTRA_STATUS, 800 PackageManager.installStatusToPublicStatus(returnCode)); 801 try { 802 final BroadcastOptions options = BroadcastOptions.makeBasic(); 803 options.setPendingIntentBackgroundActivityLaunchAllowed(false); 804 target.sendIntent(context, 0, fillIn, null /* onFinished*/, null /* handler */, 805 null /* requiredPermission */, options.toBundle()); 806 } catch (IntentSender.SendIntentException ignored) { 807 } 808 } 809 restoreAndPostInstall(InstallRequest request)810 public void restoreAndPostInstall(InstallRequest request) { 811 final int userId = request.getUserId(); 812 if (DEBUG_INSTALL) { 813 Log.v(TAG, 814 "restoreAndPostInstall userId=" + userId + " package=" + request.getPkg()); 815 } 816 817 PackageSetting packageSetting = null; 818 819 final boolean update = request.isUpdate(); 820 boolean doRestore = false; 821 if (request.getPkg() != null && !request.isArchived()) { 822 // A restore should be requested at this point: 823 // if the install succeeded and it's not an archived install 824 if (!update) { 825 // AND the operation is not an update, 826 doRestore = true; 827 } else { 828 // OR the package has never been restored. 829 String packageName = request.getPkg().getPackageName(); 830 synchronized (mPm.mLock) { 831 packageSetting = mPm.mSettings.getPackageLPr(packageName); 832 if (packageSetting != null && packageSetting.isPendingRestore()) { 833 doRestore = true; 834 } 835 } 836 } 837 } 838 839 // Set up the post-install work request bookkeeping. This will be used 840 // and cleaned up by the post-install event handling regardless of whether 841 // there's a restore pass performed. Token values are >= 1. 842 int token; 843 if (mPm.mNextInstallToken < 0) mPm.mNextInstallToken = 1; 844 token = mPm.mNextInstallToken++; 845 mPm.mRunningInstalls.put(token, request); 846 847 if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token); 848 849 final boolean succeeded = request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED; 850 if (succeeded && doRestore) { 851 // Pass responsibility to the Backup Manager. It will perform a 852 // restore if appropriate, then pass responsibility back to the 853 // Package Manager to run the post-install observer callbacks 854 // and broadcasts. 855 request.closeFreezer(); 856 doRestore = performBackupManagerRestore(userId, token, request); 857 } 858 859 // If this is an update to a package that might be potentially downgraded, then we 860 // need to check with the rollback manager whether there's any userdata that might 861 // need to be snapshotted or restored for the package. 862 // 863 // TODO(narayan): Get this working for cases where userId == UserHandle.USER_ALL. 864 if (succeeded && !doRestore && update) { 865 doRestore = performRollbackManagerRestore(userId, token, request); 866 } 867 868 if (succeeded && doRestore && !request.hasPostInstallRunnable()) { 869 boolean hasNeverBeenRestored = 870 packageSetting != null && packageSetting.isPendingRestore(); 871 request.setPostInstallRunnable(() -> { 872 // Permissions should be restored on each user that has the app installed for the 873 // first time, unless it's an unarchive install for an archived app, in which case 874 // the permissions should be restored on each user that has the app updated. 875 int[] userIdsToRestorePermissions = hasNeverBeenRestored 876 ? request.getUpdateBroadcastUserIds() 877 : request.getFirstTimeBroadcastUserIds(); 878 for (int restorePermissionUserId : userIdsToRestorePermissions) { 879 mPm.restorePermissionsAndUpdateRolesForNewUserInstall(request.getName(), 880 restorePermissionUserId); 881 } 882 }); 883 } 884 885 if (doRestore) { 886 if (packageSetting != null) { 887 synchronized (mPm.mLock) { 888 packageSetting.setPendingRestore(false); 889 } 890 } 891 } else { 892 // No restore possible, or the Backup Manager was mysteriously not 893 // available -- just fire the post-install work request directly. 894 if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token); 895 896 Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall", token); 897 898 Message msg = mPm.mHandler.obtainMessage(POST_INSTALL, token, 0); 899 mPm.mHandler.sendMessage(msg); 900 } 901 } 902 903 /** 904 * Perform Backup Manager restore for a given {@link InstallRequest}. 905 * Returns whether the restore successfully completed. 906 */ performBackupManagerRestore(int userId, int token, InstallRequest request)907 private boolean performBackupManagerRestore(int userId, int token, InstallRequest request) { 908 if (request.getPkg() == null) { 909 return false; 910 } 911 IBackupManager iBackupManager = mInjector.getIBackupManager(); 912 if (iBackupManager != null) { 913 // For backwards compatibility as USER_ALL previously routed directly to USER_SYSTEM 914 // in the BackupManager. USER_ALL is used in compatibility tests. 915 if (userId == UserHandle.USER_ALL) { 916 userId = UserHandle.USER_SYSTEM; 917 } 918 if (DEBUG_INSTALL) { 919 Log.v(TAG, "token " + token + " to BM for possible restore for user " + userId); 920 } 921 Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "restore", token); 922 try { 923 if (iBackupManager.isUserReadyForBackup(userId)) { 924 iBackupManager.restoreAtInstallForUser( 925 userId, request.getPkg().getPackageName(), token); 926 } else { 927 Slog.w(TAG, "User " + userId + " is not ready. Restore at install " 928 + "didn't take place."); 929 return false; 930 } 931 } catch (RemoteException e) { 932 // can't happen; the backup manager is local 933 } catch (Exception e) { 934 Slog.e(TAG, "Exception trying to enqueue restore", e); 935 return false; 936 } 937 } else { 938 Slog.e(TAG, "Backup Manager not found!"); 939 return false; 940 } 941 return true; 942 } 943 944 /** 945 * Perform Rollback Manager restore for a given {@link InstallRequest}. 946 * Returns whether the restore successfully completed. 947 */ performRollbackManagerRestore(int userId, int token, InstallRequest request)948 private boolean performRollbackManagerRestore(int userId, int token, InstallRequest request) { 949 if (request.getPkg() == null) { 950 return false; 951 } 952 final String packageName = request.getPkg().getPackageName(); 953 final int[] allUsers = mPm.mUserManager.getUserIds(); 954 final int[] installedUsers; 955 956 final PackageSetting ps; 957 int appId = -1; 958 long ceDataInode = -1; 959 synchronized (mPm.mLock) { 960 ps = mPm.mSettings.getPackageLPr(packageName); 961 if (ps != null) { 962 appId = ps.getAppId(); 963 ceDataInode = ps.getCeDataInode(userId); 964 // NOTE: We ignore the user specified in the InstallParam because we know this is 965 // an update, and hence need to restore data for all installed users. 966 installedUsers = ps.queryInstalledUsers(allUsers, true); 967 } else { 968 installedUsers = new int[0]; 969 } 970 } 971 972 final int installFlags = request.getInstallFlags(); 973 boolean doSnapshotOrRestore = ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0 974 || (installFlags & PackageManager.INSTALL_REQUEST_DOWNGRADE) != 0); 975 976 if (ps != null && doSnapshotOrRestore) { 977 final String seInfo = ps.getSeInfo(); 978 final RollbackManagerInternal rollbackManager = 979 mInjector.getLocalService(RollbackManagerInternal.class); 980 rollbackManager.snapshotAndRestoreUserData(packageName, 981 UserHandle.toUserHandles(installedUsers), appId, ceDataInode, seInfo, token); 982 return true; 983 } 984 return false; 985 } 986 installPackagesTraced(List<InstallRequest> requests)987 void installPackagesTraced(List<InstallRequest> requests) { 988 try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { 989 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages"); 990 installPackagesLI(requests); 991 } finally { 992 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 993 } 994 } 995 996 /** 997 * Installs one or more packages atomically. This operation is broken up into four phases: 998 * <ul> 999 * <li><b>Prepare</b> 1000 * <br/>Analyzes any current install state, parses the package and does initial 1001 * validation on it.</li> 1002 * <li><b>Scan</b> 1003 * <br/>Interrogates the parsed packages given the context collected in prepare.</li> 1004 * <li><b>Reconcile</b> 1005 * <br/>Validates scanned packages in the context of each other and the current system 1006 * state to ensure that the install will be successful. 1007 * <li><b>Commit</b> 1008 * <br/>Commits all scanned packages and updates system state. This is the only place 1009 * that system state may be modified in the install flow and all predictable errors 1010 * must be determined before this phase.</li> 1011 * </ul> 1012 * 1013 * Failure at any phase will result in a full failure to install all packages. 1014 */ 1015 @GuardedBy("mPm.mInstallLock") installPackagesLI(List<InstallRequest> requests)1016 private void installPackagesLI(List<InstallRequest> requests) { 1017 final Set<String> scannedPackages = new ArraySet<>(requests.size()); 1018 final Map<String, Settings.VersionInfo> versionInfos = new ArrayMap<>(requests.size()); 1019 final Map<String, Boolean> createdAppId = new ArrayMap<>(requests.size()); 1020 CriticalEventLog.getInstance().logInstallPackagesStarted(); 1021 boolean success = false; 1022 try { 1023 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI"); 1024 for (InstallRequest request : requests) { 1025 try { 1026 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage"); 1027 request.onPrepareStarted(); 1028 preparePackageLI(request); 1029 } catch (PrepareFailure prepareFailure) { 1030 request.setError(prepareFailure.error, 1031 prepareFailure.getMessage()); 1032 request.setOriginPackage(prepareFailure.mConflictingPackage); 1033 request.setOriginPermission(prepareFailure.mConflictingPermission); 1034 return; 1035 } finally { 1036 request.onPrepareFinished(); 1037 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 1038 } 1039 1040 final ParsedPackage packageToScan = request.getParsedPackage(); 1041 if (packageToScan == null) { 1042 request.setError(INSTALL_FAILED_SESSION_INVALID, 1043 "Failed to obtain package to scan"); 1044 return; 1045 } 1046 request.setReturnCode(PackageManager.INSTALL_SUCCEEDED); 1047 final String packageName = packageToScan.getPackageName(); 1048 try { 1049 request.onScanStarted(); 1050 final ScanResult scanResult = scanPackageTracedLI(request.getParsedPackage(), 1051 request.getParseFlags(), request.getScanFlags(), 1052 System.currentTimeMillis(), request.getUser(), 1053 request.getAbiOverride()); 1054 request.setScanResult(scanResult); 1055 request.onScanFinished(); 1056 if (!scannedPackages.add(packageName)) { 1057 request.setError( 1058 PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE, 1059 "Duplicate package " 1060 + packageName 1061 + " in multi-package install request."); 1062 return; 1063 } 1064 if (!checkNoAppStorageIsConsistent( 1065 request.getScanRequestOldPackage(), packageToScan)) { 1066 // TODO: INSTALL_FAILED_UPDATE_INCOMPATIBLE is about incomptabible 1067 // signatures. Is there a better error code? 1068 request.setError( 1069 INSTALL_FAILED_UPDATE_INCOMPATIBLE, 1070 "Update attempted to change value of " 1071 + PackageManager.PROPERTY_NO_APP_DATA_STORAGE); 1072 return; 1073 } 1074 final boolean isApex = (request.getScanFlags() & SCAN_AS_APEX) != 0; 1075 final boolean isSdkLibrary = packageToScan.isSdkLibrary(); 1076 if (isApex || (isSdkLibrary && disallowSdkLibsToBeApps())) { 1077 request.getScannedPackageSetting().setAppId(Process.INVALID_UID); 1078 } else { 1079 createdAppId.put(packageName, optimisticallyRegisterAppId(request)); 1080 } 1081 versionInfos.put(packageName, 1082 mPm.getSettingsVersionForPackage(packageToScan)); 1083 } catch (PackageManagerException e) { 1084 request.setError("Scanning Failed.", e); 1085 return; 1086 } 1087 if (request.isArchived()) { 1088 final SparseArray<String> responsibleInstallerTitles = 1089 PackageArchiver.getResponsibleInstallerTitles(mContext, 1090 mPm.snapshotComputer(), request.getInstallSource(), 1091 request.getUserId(), mPm.mUserManager.getUserIds()); 1092 if (responsibleInstallerTitles == null 1093 || responsibleInstallerTitles.size() == 0) { 1094 request.setError(PackageManagerException.ofInternalError( 1095 "Failed to obtain the responsible installer info", 1096 INTERNAL_ERROR_ARCHIVE_NO_INSTALLER_TITLE)); 1097 return; 1098 } 1099 request.setResponsibleInstallerTitles(responsibleInstallerTitles); 1100 } 1101 } 1102 1103 List<ReconciledPackage> reconciledPackages; 1104 synchronized (mPm.mLock) { 1105 try { 1106 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages"); 1107 reconciledPackages = ReconcilePackageUtils.reconcilePackages( 1108 requests, Collections.unmodifiableMap(mPm.mPackages), 1109 versionInfos, mSharedLibraries, mPm.mSettings.getKeySetManagerService(), 1110 mPm.mSettings, mPm.mInjector.getSystemConfig()); 1111 } catch (ReconcileFailure e) { 1112 for (InstallRequest request : requests) { 1113 request.setError("Reconciliation failed...", e); 1114 } 1115 return; 1116 } finally { 1117 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 1118 } 1119 if (Flags.improveInstallFreeze()) { 1120 // Postpone freezer until after reconcile 1121 for (ReconciledPackage reconciledPkg : reconciledPackages) { 1122 InstallRequest installRequest = reconciledPkg.mInstallRequest; 1123 String packageName = installRequest.getParsedPackage().getPackageName(); 1124 PackageFreezer freezer = freezePackageForInstall(packageName, 1125 UserHandle.USER_ALL, installRequest.getInstallFlags(), 1126 "installPackageLI", ApplicationExitInfo.REASON_PACKAGE_UPDATED, 1127 installRequest); 1128 installRequest.setFreezer(freezer); 1129 } 1130 } 1131 try { 1132 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "commitPackages"); 1133 commitPackagesLocked(reconciledPackages, mPm.mUserManager.getUserIds()); 1134 success = true; 1135 } finally { 1136 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 1137 } 1138 } 1139 executePostCommitStepsLIF(reconciledPackages); 1140 } finally { 1141 if (success) { 1142 for (InstallRequest request : requests) { 1143 if (request.getDataLoaderType() != DataLoaderType.INCREMENTAL) { 1144 continue; 1145 } 1146 if (request.getSignatureSchemeVersion() != SIGNING_BLOCK_V4) { 1147 continue; 1148 } 1149 // For incremental installs, we bypass the verifier prior to install. Now 1150 // that we know the package is valid, send a notice to the verifier with 1151 // the root hash of the base.apk. 1152 final String baseCodePath = request.getPkg().getBaseApkPath(); 1153 final String[] splitCodePaths = request.getPkg().getSplitCodePaths(); 1154 final Uri originUri = request.getOriginUri(); 1155 final int verificationId = mPm.mPendingVerificationToken++; 1156 final String rootHashString = PackageManagerServiceUtils 1157 .buildVerificationRootHashString(baseCodePath, splitCodePaths); 1158 VerificationUtils.broadcastPackageVerified(verificationId, originUri, 1159 PackageManager.VERIFICATION_ALLOW, rootHashString, 1160 request.getDataLoaderType(), request.getUser(), mContext); 1161 } 1162 } else { 1163 for (InstallRequest installRequest : requests) { 1164 if (installRequest.getParsedPackage() != null && createdAppId.getOrDefault( 1165 installRequest.getParsedPackage().getPackageName(), false)) { 1166 cleanUpAppIdCreation(installRequest); 1167 } 1168 } 1169 // TODO(b/194319951): create a more descriptive reason than unknown 1170 // mark all non-failure installs as UNKNOWN so we do not treat them as success 1171 for (InstallRequest request : requests) { 1172 request.closeFreezer(); 1173 if (request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED) { 1174 request.setReturnCode(PackageManager.INSTALL_UNKNOWN); 1175 } 1176 } 1177 } 1178 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 1179 } 1180 } 1181 1182 @GuardedBy("mPm.mInstallLock") checkNoAppStorageIsConsistent(AndroidPackage oldPkg, AndroidPackage newPkg)1183 private boolean checkNoAppStorageIsConsistent(AndroidPackage oldPkg, AndroidPackage newPkg) { 1184 if (oldPkg == null) { 1185 // New install, nothing to check against. 1186 return true; 1187 } 1188 final PackageManager.Property curProp = 1189 oldPkg.getProperties().get(PackageManager.PROPERTY_NO_APP_DATA_STORAGE); 1190 final PackageManager.Property newProp = 1191 newPkg.getProperties().get(PackageManager.PROPERTY_NO_APP_DATA_STORAGE); 1192 if (curProp == null || !curProp.getBoolean()) { 1193 return newProp == null || !newProp.getBoolean(); 1194 } 1195 return newProp != null && newProp.getBoolean(); 1196 } 1197 1198 @GuardedBy("mPm.mInstallLock") preparePackageLI(InstallRequest request)1199 private void preparePackageLI(InstallRequest request) throws PrepareFailure { 1200 final int[] allUsers = mPm.mUserManager.getUserIds(); 1201 final int installFlags = request.getInstallFlags(); 1202 final boolean onExternal = request.getVolumeUuid() != null; 1203 final boolean instantApp = ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0); 1204 final boolean fullApp = ((installFlags & PackageManager.INSTALL_FULL_APP) != 0); 1205 final boolean virtualPreload = 1206 ((installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0); 1207 final boolean isApex = ((installFlags & PackageManager.INSTALL_APEX) != 0); 1208 final boolean isRollback = 1209 request.getInstallReason() == PackageManager.INSTALL_REASON_ROLLBACK; 1210 @PackageManagerService.ScanFlags int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE; 1211 if (request.isInstallMove()) { 1212 // moving a complete application; perform an initial scan on the new install location 1213 scanFlags |= SCAN_INITIAL; 1214 } 1215 if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) { 1216 scanFlags |= SCAN_DONT_KILL_APP; 1217 } 1218 if (instantApp) { 1219 scanFlags |= SCAN_AS_INSTANT_APP; 1220 } 1221 if (fullApp) { 1222 scanFlags |= SCAN_AS_FULL_APP; 1223 } 1224 if (virtualPreload) { 1225 scanFlags |= SCAN_AS_VIRTUAL_PRELOAD; 1226 } 1227 if (isApex) { 1228 scanFlags |= SCAN_AS_APEX; 1229 } 1230 1231 final File tmpPackageFile = new File( 1232 isApex ? request.getApexInfo().modulePath : request.getCodePath()); 1233 if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile); 1234 1235 // Validity check 1236 if (instantApp && onExternal) { 1237 Slog.i(TAG, "Incompatible ephemeral install; external=" + onExternal); 1238 throw new PrepareFailure(PackageManager.INSTALL_FAILED_SESSION_INVALID); 1239 } 1240 1241 // Retrieve PackageSettings and parse package 1242 @ParsingPackageUtils.ParseFlags final int parseFlags = 1243 mPm.getDefParseFlags() | ParsingPackageUtils.PARSE_CHATTY 1244 | ParsingPackageUtils.PARSE_ENFORCE_CODE 1245 | (onExternal ? ParsingPackageUtils.PARSE_EXTERNAL_STORAGE : 0); 1246 1247 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage"); 1248 final ParsedPackage parsedPackage; 1249 final ArchivedPackageParcel archivedPackage; 1250 try (PackageParser2 pp = mPm.mInjector.getPreparingPackageParser()) { 1251 if (request.getPackageLite() == null || !request.isArchived()) { 1252 // TODO: pass packageLite from install request instead of reparsing the package 1253 parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false); 1254 AndroidPackageUtils.validatePackageDexMetadata(parsedPackage); 1255 archivedPackage = null; 1256 } else { 1257 // Archived install mode, no APK. 1258 parsedPackage = pp.parsePackageFromPackageLite(request.getPackageLite(), 1259 parseFlags); 1260 archivedPackage = request.getPackageLite().getArchivedPackage(); 1261 } 1262 } catch (PackageParserException e) { 1263 throw new PrepareFailure(e.error, 1264 ExceptionUtils.getCompleteMessage("Failed parse during installPackageLI", e)); 1265 } finally { 1266 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 1267 } 1268 1269 // Block the install of apps using a lower target SDK version than required. 1270 // This helps improve security and privacy as malware can target older SDK versions 1271 // to avoid enforcement of new API behavior. 1272 boolean bypassLowTargetSdkBlock = 1273 ((installFlags & PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK) != 0); 1274 1275 // Skip enforcement when the testOnly flag is set 1276 if (!bypassLowTargetSdkBlock && parsedPackage.isTestOnly()) { 1277 bypassLowTargetSdkBlock = true; 1278 } 1279 1280 // Enforce the low target sdk install block except when 1281 // the --bypass-low-target-sdk-block is set for the install 1282 if (!bypassLowTargetSdkBlock 1283 && parsedPackage.getTargetSdkVersion() < MIN_INSTALLABLE_TARGET_SDK) { 1284 Slog.w(TAG, "App " + parsedPackage.getPackageName() 1285 + " targets deprecated sdk version"); 1286 throw new PrepareFailure(INSTALL_FAILED_DEPRECATED_SDK_VERSION, 1287 "App package must target at least SDK version " 1288 + MIN_INSTALLABLE_TARGET_SDK + ", but found " 1289 + parsedPackage.getTargetSdkVersion()); 1290 } 1291 1292 // Instant apps have several additional install-time checks. 1293 if (instantApp) { 1294 if (parsedPackage.getTargetSdkVersion() < Build.VERSION_CODES.O) { 1295 Slog.w(TAG, "Instant app package " + parsedPackage.getPackageName() 1296 + " does not target at least O"); 1297 throw new PrepareFailure(INSTALL_FAILED_SESSION_INVALID, 1298 "Instant app package must target at least O"); 1299 } 1300 if (parsedPackage.getSharedUserId() != null) { 1301 Slog.w(TAG, "Instant app package " + parsedPackage.getPackageName() 1302 + " may not declare sharedUserId."); 1303 throw new PrepareFailure(INSTALL_FAILED_SESSION_INVALID, 1304 "Instant app package may not declare a sharedUserId"); 1305 } 1306 } 1307 1308 if (parsedPackage.isStaticSharedLibrary()) { 1309 // Static shared libraries have synthetic package names 1310 PackageManagerService.renameStaticSharedLibraryPackage(parsedPackage); 1311 1312 // No static shared libs on external storage 1313 if (onExternal) { 1314 Slog.i(TAG, "Static shared libs can only be installed on internal storage."); 1315 throw new PrepareFailure(INSTALL_FAILED_INVALID_INSTALL_LOCATION, 1316 "Static shared libs can only be installed on internal storage."); 1317 } 1318 } 1319 1320 String pkgName = parsedPackage.getPackageName(); 1321 request.setName(pkgName); 1322 if (parsedPackage.isTestOnly()) { 1323 if ((installFlags & PackageManager.INSTALL_ALLOW_TEST) == 0) { 1324 throw new PrepareFailure(INSTALL_FAILED_TEST_ONLY, 1325 "Failed to install test-only apk. Did you forget to add -t?"); 1326 } 1327 } 1328 1329 // either use what we've been given or parse directly from the APK 1330 if (request.getSigningDetails() != SigningDetails.UNKNOWN) { 1331 parsedPackage.setSigningDetails(request.getSigningDetails()); 1332 } else { 1333 final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing(); 1334 final ParseResult<SigningDetails> result = ParsingPackageUtils.getSigningDetails( 1335 input, parsedPackage, false /*skipVerify*/); 1336 if (result.isError()) { 1337 throw new PrepareFailure("Failed collect during installPackageLI", 1338 result.getException()); 1339 } 1340 parsedPackage.setSigningDetails(result.getResult()); 1341 } 1342 1343 if (instantApp && parsedPackage.getSigningDetails().getSignatureSchemeVersion() 1344 < SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2) { 1345 Slog.w(TAG, "Instant app package " + parsedPackage.getPackageName() 1346 + " is not signed with at least APK Signature Scheme v2"); 1347 throw new PrepareFailure(INSTALL_FAILED_SESSION_INVALID, 1348 "Instant app package must be signed with APK Signature Scheme v2 or greater"); 1349 } 1350 1351 boolean systemApp = false; 1352 boolean replace = false; 1353 synchronized (mPm.mLock) { 1354 final PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName); 1355 // Check if installing already existing package 1356 if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { 1357 String oldName = mPm.mSettings.getRenamedPackageLPr(pkgName); 1358 if (parsedPackage.getOriginalPackages().contains(oldName) 1359 && mPm.mPackages.containsKey(oldName)) { 1360 // This package is derived from an original package, 1361 // and this device has been updating from that original 1362 // name. We must continue using the original name, so 1363 // rename the new package here. 1364 parsedPackage.setPackageName(oldName); 1365 pkgName = parsedPackage.getPackageName(); 1366 replace = true; 1367 if (DEBUG_INSTALL) { 1368 Slog.d(TAG, "Replacing existing renamed package: oldName=" 1369 + oldName + " pkgName=" + pkgName); 1370 } 1371 } else if (ps != null) { 1372 // This package, under its official name, already exists 1373 // on the device; we should replace it. 1374 replace = true; 1375 if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing package: " + pkgName); 1376 } 1377 if (replace) { 1378 // Prevent apps opting out from runtime permissions 1379 final int oldTargetSdk = ps.getTargetSdkVersion(); 1380 final int newTargetSdk = parsedPackage.getTargetSdkVersion(); 1381 if (oldTargetSdk > Build.VERSION_CODES.LOLLIPOP_MR1 1382 && newTargetSdk <= Build.VERSION_CODES.LOLLIPOP_MR1) { 1383 throw new PrepareFailure( 1384 PackageManager.INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE, 1385 "Package " + parsedPackage.getPackageName() 1386 + " new target SDK " + newTargetSdk 1387 + " doesn't support runtime permissions but the old" 1388 + " target SDK " + oldTargetSdk + " does."); 1389 } 1390 // Prevent persistent apps from being updated 1391 if (ps.isPersistent() 1392 && ((installFlags & PackageManager.INSTALL_STAGED) == 0)) { 1393 throw new PrepareFailure(PackageManager.INSTALL_FAILED_INVALID_APK, 1394 "Package " + pkgName + " is a persistent app. " 1395 + "Persistent apps are not updateable."); 1396 } 1397 } 1398 } 1399 1400 PackageSetting signatureCheckPs = ps; 1401 1402 // SDK libs can have other major versions with different package names. 1403 if (signatureCheckPs == null && parsedPackage.isSdkLibrary()) { 1404 WatchedLongSparseArray<SharedLibraryInfo> libraryInfos = 1405 mSharedLibraries.getSharedLibraryInfos( 1406 parsedPackage.getSdkLibraryName()); 1407 if (libraryInfos != null && libraryInfos.size() > 0) { 1408 // Any existing version would do. 1409 SharedLibraryInfo libraryInfo = libraryInfos.valueAt(0); 1410 signatureCheckPs = mPm.mSettings.getPackageLPr(libraryInfo.getPackageName()); 1411 } 1412 } 1413 1414 // Static shared libs have same package with different versions where 1415 // we internally use a synthetic package name to allow multiple versions 1416 // of the same package, therefore we need to compare signatures against 1417 // the package setting for the latest library version. 1418 if (parsedPackage.isStaticSharedLibrary()) { 1419 SharedLibraryInfo libraryInfo = 1420 mSharedLibraries.getLatestStaticSharedLibraVersion(parsedPackage); 1421 if (libraryInfo != null) { 1422 signatureCheckPs = mPm.mSettings.getPackageLPr(libraryInfo.getPackageName()); 1423 } 1424 } 1425 1426 if (signatureCheckPs != null) { 1427 if (DEBUG_INSTALL) { 1428 Slog.d(TAG, 1429 "Existing package for signature checking: " + signatureCheckPs); 1430 } 1431 1432 // Quick validity check that we're signed correctly if updating; 1433 // we'll check this again later when scanning, but we want to 1434 // bail early here before tripping over redefined permissions. 1435 final KeySetManagerService ksms = mPm.mSettings.getKeySetManagerService(); 1436 final SharedUserSetting signatureCheckSus = mPm.mSettings.getSharedUserSettingLPr( 1437 signatureCheckPs); 1438 if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, signatureCheckSus, 1439 scanFlags)) { 1440 if (!ksms.checkUpgradeKeySetLocked(signatureCheckPs, parsedPackage)) { 1441 throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package " 1442 + parsedPackage.getPackageName() + " upgrade keys do not match the " 1443 + "previously installed version"); 1444 } 1445 } else { 1446 try { 1447 final boolean compareCompat = 1448 ReconcilePackageUtils.isCompatSignatureUpdateNeeded( 1449 mPm.getSettingsVersionForPackage(parsedPackage)); 1450 final boolean compareRecover = 1451 ReconcilePackageUtils.isRecoverSignatureUpdateNeeded( 1452 mPm.getSettingsVersionForPackage(parsedPackage)); 1453 // We don't care about disabledPkgSetting on install for now. 1454 final boolean compatMatch = 1455 PackageManagerServiceUtils.verifySignatures(signatureCheckPs, 1456 signatureCheckSus, null, 1457 parsedPackage.getSigningDetails(), compareCompat, compareRecover, 1458 isRollback); 1459 // The new KeySets will be re-added later in the scanning process. 1460 if (compatMatch) { 1461 synchronized (mPm.mLock) { 1462 ksms.removeAppKeySetDataLPw(parsedPackage.getPackageName()); 1463 } 1464 } 1465 } catch (PackageManagerException e) { 1466 throw new PrepareFailure(e.error, e.getMessage()); 1467 } 1468 } 1469 } 1470 1471 if (ps != null) { 1472 if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps); 1473 1474 systemApp = ps.isSystem(); 1475 request.setOriginUsers(ps.queryUsersInstalledOrHasData( 1476 allUsers)); 1477 } 1478 1479 final int numGroups = ArrayUtils.size(parsedPackage.getPermissionGroups()); 1480 for (int groupNum = 0; groupNum < numGroups; groupNum++) { 1481 final ParsedPermissionGroup group = 1482 parsedPackage.getPermissionGroups().get(groupNum); 1483 final PermissionGroupInfo sourceGroup = mPm.getPermissionGroupInfo(group.getName(), 1484 0); 1485 1486 if (sourceGroup != null && cannotInstallWithBadPermissionGroups(parsedPackage)) { 1487 final String sourcePackageName = sourceGroup.packageName; 1488 1489 if ((replace || !parsedPackage.getPackageName().equals(sourcePackageName)) 1490 && !doesSignatureMatchForPermissions(sourcePackageName, parsedPackage, 1491 scanFlags)) { 1492 EventLog.writeEvent(0x534e4554, "146211400", -1, 1493 parsedPackage.getPackageName()); 1494 1495 throw new PrepareFailure(INSTALL_FAILED_DUPLICATE_PERMISSION_GROUP, 1496 "Package " 1497 + parsedPackage.getPackageName() 1498 + " attempting to redeclare permission group " 1499 + group.getName() + " already owned by " 1500 + sourcePackageName); 1501 } 1502 } 1503 } 1504 1505 // TODO: Move logic for checking permission compatibility into PermissionManagerService 1506 final int n = ArrayUtils.size(parsedPackage.getPermissions()); 1507 for (int i = n - 1; i >= 0; i--) { 1508 final ParsedPermission perm = parsedPackage.getPermissions().get(i); 1509 final Permission bp = mPm.mPermissionManager.getPermissionTEMP(perm.getName()); 1510 1511 // Don't allow anyone but the system to define ephemeral permissions. 1512 if ((perm.getProtectionLevel() & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0 1513 && !systemApp) { 1514 Slog.w(TAG, "Non-System package " + parsedPackage.getPackageName() 1515 + " attempting to delcare ephemeral permission " 1516 + perm.getName() + "; Removing ephemeral."); 1517 ComponentMutateUtils.setProtectionLevel(perm, 1518 perm.getProtectionLevel() & ~PermissionInfo.PROTECTION_FLAG_INSTANT); 1519 } 1520 1521 // Check whether the newly-scanned package wants to define an already-defined perm 1522 if (bp != null) { 1523 final String sourcePackageName = bp.getPackageName(); 1524 1525 if (!doesSignatureMatchForPermissions(sourcePackageName, parsedPackage, 1526 scanFlags)) { 1527 // If the owning package is the system itself, we log but allow 1528 // install to proceed; we fail the install on all other permission 1529 // redefinitions. 1530 if (!sourcePackageName.equals("android")) { 1531 throw new PrepareFailure(INSTALL_FAILED_DUPLICATE_PERMISSION, 1532 "Package " 1533 + parsedPackage.getPackageName() 1534 + " attempting to redeclare permission " 1535 + perm.getName() + " already owned by " 1536 + sourcePackageName) 1537 .conflictsWithExistingPermission(perm.getName(), 1538 sourcePackageName); 1539 } else { 1540 Slog.w(TAG, "Package " + parsedPackage.getPackageName() 1541 + " attempting to redeclare system permission " 1542 + perm.getName() + "; ignoring new declaration"); 1543 parsedPackage.removePermission(i); 1544 } 1545 } else if (!PLATFORM_PACKAGE_NAME.equals(parsedPackage.getPackageName())) { 1546 // Prevent apps to change protection level to dangerous from any other 1547 // type as this would allow a privilege escalation where an app adds a 1548 // normal/signature permission in other app's group and later redefines 1549 // it as dangerous leading to the group auto-grant. 1550 if ((perm.getProtectionLevel() & PermissionInfo.PROTECTION_MASK_BASE) 1551 == PermissionInfo.PROTECTION_DANGEROUS) { 1552 if (!bp.isRuntime()) { 1553 Slog.w(TAG, "Package " + parsedPackage.getPackageName() 1554 + " trying to change a non-runtime permission " 1555 + perm.getName() 1556 + " to runtime; keeping old protection level"); 1557 ComponentMutateUtils.setProtectionLevel(perm, 1558 bp.getProtectionLevel()); 1559 } 1560 } 1561 } 1562 } 1563 1564 if (perm.getGroup() != null 1565 && cannotInstallWithBadPermissionGroups(parsedPackage)) { 1566 boolean isPermGroupDefinedByPackage = false; 1567 for (int groupNum = 0; groupNum < numGroups; groupNum++) { 1568 if (parsedPackage.getPermissionGroups().get(groupNum).getName() 1569 .equals(perm.getGroup())) { 1570 isPermGroupDefinedByPackage = true; 1571 break; 1572 } 1573 } 1574 1575 if (!isPermGroupDefinedByPackage) { 1576 final PermissionGroupInfo sourceGroup = 1577 mPm.getPermissionGroupInfo(perm.getGroup(), 0); 1578 1579 if (sourceGroup == null) { 1580 EventLog.writeEvent(0x534e4554, "146211400", -1, 1581 parsedPackage.getPackageName()); 1582 1583 throw new PrepareFailure(INSTALL_FAILED_BAD_PERMISSION_GROUP, 1584 "Package " 1585 + parsedPackage.getPackageName() 1586 + " attempting to declare permission " 1587 + perm.getName() + " in non-existing group " 1588 + perm.getGroup()); 1589 } else { 1590 String groupSourcePackageName = sourceGroup.packageName; 1591 1592 if (!PLATFORM_PACKAGE_NAME.equals(groupSourcePackageName) 1593 && !doesSignatureMatchForPermissions(groupSourcePackageName, 1594 parsedPackage, scanFlags)) { 1595 EventLog.writeEvent(0x534e4554, "146211400", -1, 1596 parsedPackage.getPackageName()); 1597 1598 throw new PrepareFailure(INSTALL_FAILED_BAD_PERMISSION_GROUP, 1599 "Package " 1600 + parsedPackage.getPackageName() 1601 + " attempting to declare permission " 1602 + perm.getName() + " in group " 1603 + perm.getGroup() + " owned by package " 1604 + groupSourcePackageName 1605 + " with incompatible certificate"); 1606 } 1607 } 1608 } 1609 } 1610 } 1611 } 1612 1613 if (systemApp) { 1614 if (onExternal) { 1615 // Abort update; system app can't be replaced with app on sdcard 1616 throw new PrepareFailure(INSTALL_FAILED_INVALID_INSTALL_LOCATION, 1617 "Cannot install updates to system apps on sdcard"); 1618 } else if (instantApp) { 1619 // Abort update; system app can't be replaced with an instant app 1620 throw new PrepareFailure(INSTALL_FAILED_SESSION_INVALID, 1621 "Cannot update a system app with an instant app"); 1622 } 1623 } 1624 1625 if (request.isInstallMove()) { 1626 // We did an in-place move, so dex is ready to roll 1627 scanFlags |= SCAN_NO_DEX; 1628 scanFlags |= SCAN_MOVE; 1629 1630 synchronized (mPm.mLock) { 1631 final PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName); 1632 if (ps == null) { 1633 request.setError(PackageManagerException.ofInternalError( 1634 "Missing settings for moved package " + pkgName, 1635 PackageManagerException.INTERNAL_ERROR_MISSING_SETTING_FOR_MOVE)); 1636 } 1637 1638 // We moved the entire application as-is, so bring over the 1639 // previously derived ABI information. 1640 parsedPackage.setPrimaryCpuAbi(ps.getPrimaryCpuAbiLegacy()) 1641 .setSecondaryCpuAbi(ps.getSecondaryCpuAbiLegacy()); 1642 } 1643 1644 } else { 1645 // Enable SCAN_NO_DEX flag to skip dexopt at a later stage 1646 scanFlags |= SCAN_NO_DEX; 1647 // The native libs of Apex is located in apex_payload.img, don't need to parse it from 1648 // the original apex file 1649 if (!isApex) { 1650 try { 1651 PackageSetting pkgSetting; 1652 synchronized (mPm.mLock) { 1653 pkgSetting = mPm.mSettings.getPackageLPr(pkgName); 1654 } 1655 boolean isUpdatedSystemAppFromExistingSetting = pkgSetting != null 1656 && pkgSetting.isUpdatedSystemApp(); 1657 final String abiOverride = deriveAbiOverride(request.getAbiOverride()); 1658 1659 // TODO: Are these system flags actually set properly at this stage? 1660 boolean isUpdatedSystemAppInferred = 1661 pkgSetting != null && pkgSetting.isSystem(); 1662 // derivePackageAbi works OK for archived packages despite logging some errors. 1663 final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths> 1664 derivedAbi = mPackageAbiHelper.derivePackageAbi(parsedPackage, 1665 systemApp, (isUpdatedSystemAppFromExistingSetting 1666 || isUpdatedSystemAppInferred), abiOverride, 1667 ScanPackageUtils.getAppLib32InstallDir()); 1668 derivedAbi.first.applyTo(parsedPackage); 1669 derivedAbi.second.applyTo(parsedPackage); 1670 } catch (PackageManagerException pme) { 1671 Slog.e(TAG, "Error deriving application ABI", pme); 1672 throw PrepareFailure.ofInternalError( 1673 "Error deriving application ABI: " + pme.getMessage(), 1674 PackageManagerException.INTERNAL_ERROR_DERIVING_ABI); 1675 } 1676 } 1677 } 1678 1679 if (!isApex) { 1680 doRenameLI(request, parsedPackage); 1681 1682 try { 1683 setUpFsVerity(parsedPackage); 1684 } catch (Installer.InstallerException | IOException | DigestException 1685 | NoSuchAlgorithmException e) { 1686 throw PrepareFailure.ofInternalError( 1687 "Failed to set up verity: " + e, 1688 PackageManagerException.INTERNAL_ERROR_VERITY_SETUP); 1689 } 1690 } else { 1691 // Use the path returned by apexd 1692 parsedPackage.setPath(request.getApexInfo().modulePath); 1693 parsedPackage.setBaseApkPath(request.getApexInfo().modulePath); 1694 } 1695 1696 PackageFreezer freezer = null; 1697 if (!Flags.improveInstallFreeze()) { 1698 freezer = freezePackageForInstall(pkgName, UserHandle.USER_ALL, installFlags, 1699 "installPackageLI", ApplicationExitInfo.REASON_PACKAGE_UPDATED, request); 1700 } 1701 1702 1703 boolean shouldCloseFreezerBeforeReturn = true; 1704 try { 1705 final PackageSetting oldPackageState; 1706 final AndroidPackage oldPackage; 1707 String renamedPackage; 1708 boolean sysPkg = false; 1709 int targetScanFlags = scanFlags; 1710 int targetParseFlags = parseFlags; 1711 final PackageSetting ps; 1712 final PackageSetting disabledPs; 1713 final SharedUserSetting sharedUserSetting; 1714 if (replace) { 1715 final String pkgName11 = parsedPackage.getPackageName(); 1716 synchronized (mPm.mLock) { 1717 oldPackageState = mPm.mSettings.getPackageLPr(pkgName11); 1718 } 1719 oldPackage = oldPackageState.getAndroidPackage(); 1720 if (parsedPackage.isStaticSharedLibrary()) { 1721 // Static libs have a synthetic package name containing the version 1722 // and cannot be updated as an update would get a new package name, 1723 // unless this is installed from adb which is useful for development. 1724 if (oldPackage != null 1725 && (installFlags & PackageManager.INSTALL_FROM_ADB) == 0) { 1726 throw new PrepareFailure(INSTALL_FAILED_DUPLICATE_PACKAGE, 1727 "Packages declaring " 1728 + "static-shared libs cannot be updated"); 1729 } 1730 } 1731 1732 final boolean isInstantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0; 1733 1734 final int[] installedUsers; 1735 final int[] uninstalledUsers; 1736 1737 synchronized (mPm.mLock) { 1738 if (DEBUG_INSTALL) { 1739 Slog.d(TAG, 1740 "replacePackageLI: new=" + parsedPackage 1741 + ", old=" + oldPackageState.getName()); 1742 } 1743 1744 ps = mPm.mSettings.getPackageLPr(pkgName11); 1745 disabledPs = mPm.mSettings.getDisabledSystemPkgLPr(ps); 1746 sharedUserSetting = mPm.mSettings.getSharedUserSettingLPr(ps); 1747 1748 // verify signatures are valid 1749 final KeySetManagerService ksms = mPm.mSettings.getKeySetManagerService(); 1750 if (ksms.shouldCheckUpgradeKeySetLocked(ps, sharedUserSetting, scanFlags)) { 1751 if (!ksms.checkUpgradeKeySetLocked(ps, parsedPackage)) { 1752 throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, 1753 "New package not signed by keys specified by upgrade-keysets: " 1754 + pkgName11); 1755 } 1756 } else { 1757 SigningDetails parsedPkgSigningDetails = parsedPackage.getSigningDetails(); 1758 SigningDetails oldPkgSigningDetails = oldPackageState.getSigningDetails(); 1759 // default to original signature matching 1760 if (!parsedPkgSigningDetails.checkCapability(oldPkgSigningDetails, 1761 SigningDetails.CertCapabilities.INSTALLED_DATA) 1762 && !oldPkgSigningDetails.checkCapability(parsedPkgSigningDetails, 1763 SigningDetails.CertCapabilities.ROLLBACK)) { 1764 // Allow the update to proceed if this is a rollback and the parsed 1765 // package's current signing key is the current signer or in the lineage 1766 // of the old package; this allows a rollback to a previously installed 1767 // version after an app's signing key has been rotated without requiring 1768 // the rollback capability on the previous signing key. 1769 if (!isRollback || !oldPkgSigningDetails.hasAncestorOrSelf( 1770 parsedPkgSigningDetails)) { 1771 throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, 1772 "New package has a different signature: " + pkgName11); 1773 } 1774 } 1775 } 1776 1777 // don't allow a system upgrade unless the upgrade hash matches 1778 if (oldPackageState.getRestrictUpdateHash() != null 1779 && oldPackageState.isSystem()) { 1780 final byte[] digestBytes; 1781 try { 1782 final MessageDigest digest = MessageDigest.getInstance("SHA-512"); 1783 updateDigest(digest, new File(parsedPackage.getBaseApkPath())); 1784 if (!ArrayUtils.isEmpty(parsedPackage.getSplitCodePaths())) { 1785 for (String path : parsedPackage.getSplitCodePaths()) { 1786 updateDigest(digest, new File(path)); 1787 } 1788 } 1789 digestBytes = digest.digest(); 1790 } catch (NoSuchAlgorithmException | IOException e) { 1791 throw new PrepareFailure(INSTALL_FAILED_INVALID_APK, 1792 "Could not compute hash: " + pkgName11); 1793 } 1794 if (!Arrays.equals(oldPackageState.getRestrictUpdateHash(), digestBytes)) { 1795 throw new PrepareFailure(INSTALL_FAILED_INVALID_APK, 1796 "New package fails restrict-update check: " + pkgName11); 1797 } 1798 // retain upgrade restriction 1799 parsedPackage.setRestrictUpdateHash( 1800 oldPackageState.getRestrictUpdateHash()); 1801 } 1802 1803 if (oldPackage != null) { 1804 // APK should not change its sharedUserId declarations 1805 final var oldSharedUid = oldPackage.getSharedUserId() != null 1806 ? oldPackage.getSharedUserId() : "<nothing>"; 1807 final var newSharedUid = parsedPackage.getSharedUserId() != null 1808 ? parsedPackage.getSharedUserId() : "<nothing>"; 1809 if (!oldSharedUid.equals(newSharedUid)) { 1810 throw new PrepareFailure(INSTALL_FAILED_UID_CHANGED, 1811 "Package " + parsedPackage.getPackageName() 1812 + " shared user changed from " 1813 + oldSharedUid + " to " + newSharedUid); 1814 } 1815 1816 // APK should not re-join shared UID 1817 if (oldPackage.isLeavingSharedUser() 1818 && !parsedPackage.isLeavingSharedUser()) { 1819 throw new PrepareFailure(INSTALL_FAILED_UID_CHANGED, 1820 "Package " + parsedPackage.getPackageName() 1821 + " attempting to rejoin " + newSharedUid); 1822 } 1823 } 1824 1825 // In case of rollback, remember per-user/profile install state 1826 installedUsers = ps.queryInstalledUsers(allUsers, true); 1827 uninstalledUsers = ps.queryInstalledUsers(allUsers, false); 1828 1829 // don't allow an upgrade from full to ephemeral 1830 if (isInstantApp) { 1831 if (request.getUserId() == UserHandle.USER_ALL) { 1832 for (int currentUser : allUsers) { 1833 if (!ps.getInstantApp(currentUser)) { 1834 // can't downgrade from full to instant 1835 Slog.w(TAG, 1836 "Can't replace full app with instant app: " + pkgName11 1837 + " for user: " + currentUser); 1838 throw new PrepareFailure( 1839 PackageManager.INSTALL_FAILED_SESSION_INVALID); 1840 } 1841 } 1842 } else if (!ps.getInstantApp(request.getUserId())) { 1843 // can't downgrade from full to instant 1844 Slog.w(TAG, "Can't replace full app with instant app: " + pkgName11 1845 + " for user: " + request.getUserId()); 1846 throw new PrepareFailure( 1847 PackageManager.INSTALL_FAILED_SESSION_INVALID); 1848 } 1849 } 1850 } 1851 1852 // Update what is removed 1853 PackageRemovedInfo removedInfo = new PackageRemovedInfo(); 1854 removedInfo.mUid = ps.getAppId(); 1855 removedInfo.mRemovedPackage = ps.getPackageName(); 1856 removedInfo.mInstallerPackageName = 1857 ps.getInstallSource().mInstallerPackageName; 1858 removedInfo.mIsStaticSharedLib = 1859 parsedPackage.getStaticSharedLibraryName() != null; 1860 removedInfo.mIsUpdate = true; 1861 removedInfo.mOrigUsers = installedUsers; 1862 removedInfo.mInstallReasons = new SparseIntArray(installedUsers.length); 1863 for (int i = 0; i < installedUsers.length; i++) { 1864 final int userId = installedUsers[i]; 1865 removedInfo.mInstallReasons.put(userId, 1866 ps.getInstallReason(userId)); 1867 } 1868 removedInfo.mUninstallReasons = new SparseIntArray(uninstalledUsers.length); 1869 for (int i = 0; i < uninstalledUsers.length; i++) { 1870 final int userId = uninstalledUsers[i]; 1871 removedInfo.mUninstallReasons.put(userId, 1872 ps.getUninstallReason(userId)); 1873 } 1874 removedInfo.mIsExternal = oldPackageState.isExternalStorage(); 1875 removedInfo.mRemovedPackageVersionCode = oldPackageState.getVersionCode(); 1876 request.setRemovedInfo(removedInfo); 1877 1878 sysPkg = oldPackageState.isSystem(); 1879 if (sysPkg) { 1880 // Set the system/privileged/oem/vendor/product flags as needed 1881 final boolean privileged = oldPackageState.isPrivileged(); 1882 final boolean oem = oldPackageState.isOem(); 1883 final boolean vendor = oldPackageState.isVendor(); 1884 final boolean product = oldPackageState.isProduct(); 1885 final boolean odm = oldPackageState.isOdm(); 1886 final boolean systemExt = oldPackageState.isSystemExt(); 1887 final @ParsingPackageUtils.ParseFlags int systemParseFlags = parseFlags; 1888 final @PackageManagerService.ScanFlags int systemScanFlags = scanFlags 1889 | SCAN_AS_SYSTEM 1890 | (privileged ? SCAN_AS_PRIVILEGED : 0) 1891 | (oem ? SCAN_AS_OEM : 0) 1892 | (vendor ? SCAN_AS_VENDOR : 0) 1893 | (product ? SCAN_AS_PRODUCT : 0) 1894 | (odm ? SCAN_AS_ODM : 0) 1895 | (systemExt ? SCAN_AS_SYSTEM_EXT : 0); 1896 1897 if (DEBUG_INSTALL) { 1898 Slog.d(TAG, "replaceSystemPackageLI: new=" + parsedPackage 1899 + ", old=" + oldPackageState.getName()); 1900 } 1901 request.setReturnCode(PackageManager.INSTALL_SUCCEEDED); 1902 request.setApexModuleName(oldPackageState.getApexModuleName()); 1903 targetParseFlags = systemParseFlags; 1904 targetScanFlags = systemScanFlags; 1905 } else { // non system replace 1906 if (DEBUG_INSTALL) { 1907 Slog.d(TAG, 1908 "replaceNonSystemPackageLI: new=" + parsedPackage + ", old=" 1909 + oldPackageState.getName()); 1910 } 1911 } 1912 } else { // new package install 1913 ps = null; 1914 disabledPs = null; 1915 oldPackageState = null; 1916 // Remember this for later, in case we need to rollback this install 1917 String pkgName1 = parsedPackage.getPackageName(); 1918 1919 if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + parsedPackage); 1920 1921 // TODO(b/194319951): MOVE TO RECONCILE 1922 synchronized (mPm.mLock) { 1923 renamedPackage = mPm.mSettings.getRenamedPackageLPr(pkgName1); 1924 if (renamedPackage != null) { 1925 // A package with the same name is already installed, though 1926 // it has been renamed to an older name. The package we 1927 // are trying to install should be installed as an update to 1928 // the existing one, but that has not been requested, so bail. 1929 throw new PrepareFailure(INSTALL_FAILED_ALREADY_EXISTS, 1930 "Attempt to re-install " + pkgName1 1931 + " without first uninstalling package running as " 1932 + renamedPackage); 1933 } 1934 if (mPm.mPackages.containsKey(pkgName1)) { 1935 // Don't allow installation over an existing package with the same name. 1936 throw new PrepareFailure(INSTALL_FAILED_ALREADY_EXISTS, 1937 "Attempt to re-install " + pkgName1 1938 + " without first uninstalling."); 1939 } 1940 } 1941 } 1942 // we're passing the freezer back to be closed in a later phase of install 1943 shouldCloseFreezerBeforeReturn = false; 1944 1945 request.setPrepareResult(replace, targetScanFlags, targetParseFlags, 1946 oldPackageState, parsedPackage, archivedPackage, 1947 replace /* clearCodeCache */, sysPkg, ps, disabledPs); 1948 } finally { 1949 if (freezer != null) { 1950 request.setFreezer(freezer); 1951 if (shouldCloseFreezerBeforeReturn) { 1952 freezer.close(); 1953 } 1954 } 1955 } 1956 } 1957 1958 /** 1959 * Rename package into final resting place. All paths on the given 1960 * scanned package should be updated to reflect the rename. 1961 */ 1962 @GuardedBy("mPm.mInstallLock") doRenameLI(InstallRequest request, ParsedPackage parsedPackage)1963 private void doRenameLI(InstallRequest request, 1964 ParsedPackage parsedPackage) throws PrepareFailure { 1965 final int status = request.getReturnCode(); 1966 final String statusMsg = request.getReturnMsg(); 1967 if (request.isInstallMove()) { 1968 if (status != PackageManager.INSTALL_SUCCEEDED) { 1969 mRemovePackageHelper.cleanUpForMoveInstall(request.getMoveToUuid(), 1970 request.getMovePackageName(), request.getMoveFromCodePath()); 1971 throw new PrepareFailure(status, statusMsg); 1972 } 1973 return; 1974 } 1975 // For file installations 1976 if (status != PackageManager.INSTALL_SUCCEEDED) { 1977 mRemovePackageHelper.removeCodePath(request.getCodeFile()); 1978 throw new PrepareFailure(status, statusMsg); 1979 } 1980 1981 final File targetDir = resolveTargetDir(request.getInstallFlags(), request.getCodeFile()); 1982 final File beforeCodeFile = request.getCodeFile(); 1983 final File afterCodeFile = PackageManagerServiceUtils.getNextCodePath(targetDir, 1984 parsedPackage.getPackageName()); 1985 1986 if (DEBUG_INSTALL) Slog.d(TAG, "Renaming " + beforeCodeFile + " to " + afterCodeFile); 1987 final boolean onIncremental = mPm.mIncrementalManager != null 1988 && isIncrementalPath(beforeCodeFile.getAbsolutePath()); 1989 try { 1990 makeDirRecursive(afterCodeFile.getParentFile(), 0771); 1991 if (onIncremental) { 1992 // Just link files here. The stage dir will be removed when the installation 1993 // session is completed. 1994 mPm.mIncrementalManager.linkCodePath(beforeCodeFile, afterCodeFile); 1995 } else { 1996 Os.rename(beforeCodeFile.getAbsolutePath(), afterCodeFile.getAbsolutePath()); 1997 } 1998 } catch (IOException | ErrnoException e) { 1999 Slog.w(TAG, "Failed to rename", e); 2000 throw new PrepareFailure(PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE, 2001 "Failed to rename"); 2002 } 2003 2004 if (!onIncremental && !SELinux.restoreconRecursive(afterCodeFile)) { 2005 Slog.w(TAG, "Failed to restorecon"); 2006 throw new PrepareFailure(PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE, 2007 "Failed to restorecon"); 2008 } 2009 2010 // Reflect the rename internally 2011 request.setCodeFile(afterCodeFile); 2012 2013 // Reflect the rename in scanned details 2014 try { 2015 parsedPackage.setPath(afterCodeFile.getCanonicalPath()); 2016 } catch (IOException e) { 2017 Slog.e(TAG, "Failed to get path: " + afterCodeFile, e); 2018 throw new PrepareFailure(PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE, 2019 "Failed to get path: " + afterCodeFile); 2020 } 2021 parsedPackage.setBaseApkPath(FileUtils.rewriteAfterRename(beforeCodeFile, 2022 afterCodeFile, parsedPackage.getBaseApkPath())); 2023 parsedPackage.setSplitCodePaths(FileUtils.rewriteAfterRename(beforeCodeFile, 2024 afterCodeFile, parsedPackage.getSplitCodePaths())); 2025 } 2026 2027 // TODO(b/168126411): Once staged install flow starts using the same folder as non-staged 2028 // flow, we won't need this method anymore. resolveTargetDir(int installFlags, File codeFile)2029 private File resolveTargetDir(int installFlags, File codeFile) { 2030 boolean isStagedInstall = (installFlags & INSTALL_STAGED) != 0; 2031 if (isStagedInstall) { 2032 return Environment.getDataAppDirectory(null); 2033 } else { 2034 return codeFile.getParentFile(); 2035 } 2036 } 2037 2038 /* 2039 * Cannot properly check CANNOT_INSTALL_WITH_BAD_PERMISSION_GROUPS using CompatChanges 2040 * as this only works for packages that are installed 2041 * 2042 * TODO: Move logic for permission group compatibility into PermissionManagerService 2043 */ 2044 @SuppressWarnings("AndroidFrameworkCompatChange") cannotInstallWithBadPermissionGroups(ParsedPackage parsedPackage)2045 private static boolean cannotInstallWithBadPermissionGroups(ParsedPackage parsedPackage) { 2046 return parsedPackage.getTargetSdkVersion() >= Build.VERSION_CODES.S; 2047 } 2048 doesSignatureMatchForPermissions(@onNull String sourcePackageName, @NonNull ParsedPackage parsedPackage, int scanFlags)2049 private boolean doesSignatureMatchForPermissions(@NonNull String sourcePackageName, 2050 @NonNull ParsedPackage parsedPackage, int scanFlags) { 2051 // If the defining package is signed with our cert, it's okay. This 2052 // also includes the "updating the same package" case, of course. 2053 // "updating same package" could also involve key-rotation. 2054 2055 final PackageSetting sourcePackageSetting; 2056 final KeySetManagerService ksms; 2057 final SharedUserSetting sharedUserSetting; 2058 synchronized (mPm.mLock) { 2059 sourcePackageSetting = mPm.mSettings.getPackageLPr(sourcePackageName); 2060 ksms = mPm.mSettings.getKeySetManagerService(); 2061 sharedUserSetting = mPm.mSettings.getSharedUserSettingLPr(sourcePackageSetting); 2062 } 2063 2064 final SigningDetails sourceSigningDetails = (sourcePackageSetting == null 2065 ? SigningDetails.UNKNOWN : sourcePackageSetting.getSigningDetails()); 2066 if (sourcePackageName.equals(parsedPackage.getPackageName()) 2067 && (ksms.shouldCheckUpgradeKeySetLocked( 2068 sourcePackageSetting, sharedUserSetting, scanFlags))) { 2069 return ksms.checkUpgradeKeySetLocked(sourcePackageSetting, parsedPackage); 2070 } else { 2071 2072 // in the event of signing certificate rotation, we need to see if the 2073 // package's certificate has rotated from the current one, or if it is an 2074 // older certificate with which the current is ok with sharing permissions 2075 if (sourceSigningDetails.checkCapability( 2076 parsedPackage.getSigningDetails(), 2077 SigningDetails.CertCapabilities.PERMISSION)) { 2078 return true; 2079 } else if (parsedPackage.getSigningDetails().checkCapability( 2080 sourceSigningDetails, 2081 SigningDetails.CertCapabilities.PERMISSION)) { 2082 // the scanned package checks out, has signing certificate rotation 2083 // history, and is newer; bring it over 2084 synchronized (mPm.mLock) { 2085 sourcePackageSetting.setSigningDetails(parsedPackage.getSigningDetails()); 2086 } 2087 return true; 2088 } else { 2089 return false; 2090 } 2091 } 2092 } 2093 2094 /** 2095 * Set up fs-verity for the given package. For older devices that do not support fs-verity, 2096 * this is a no-op. 2097 */ setUpFsVerity(AndroidPackage pkg)2098 private void setUpFsVerity(AndroidPackage pkg) throws Installer.InstallerException, 2099 PrepareFailure, IOException, DigestException, NoSuchAlgorithmException { 2100 if (!PackageManagerServiceUtils.isApkVerityEnabled()) { 2101 return; 2102 } 2103 2104 if (isIncrementalPath(pkg.getPath()) && IncrementalManager.getVersion() 2105 < IncrementalManager.MIN_VERSION_TO_SUPPORT_FSVERITY) { 2106 return; 2107 } 2108 2109 // Collect files we care for fs-verity setup. 2110 ArrayMap<String, String> fsverityCandidates = new ArrayMap<>(); 2111 fsverityCandidates.put(pkg.getBaseApkPath(), 2112 VerityUtils.getFsveritySignatureFilePath(pkg.getBaseApkPath())); 2113 2114 final String dmPath = DexMetadataHelper.buildDexMetadataPathForApk( 2115 pkg.getBaseApkPath()); 2116 if (new File(dmPath).exists()) { 2117 fsverityCandidates.put(dmPath, VerityUtils.getFsveritySignatureFilePath(dmPath)); 2118 } 2119 2120 for (String path : pkg.getSplitCodePaths()) { 2121 fsverityCandidates.put(path, VerityUtils.getFsveritySignatureFilePath(path)); 2122 2123 final String splitDmPath = DexMetadataHelper.buildDexMetadataPathForApk(path); 2124 if (new File(splitDmPath).exists()) { 2125 fsverityCandidates.put(splitDmPath, 2126 VerityUtils.getFsveritySignatureFilePath(splitDmPath)); 2127 } 2128 } 2129 2130 var fis = FileIntegrityService.getService(); 2131 for (Map.Entry<String, String> entry : fsverityCandidates.entrySet()) { 2132 try { 2133 final String filePath = entry.getKey(); 2134 if (VerityUtils.hasFsverity(filePath)) { 2135 continue; 2136 } 2137 2138 final String signaturePath = entry.getValue(); 2139 if (new File(signaturePath).exists()) { 2140 // If signature is provided, enable fs-verity first so that the file can be 2141 // measured for signature check below. 2142 VerityUtils.setUpFsverity(filePath); 2143 2144 if (!fis.verifyPkcs7DetachedSignature(signaturePath, filePath)) { 2145 throw new PrepareFailure(PackageManager.INSTALL_FAILED_BAD_SIGNATURE, 2146 "fs-verity signature does not verify against a known key"); 2147 } 2148 } 2149 } catch (IOException e) { 2150 throw new PrepareFailure(PackageManager.INSTALL_FAILED_BAD_SIGNATURE, 2151 "Failed to enable fs-verity: " + e); 2152 } 2153 } 2154 } 2155 freezePackageForInstall(String packageName, int userId, int installFlags, String killReason, int exitInfoReason, InstallRequest request)2156 private PackageFreezer freezePackageForInstall(String packageName, int userId, int installFlags, 2157 String killReason, int exitInfoReason, InstallRequest request) { 2158 if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) { 2159 return new PackageFreezer(mPm, request); 2160 } else { 2161 return mPm.freezePackage(packageName, userId, killReason, exitInfoReason, request); 2162 } 2163 } 2164 updateDigest(MessageDigest digest, File file)2165 private static void updateDigest(MessageDigest digest, File file) throws IOException { 2166 try (DigestInputStream digestStream = 2167 new DigestInputStream(new FileInputStream(file), digest)) { 2168 int length, total = 0; 2169 while ((length = digestStream.read()) != -1) { 2170 total += length; 2171 } // just plow through the file 2172 } 2173 } 2174 2175 @GuardedBy("mPm.mLock") commitPackagesLocked(List<ReconciledPackage> reconciledPackages, @NonNull int[] allUsers)2176 private void commitPackagesLocked(List<ReconciledPackage> reconciledPackages, 2177 @NonNull int[] allUsers) { 2178 // TODO: remove any expected failures from this method; this should only be able to fail due 2179 // to unavoidable errors (I/O, etc.) 2180 for (ReconciledPackage reconciledPkg : reconciledPackages) { 2181 final InstallRequest installRequest = reconciledPkg.mInstallRequest; 2182 final ParsedPackage parsedPackage = installRequest.getParsedPackage(); 2183 final String packageName = parsedPackage.getPackageName(); 2184 2185 installRequest.onCommitStarted(); 2186 if (installRequest.isInstallReplace()) { 2187 AndroidPackage oldPackage = mPm.mPackages.get(packageName); 2188 2189 // Set the update and install times 2190 PackageStateInternal deletedPkgSetting = mPm.snapshotComputer() 2191 .getPackageStateInternal(packageName); 2192 // TODO(b/225756739): For rebootless APEX, consider using lastUpdateMillis provided 2193 // by apexd to be more accurate. 2194 installRequest.setScannedPackageSettingFirstInstallTimeFromReplaced( 2195 deletedPkgSetting, allUsers); 2196 installRequest.setScannedPackageSettingLastUpdateTime( 2197 System.currentTimeMillis()); 2198 2199 installRequest.getRemovedInfo().mBroadcastAllowList = 2200 mPm.mAppsFilter.getVisibilityAllowList(mPm.snapshotComputer(), 2201 installRequest.getScannedPackageSetting(), 2202 allUsers, mPm.mSettings.getPackagesLocked()); 2203 if (installRequest.isInstallSystem()) { 2204 // Remove existing system package 2205 mRemovePackageHelper.removePackage(oldPackage, true); 2206 if (!disableSystemPackageLPw(oldPackage)) { 2207 // We didn't need to disable the .apk as a current system package, 2208 // which means we are replacing another update that is already 2209 // installed. We need to make sure to delete the older one's .apk. 2210 installRequest.getRemovedInfo().mArgs = new CleanUpArgs( 2211 packageName, 2212 oldPackage.getPath(), 2213 getAppDexInstructionSets( 2214 deletedPkgSetting.getPrimaryCpuAbi(), 2215 deletedPkgSetting.getSecondaryCpuAbi())); 2216 } else { 2217 installRequest.getRemovedInfo().mArgs = null; 2218 } 2219 } else { 2220 try { 2221 // Settings will be written during the call to updateSettingsLI(). 2222 mDeletePackageHelper.executeDeletePackage( 2223 reconciledPkg.mDeletePackageAction, packageName, 2224 true, allUsers, false); 2225 } catch (SystemDeleteException e) { 2226 if (mPm.mIsEngBuild) { 2227 throw new RuntimeException("Unexpected failure", e); 2228 // ignore; not possible for non-system app 2229 } 2230 } 2231 2232 if (installRequest.getReturnCode() == PackageManager.INSTALL_SUCCEEDED) { 2233 PackageSetting ps2 = mPm.mSettings.getPackageLPr( 2234 parsedPackage.getPackageName()); 2235 if (ps2 != null) { 2236 installRequest.getRemovedInfo().mRemovedForAllUsers = 2237 mPm.mPackages.get(ps2.getPackageName()) == null; 2238 } 2239 } 2240 } 2241 } 2242 2243 AndroidPackage pkg = commitReconciledScanResultLocked(reconciledPkg, allUsers); 2244 updateSettingsLI(pkg, allUsers, installRequest); 2245 2246 final PackageSetting ps = mPm.mSettings.getPackageLPr(packageName); 2247 if (ps != null) { 2248 installRequest.setNewUsers( 2249 ps.queryInstalledUsers(allUsers, true)); 2250 ps.setUpdateAvailable(false /*updateAvailable*/); 2251 } 2252 if (installRequest.getReturnCode() == PackageManager.INSTALL_SUCCEEDED) { 2253 // If this is an archival installation then we'll initialize the archive status, 2254 // while also marking package as not installed. 2255 // Doing this at the very end of the install as we are using ps.getInstalled 2256 // to figure out which users were changed. 2257 mPm.markPackageAsArchivedIfNeeded(ps, 2258 installRequest.getArchivedPackage(), 2259 installRequest.getResponsibleInstallerTitles(), 2260 installRequest.getNewUsers()); 2261 mPm.updateSequenceNumberLP(ps, installRequest.getNewUsers()); 2262 mPm.updateInstantAppInstallerLocked(packageName); 2263 } 2264 installRequest.onCommitFinished(); 2265 } 2266 ApplicationPackageManager.invalidateGetPackagesForUidCache(); 2267 } 2268 2269 @GuardedBy("mPm.mLock") disableSystemPackageLPw(AndroidPackage oldPkg)2270 private boolean disableSystemPackageLPw(AndroidPackage oldPkg) { 2271 return mPm.mSettings.disableSystemPackageLPw(oldPkg.getPackageName(), true); 2272 } 2273 updateSettingsLI(AndroidPackage newPackage, int[] allUsers, InstallRequest installRequest)2274 private void updateSettingsLI(AndroidPackage newPackage, 2275 int[] allUsers, InstallRequest installRequest) { 2276 updateSettingsInternalLI(newPackage, allUsers, installRequest); 2277 } 2278 updateSettingsInternalLI(AndroidPackage pkg, int[] allUsers, InstallRequest installRequest)2279 private void updateSettingsInternalLI(AndroidPackage pkg, 2280 int[] allUsers, InstallRequest installRequest) { 2281 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettingsInternal"); 2282 2283 final String pkgName = pkg.getPackageName(); 2284 final int[] installedForUsers = installRequest.getOriginUsers(); 2285 final int installReason = installRequest.getInstallReason(); 2286 final String installerPackageName = installRequest.getInstallerPackageName(); 2287 2288 if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.getPath()); 2289 final int userId = installRequest.getUserId(); 2290 if (userId != UserHandle.USER_ALL && userId != UserHandle.USER_CURRENT 2291 && !mPm.mUserManager.exists(userId)) { 2292 installRequest.setError(PackageManagerException.ofInternalError( 2293 "User " + userId + " doesn't exist or has been removed", 2294 PackageManagerException.INTERNAL_ERROR_MISSING_USER)); 2295 return; 2296 } 2297 synchronized (mPm.mLock) { 2298 // For system-bundled packages, we assume that installing an upgraded version 2299 // of the package implies that the user actually wants to run that new code, 2300 // so we enable the package. 2301 final PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName); 2302 if (ps != null) { 2303 if (ps.isSystem()) { 2304 if (DEBUG_INSTALL) { 2305 Slog.d(TAG, "Implicitly enabling system package on upgrade: " + pkgName); 2306 } 2307 // Enable system package for requested users 2308 if (installedForUsers != null 2309 && !installRequest.isApplicationEnabledSettingPersistent()) { 2310 for (int origUserId : installedForUsers) { 2311 if (userId == UserHandle.USER_ALL || userId == origUserId) { 2312 ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, 2313 origUserId, installerPackageName); 2314 } 2315 } 2316 } 2317 // Also convey the prior install/uninstall state 2318 if (allUsers != null && installedForUsers != null) { 2319 for (int currentUserId : allUsers) { 2320 final boolean installed = ArrayUtils.contains( 2321 installedForUsers, currentUserId); 2322 if (DEBUG_INSTALL) { 2323 Slog.d(TAG, " user " + currentUserId + " => " + installed); 2324 } 2325 ps.setInstalled(installed, currentUserId); 2326 } 2327 // these install state changes will be persisted in the 2328 // upcoming call to mSettings.writeLPr(). 2329 } 2330 2331 if (allUsers != null) { 2332 for (int currentUserId : allUsers) { 2333 ps.resetOverrideComponentLabelIcon(currentUserId); 2334 } 2335 } 2336 } 2337 2338 // Retrieve the overlays for shared libraries of the package. 2339 if (!ps.getPkgState().getUsesLibraryInfos().isEmpty()) { 2340 for (SharedLibraryWrapper sharedLib : ps.getPkgState().getUsesLibraryInfos()) { 2341 for (int currentUserId : allUsers) { 2342 if (sharedLib.getType() != SharedLibraryInfo.TYPE_DYNAMIC) { 2343 // TODO(146804378): Support overlaying static shared libraries 2344 continue; 2345 } 2346 final PackageSetting libPs = mPm.mSettings.getPackageLPr( 2347 sharedLib.getPackageName()); 2348 if (libPs == null) { 2349 continue; 2350 } 2351 ps.setOverlayPathsForLibrary(sharedLib.getName(), 2352 libPs.getOverlayPaths(currentUserId), currentUserId); 2353 } 2354 } 2355 } 2356 2357 if (userId != UserHandle.USER_ALL) { 2358 // It's implied that when a user requests installation, they want the app to 2359 // be installed and enabled. The caller, however, can explicitly specify to 2360 // keep the existing enabled state. 2361 ps.setInstalled(true, userId); 2362 if (!installRequest.isApplicationEnabledSettingPersistent()) { 2363 ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userId, 2364 installerPackageName); 2365 } 2366 // Clear any existing archive state. 2367 mPm.mInstallerService.mPackageArchiver.clearArchiveState(ps, userId); 2368 } else if (allUsers != null) { 2369 // The caller explicitly specified INSTALL_ALL_USERS flag. 2370 // Thus, updating the settings to install the app for all users. 2371 for (int currentUserId : allUsers) { 2372 // If the app is already installed for the currentUser, 2373 // keep it as installed as we might be updating the app at this place. 2374 // If not currently installed, check if the currentUser is restricted by 2375 // DISALLOW_INSTALL_APPS or DISALLOW_DEBUGGING_FEATURES device policy. 2376 // Install / update the app if the user isn't restricted. Skip otherwise. 2377 final boolean installedForCurrentUser = ArrayUtils.contains( 2378 installedForUsers, currentUserId); 2379 final boolean restrictedByPolicy = 2380 mPm.isUserRestricted(currentUserId, 2381 UserManager.DISALLOW_INSTALL_APPS) 2382 || mPm.isUserRestricted(currentUserId, 2383 UserManager.DISALLOW_DEBUGGING_FEATURES); 2384 if (installedForCurrentUser || !restrictedByPolicy) { 2385 ps.setInstalled(true, currentUserId); 2386 if (!installRequest.isApplicationEnabledSettingPersistent()) { 2387 ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, currentUserId, 2388 installerPackageName); 2389 } 2390 // Clear any existing archive state. 2391 mPm.mInstallerService.mPackageArchiver.clearArchiveState(ps, 2392 currentUserId); 2393 } else { 2394 ps.setInstalled(false, currentUserId); 2395 } 2396 } 2397 } 2398 2399 mPm.mSettings.addInstallerPackageNames(ps.getInstallSource()); 2400 2401 // When replacing an existing package, preserve the original install reason for all 2402 // users that had the package installed before. Similarly for uninstall reasons. 2403 final Set<Integer> previousUserIds = new ArraySet<>(); 2404 if (installRequest.getRemovedInfo() != null 2405 && installRequest.getRemovedInfo().mInstallReasons != null) { 2406 final int installReasonCount = 2407 installRequest.getRemovedInfo().mInstallReasons.size(); 2408 for (int i = 0; i < installReasonCount; i++) { 2409 final int previousUserId = 2410 installRequest.getRemovedInfo().mInstallReasons.keyAt(i); 2411 final int previousInstallReason = 2412 installRequest.getRemovedInfo().mInstallReasons.valueAt(i); 2413 ps.setInstallReason(previousInstallReason, previousUserId); 2414 previousUserIds.add(previousUserId); 2415 } 2416 } 2417 if (installRequest.getRemovedInfo() != null 2418 && installRequest.getRemovedInfo().mUninstallReasons != null) { 2419 for (int i = 0; i < installRequest.getRemovedInfo().mUninstallReasons.size(); 2420 i++) { 2421 final int previousUserId = 2422 installRequest.getRemovedInfo().mUninstallReasons.keyAt(i); 2423 final int previousReason = 2424 installRequest.getRemovedInfo().mUninstallReasons.valueAt(i); 2425 ps.setUninstallReason(previousReason, previousUserId); 2426 } 2427 } 2428 2429 // Set install reason for users that are having the package newly installed. 2430 if (userId == UserHandle.USER_ALL) { 2431 for (int currentUserId : allUsers) { 2432 if (!previousUserIds.contains(currentUserId) 2433 && ps.getInstalled(currentUserId)) { 2434 ps.setInstallReason(installReason, currentUserId); 2435 } 2436 } 2437 } else if (!previousUserIds.contains(userId)) { 2438 ps.setInstallReason(installReason, userId); 2439 } 2440 2441 // TODO(b/169721400): generalize Incremental States and create a Callback object 2442 // that can be used for all the packages. 2443 final String codePath = ps.getPathString(); 2444 if (IncrementalManager.isIncrementalPath(codePath) 2445 && mIncrementalManager != null) { 2446 mIncrementalManager.registerLoadingProgressCallback(codePath, 2447 new IncrementalProgressListener(ps.getPackageName(), mPm)); 2448 } 2449 2450 // Ensure that the uninstall reason is UNKNOWN for users with the package installed. 2451 for (int currentUserId : allUsers) { 2452 if (ps.getInstalled(currentUserId)) { 2453 ps.setUninstallReason(UNINSTALL_REASON_UNKNOWN, currentUserId); 2454 } 2455 } 2456 2457 mPm.mSettings.writeKernelMappingLPr(ps); 2458 2459 final PermissionManagerServiceInternal.PackageInstalledParams.Builder 2460 permissionParamsBuilder = 2461 new PermissionManagerServiceInternal.PackageInstalledParams.Builder(); 2462 final boolean grantRequestedPermissions = (installRequest.getInstallFlags() 2463 & PackageManager.INSTALL_GRANT_ALL_REQUESTED_PERMISSIONS) != 0; 2464 if (grantRequestedPermissions) { 2465 var permissionStates = new ArrayMap<String, Integer>(); 2466 for (var permissionName : pkg.getRequestedPermissions()) { 2467 permissionStates.put(permissionName, 2468 PackageInstaller.SessionParams.PERMISSION_STATE_GRANTED); 2469 } 2470 permissionParamsBuilder.setPermissionStates(permissionStates); 2471 } else { 2472 var permissionStates = installRequest.getPermissionStates(); 2473 if (permissionStates != null) { 2474 permissionParamsBuilder 2475 .setPermissionStates(permissionStates); 2476 } 2477 } 2478 final boolean allowlistAllRestrictedPermissions = 2479 (installRequest.getInstallFlags() 2480 & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) != 0; 2481 final List<String> allowlistedRestrictedPermissions = 2482 allowlistAllRestrictedPermissions 2483 ? new ArrayList<>(pkg.getRequestedPermissions()) 2484 : installRequest.getAllowlistedRestrictedPermissions(); 2485 if (allowlistedRestrictedPermissions != null) { 2486 permissionParamsBuilder.setAllowlistedRestrictedPermissions( 2487 allowlistedRestrictedPermissions); 2488 } 2489 final int autoRevokePermissionsMode = installRequest.getAutoRevokePermissionsMode(); 2490 permissionParamsBuilder.setAutoRevokePermissionsMode(autoRevokePermissionsMode); 2491 mPm.mPermissionManager.onPackageInstalled(pkg, installRequest.getPreviousAppId(), 2492 permissionParamsBuilder.build(), userId); 2493 } 2494 installRequest.setName(pkgName); 2495 installRequest.setAppId(pkg.getUid()); 2496 installRequest.setPkg(pkg); 2497 installRequest.setReturnCode(PackageManager.INSTALL_SUCCEEDED); 2498 //to update install status 2499 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "writeSettings"); 2500 mPm.writeSettingsLPrTEMP(); 2501 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 2502 } 2503 2504 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 2505 } 2506 setAccessRestrictedSettingsMode(String pkgName, int appId, int userId, int mode)2507 private void setAccessRestrictedSettingsMode(String pkgName, int appId, int userId, int mode) { 2508 final AppOpsManager appOpsManager = mPm.mContext.getSystemService(AppOpsManager.class); 2509 final int uid = UserHandle.getUid(userId, appId); 2510 appOpsManager.setMode(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, 2511 uid, 2512 pkgName, 2513 mode); 2514 } 2515 2516 /** 2517 * On successful install, executes remaining steps after commit completes and the package lock 2518 * is released. These are typically more expensive or require calls to installd, which often 2519 * locks on {@link com.android.server.pm.PackageManagerService.mLock}. 2520 */ 2521 @GuardedBy("mPm.mInstallLock") executePostCommitStepsLIF(List<ReconciledPackage> reconciledPackages)2522 private void executePostCommitStepsLIF(List<ReconciledPackage> reconciledPackages) { 2523 final ArraySet<IncrementalStorage> incrementalStorages = new ArraySet<>(); 2524 for (ReconciledPackage reconciledPkg : reconciledPackages) { 2525 final InstallRequest installRequest = reconciledPkg.mInstallRequest; 2526 final PackageSetting ps = installRequest.getScannedPackageSetting(); 2527 final String packageName = ps.getPackageName(); 2528 final String codePath = ps.getPathString(); 2529 final AndroidPackage pkg = ps.getPkg(); 2530 final boolean onIncremental = mIncrementalManager != null 2531 && isIncrementalPath(codePath); 2532 if (onIncremental) { 2533 IncrementalStorage storage = mIncrementalManager.openStorage(codePath); 2534 if (storage == null) { 2535 throw new IllegalArgumentException( 2536 "Install: null storage for incremental package " + packageName); 2537 } 2538 incrementalStorages.add(storage); 2539 } 2540 2541 // Hardcode previousAppId to 0 to disable any data migration (http://b/221088088) 2542 mAppDataHelper.prepareAppDataPostCommitLIF(ps, 0, installRequest.getNewUsers()); 2543 if (installRequest.isClearCodeCache()) { 2544 mAppDataHelper.clearAppDataLIF(ps.getPkg(), UserHandle.USER_ALL, 2545 FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL 2546 | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); 2547 } 2548 if (installRequest.isInstallReplace() && pkg != null) { 2549 mDexManager.notifyPackageUpdated(packageName, 2550 pkg.getBaseApkPath(), pkg.getSplitCodePaths()); 2551 } 2552 2553 // Construct the DexoptOptions early to see if we should skip running dexopt. 2554 // 2555 // Do not run PackageDexOptimizer through the local performDexOpt 2556 // method because `pkg` may not be in `mPackages` yet. 2557 // 2558 // Also, don't fail application installs if the dexopt step fails. 2559 DexoptOptions dexoptOptions = DexOptHelper.getDexoptOptionsByInstallRequest( 2560 installRequest, mDexManager); 2561 // Check whether we need to dexopt the app. 2562 // 2563 // NOTE: it is IMPORTANT to call dexopt: 2564 // - after doRename which will sync the package data from AndroidPackage and 2565 // its corresponding ApplicationInfo. 2566 // - after installNewPackageLIF or replacePackageLIF which will update result with the 2567 // uid of the application (pkg.applicationInfo.uid). 2568 // This update happens in place! 2569 // 2570 // We only need to dexopt if the package meets ALL of the following conditions: 2571 // 1) it is not an instant app or if it is then dexopt is enabled via gservices. 2572 // 2) it is not debuggable. 2573 // 3) it is not on Incremental File System. 2574 // 2575 // Note that we do not dexopt instant apps by default. dexopt can take some time to 2576 // complete, so we skip this step during installation. Instead, we'll take extra time 2577 // the first time the instant app starts. It's preferred to do it this way to provide 2578 // continuous progress to the useur instead of mysteriously blocking somewhere in the 2579 // middle of running an instant app. The default behaviour can be overridden 2580 // via gservices. 2581 // 2582 // Furthermore, dexopt may be skipped, depending on the install scenario and current 2583 // state of the device. 2584 // 2585 // TODO(b/174695087): instantApp and onIncremental should be removed and their install 2586 // path moved to SCENARIO_FAST. 2587 2588 final boolean performDexopt = DexOptHelper.shouldPerformDexopt(installRequest, 2589 dexoptOptions, mContext); 2590 if (performDexopt) { 2591 // dexopt can take long, and ArtService doesn't require installd, so we release 2592 // the lock here and re-acquire the lock after dexopt is finished. 2593 PackageManagerTracedLock.RawLock installLock = mPm.mInstallLock.getRawLock(); 2594 installLock.unlock(); 2595 try { 2596 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt"); 2597 2598 // This mirrors logic from commitReconciledScanResultLocked, where the library 2599 // files needed for dexopt are assigned. 2600 PackageSetting realPkgSetting = installRequest.getRealPackageSetting(); 2601 2602 // Unfortunately, the updated system app flag is only tracked on this 2603 // PackageSetting 2604 boolean isUpdatedSystemApp = 2605 installRequest.getScannedPackageSetting().isUpdatedSystemApp(); 2606 2607 realPkgSetting.getPkgState().setUpdatedSystemApp(isUpdatedSystemApp); 2608 2609 DexoptResult dexOptResult = DexOptHelper.dexoptPackageUsingArtService( 2610 installRequest, dexoptOptions); 2611 installRequest.onDexoptFinished(dexOptResult); 2612 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 2613 } finally { 2614 installLock.lock(); 2615 } 2616 } 2617 } 2618 PackageManagerServiceUtils.waitForNativeBinariesExtractionForIncremental( 2619 incrementalStorages); 2620 } 2621 verifyReplacingVersionCode(PackageInfoLite pkgLite, long requiredInstalledVersionCode, int installFlags)2622 Pair<Integer, String> verifyReplacingVersionCode(PackageInfoLite pkgLite, 2623 long requiredInstalledVersionCode, int installFlags) { 2624 if ((installFlags & PackageManager.INSTALL_APEX) != 0) { 2625 return verifyReplacingVersionCodeForApex( 2626 pkgLite, requiredInstalledVersionCode, installFlags); 2627 } 2628 2629 String packageName = pkgLite.packageName; 2630 synchronized (mPm.mLock) { 2631 // Package which currently owns the data that the new package will own if installed. 2632 // If an app is uninstalled while keeping data (e.g. adb uninstall -k), installedPkg 2633 // will be null whereas dataOwnerPkg will contain information about the package 2634 // which was uninstalled while keeping its data. 2635 AndroidPackage dataOwnerPkg = mPm.mPackages.get(packageName); 2636 PackageSetting dataOwnerPs = mPm.mSettings.getPackageLPr(packageName); 2637 if (dataOwnerPkg == null) { 2638 if (dataOwnerPs != null) { 2639 dataOwnerPkg = dataOwnerPs.getPkg(); 2640 } 2641 } 2642 2643 if (requiredInstalledVersionCode != PackageManager.VERSION_CODE_HIGHEST) { 2644 if (dataOwnerPkg == null) { 2645 String errorMsg = "Required installed version code was " 2646 + requiredInstalledVersionCode 2647 + " but package is not installed"; 2648 Slog.w(TAG, errorMsg); 2649 return Pair.create( 2650 PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION, errorMsg); 2651 } 2652 2653 if (dataOwnerPkg.getLongVersionCode() != requiredInstalledVersionCode) { 2654 String errorMsg = "Required installed version code was " 2655 + requiredInstalledVersionCode 2656 + " but actual installed version is " 2657 + dataOwnerPkg.getLongVersionCode(); 2658 Slog.w(TAG, errorMsg); 2659 return Pair.create( 2660 PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION, errorMsg); 2661 } 2662 } 2663 2664 if (dataOwnerPkg != null && !dataOwnerPkg.isSdkLibrary()) { 2665 if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags, 2666 dataOwnerPkg.isDebuggable())) { 2667 // Downgrade is not permitted; a lower version of the app will not be allowed 2668 try { 2669 PackageManagerServiceUtils.checkDowngrade(dataOwnerPkg, pkgLite); 2670 } catch (PackageManagerException e) { 2671 String errorMsg = "Downgrade detected: " + e.getMessage(); 2672 Slog.w(TAG, errorMsg); 2673 return Pair.create( 2674 PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg); 2675 } 2676 } else if (dataOwnerPs.isSystem()) { 2677 // Downgrade is permitted, but system apps can't be downgraded below 2678 // the version preloaded onto the system image 2679 final PackageSetting disabledPs = mPm.mSettings.getDisabledSystemPkgLPr( 2680 dataOwnerPs); 2681 if (disabledPs != null) { 2682 dataOwnerPkg = disabledPs.getPkg(); 2683 } 2684 if (!Build.IS_DEBUGGABLE && !dataOwnerPkg.isDebuggable()) { 2685 // Only restrict non-debuggable builds and non-debuggable version of the app 2686 try { 2687 PackageManagerServiceUtils.checkDowngrade(dataOwnerPkg, pkgLite); 2688 } catch (PackageManagerException e) { 2689 String errorMsg = 2690 "System app: " + packageName + " cannot be downgraded to" 2691 + " older than its preloaded version on the system" 2692 + " image. " + e.getMessage(); 2693 Slog.w(TAG, errorMsg); 2694 return Pair.create( 2695 PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg); 2696 } 2697 } 2698 } 2699 } 2700 } 2701 return Pair.create(PackageManager.INSTALL_SUCCEEDED, null); 2702 } 2703 verifyReplacingVersionCodeForApex(PackageInfoLite pkgLite, long requiredInstalledVersionCode, int installFlags)2704 private Pair<Integer, String> verifyReplacingVersionCodeForApex(PackageInfoLite pkgLite, 2705 long requiredInstalledVersionCode, int installFlags) { 2706 String packageName = pkgLite.packageName; 2707 2708 final PackageInfo activePackage = mPm.snapshotComputer().getPackageInfo( 2709 packageName, PackageManager.MATCH_APEX, UserHandle.USER_SYSTEM); 2710 if (activePackage == null) { 2711 String errorMsg = "Attempting to install new APEX package " + packageName; 2712 Slog.w(TAG, errorMsg); 2713 return Pair.create(PackageManager.INSTALL_FAILED_PACKAGE_CHANGED, errorMsg); 2714 } 2715 2716 final long activeVersion = activePackage.getLongVersionCode(); 2717 if (requiredInstalledVersionCode != PackageManager.VERSION_CODE_HIGHEST 2718 && activeVersion != requiredInstalledVersionCode) { 2719 String errorMsg = "Installed version of APEX package " + packageName 2720 + " does not match required. Active version: " + activeVersion 2721 + " required: " + requiredInstalledVersionCode; 2722 Slog.w(TAG, errorMsg); 2723 return Pair.create(PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION, errorMsg); 2724 } 2725 2726 final boolean isAppDebuggable = (activePackage.applicationInfo.flags 2727 & ApplicationInfo.FLAG_DEBUGGABLE) != 0; 2728 final long newVersionCode = pkgLite.getLongVersionCode(); 2729 if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags, isAppDebuggable) 2730 && newVersionCode < activeVersion) { 2731 String errorMsg = "Downgrade of APEX package " + packageName 2732 + " is not allowed. Active version: " + activeVersion 2733 + " attempted: " + newVersionCode; 2734 Slog.w(TAG, errorMsg); 2735 return Pair.create(PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg); 2736 } 2737 2738 return Pair.create(PackageManager.INSTALL_SUCCEEDED, null); 2739 } 2740 getUidForVerifier(VerifierInfo verifierInfo)2741 int getUidForVerifier(VerifierInfo verifierInfo) { 2742 synchronized (mPm.mLock) { 2743 final AndroidPackage pkg = mPm.mPackages.get(verifierInfo.packageName); 2744 if (pkg == null) { 2745 return -1; 2746 } else if (pkg.getSigningDetails().getSignatures().length != 1) { 2747 Slog.i(TAG, "Verifier package " + verifierInfo.packageName 2748 + " has more than one signature; ignoring"); 2749 return -1; 2750 } 2751 2752 /* 2753 * If the public key of the package's signature does not match 2754 * our expected public key, then this is a different package and 2755 * we should skip. 2756 */ 2757 2758 final byte[] expectedPublicKey; 2759 try { 2760 final Signature verifierSig = pkg.getSigningDetails().getSignatures()[0]; 2761 final PublicKey publicKey = verifierSig.getPublicKey(); 2762 expectedPublicKey = publicKey.getEncoded(); 2763 } catch (CertificateException e) { 2764 return -1; 2765 } 2766 2767 final byte[] actualPublicKey = verifierInfo.publicKey.getEncoded(); 2768 2769 if (!Arrays.equals(actualPublicKey, expectedPublicKey)) { 2770 Slog.i(TAG, "Verifier package " + verifierInfo.packageName 2771 + " does not have the expected public key; ignoring"); 2772 return -1; 2773 } 2774 2775 return pkg.getUid(); 2776 } 2777 } 2778 sendPendingBroadcasts()2779 public void sendPendingBroadcasts() { 2780 String[] packages; 2781 ArrayList<String>[] components; 2782 int numBroadcasts = 0, numUsers; 2783 int[] uids; 2784 2785 synchronized (mPm.mLock) { 2786 final SparseArray<ArrayMap<String, ArrayList<String>>> userIdToPackagesToComponents = 2787 mPm.mPendingBroadcasts.copiedMap(); 2788 numUsers = userIdToPackagesToComponents.size(); 2789 for (int n = 0; n < numUsers; n++) { 2790 numBroadcasts += userIdToPackagesToComponents.valueAt(n).size(); 2791 } 2792 if (numBroadcasts == 0) { 2793 // Nothing to be done. Just return 2794 return; 2795 } 2796 packages = new String[numBroadcasts]; 2797 components = new ArrayList[numBroadcasts]; 2798 uids = new int[numBroadcasts]; 2799 int i = 0; // filling out the above arrays 2800 2801 for (int n = 0; n < numUsers; n++) { 2802 final int packageUserId = userIdToPackagesToComponents.keyAt(n); 2803 final ArrayMap<String, ArrayList<String>> componentsToBroadcast = 2804 userIdToPackagesToComponents.valueAt(n); 2805 final int numComponents = CollectionUtils.size(componentsToBroadcast); 2806 for (int index = 0; index < numComponents; index++) { 2807 packages[i] = componentsToBroadcast.keyAt(index); 2808 components[i] = componentsToBroadcast.valueAt(index); 2809 final PackageSetting ps = mPm.mSettings.getPackageLPr(packages[i]); 2810 uids[i] = (ps != null) 2811 ? UserHandle.getUid(packageUserId, ps.getAppId()) 2812 : -1; 2813 i++; 2814 } 2815 } 2816 numBroadcasts = i; 2817 mPm.mPendingBroadcasts.clear(); 2818 } 2819 final Computer snapshot = mPm.snapshotComputer(); 2820 // Send broadcasts 2821 for (int i = 0; i < numBroadcasts; i++) { 2822 mBroadcastHelper.sendPackageChangedBroadcast(snapshot, packages[i], 2823 true /* dontKillApp */, components[i], uids[i], null /* reason */); 2824 } 2825 } 2826 handlePackagePostInstall(InstallRequest request, boolean launchedForRestore)2827 void handlePackagePostInstall(InstallRequest request, boolean launchedForRestore) { 2828 final boolean killApp = 2829 (request.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) == 0; 2830 final boolean succeeded = request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED; 2831 final boolean update = request.isUpdate(); 2832 final boolean archived = request.isArchived(); 2833 final String packageName = request.getName(); 2834 final Computer snapshot = mPm.snapshotComputer(); 2835 final PackageStateInternal pkgSetting = 2836 succeeded ? snapshot.getPackageStateInternal(packageName) : null; 2837 final boolean removedBeforeUpdate = (pkgSetting == null) 2838 || (pkgSetting.isSystem() && !pkgSetting.getPath().getPath().equals( 2839 request.getPkg().getPath())); 2840 if (succeeded && removedBeforeUpdate) { 2841 Slog.e(TAG, packageName + " was removed before handlePackagePostInstall " 2842 + "could be executed"); 2843 request.setReturnCode(INSTALL_FAILED_PACKAGE_CHANGED); 2844 request.setReturnMessage("Package was removed before install could complete."); 2845 2846 // Remove the update failed package's older resources safely now 2847 mRemovePackageHelper.cleanUpResources(packageName, request.getOldCodeFile(), 2848 request.getOldInstructionSet()); 2849 mPm.notifyInstallObserver(request); 2850 return; 2851 } 2852 2853 if (succeeded) { 2854 if (Flags.aslInApkAppMetadataSource() 2855 && pkgSetting.getAppMetadataSource() == APP_METADATA_SOURCE_APK) { 2856 if (!extractAppMetadataFromApk(request.getPkg(), 2857 pkgSetting.getAppMetadataFilePath(), pkgSetting.isSystem())) { 2858 synchronized (mPm.mLock) { 2859 PackageSetting setting = mPm.mSettings.getPackageLPr(packageName); 2860 if (setting != null) { 2861 setting.setAppMetadataFilePath(null) 2862 .setAppMetadataSource(APP_METADATA_SOURCE_UNKNOWN); 2863 } 2864 } 2865 } 2866 } 2867 2868 // Clear the uid cache after we installed a new package. 2869 mPm.mPerUidReadTimeoutsCache = null; 2870 2871 mPm.notifyInstantAppPackageInstalled(request.getPkg().getPackageName(), 2872 request.getNewUsers()); 2873 2874 final int[] firstUserIds = request.getFirstTimeBroadcastUserIds(); 2875 2876 if (request.getPkg().getStaticSharedLibraryName() == null) { 2877 mPm.mProcessLoggingHandler.invalidateBaseApkHash(request.getPkg().getBaseApkPath()); 2878 } 2879 2880 mBroadcastHelper.sendPostInstallBroadcasts(mPm.snapshotComputer(), request, packageName, 2881 mPm.mRequiredPermissionControllerPackage, mPm.mRequiredVerifierPackages, 2882 mPm.mRequiredInstallerPackage, 2883 /* packageSender= */ mPm, launchedForRestore, killApp, update, archived); 2884 2885 if (request.isAllNewUsers() && !update) { 2886 mPm.notifyPackageAdded(packageName, request.getAppId()); 2887 } else { 2888 mPm.notifyPackageChanged(packageName, request.getAppId()); 2889 } 2890 2891 // Set the OP_ACCESS_RESTRICTED_SETTINGS op, which is used by ECM (see {@link 2892 // EnhancedConfirmationManager}) as a persistent state denoting whether an app is 2893 // currently guarded by ECM, not guarded by ECM, or (in Android V+) that this should 2894 // be decided later. 2895 if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled() 2896 && android.security.Flags.extendEcmToAllSettings()) { 2897 final int appId = request.getAppId(); 2898 mPm.mHandler.post(() -> { 2899 for (int userId : firstUserIds) { 2900 // MODE_DEFAULT means that the app's guardedness will be decided lazily 2901 setAccessRestrictedSettingsMode(packageName, appId, userId, 2902 AppOpsManager.MODE_DEFAULT); 2903 } 2904 }); 2905 } else { 2906 // Apply restricted settings on potentially dangerous packages. Needs to happen 2907 // after appOpsManager is notified of the new package 2908 if (request.getPackageSource() == PackageInstaller.PACKAGE_SOURCE_LOCAL_FILE 2909 || request.getPackageSource() 2910 == PackageInstaller.PACKAGE_SOURCE_DOWNLOADED_FILE) { 2911 final int appId = request.getAppId(); 2912 mPm.mHandler.post(() -> { 2913 for (int userId : firstUserIds) { 2914 // MODE_ERRORED means that the app is explicitly guarded 2915 setAccessRestrictedSettingsMode(packageName, appId, userId, 2916 AppOpsManager.MODE_ERRORED); 2917 } 2918 }); 2919 } 2920 } 2921 2922 // Log current value of "unknown sources" setting 2923 EventLog.writeEvent(EventLogTags.UNKNOWN_SOURCES_ENABLED, 2924 getUnknownSourcesSettings()); 2925 2926 // Remove the replaced package's older resources safely now 2927 CleanUpArgs args = request.getRemovedInfo() != null 2928 ? request.getRemovedInfo().mArgs : null; 2929 if (args != null) { 2930 if (!killApp) { 2931 // If we didn't kill the app, defer the deletion of code/resource files, 2932 // since the old code/resource files may still be in use by the running 2933 // application. This mitigates problems and cases where resources or 2934 // code is loaded by a new Activity before ApplicationInfo changes have 2935 // propagated to all application threads. 2936 mPm.scheduleDeferredNoKillPostDelete(args); 2937 if (Flags.improveInstallDontKill()) { 2938 try (var installLock = mPm.mInstallLock.acquireLock()) { 2939 PackageManagerServiceUtils.linkFilesToOldDirs(mPm.mInstaller, 2940 packageName, pkgSetting.getPath(), pkgSetting.getOldPaths()); 2941 } 2942 } 2943 } else { 2944 mRemovePackageHelper.cleanUpResources(packageName, args.getCodeFile(), 2945 args.getInstructionSets()); 2946 } 2947 } else { 2948 // Force a gc to clear up things. Ask for a background one, it's fine to go on 2949 // and not block here. 2950 VMRuntime.getRuntime().requestConcurrentGC(); 2951 } 2952 2953 if (!archived) { 2954 // Notify DexManager that the package was installed for new users. 2955 // The updated users should already be indexed and the package code paths 2956 // should not change. 2957 // Don't notify the manager for ephemeral apps as they are not expected to 2958 // survive long enough to benefit of background optimizations. 2959 for (int userId : firstUserIds) { 2960 PackageInfo info = snapshot.getPackageInfo(packageName, /*flags*/ 0, userId); 2961 // There's a race currently where some install events may interleave with an 2962 // uninstall. This can lead to package info being null (b/36642664). 2963 if (info != null) { 2964 mDexManager.notifyPackageInstalled(info, userId); 2965 } 2966 } 2967 } else { 2968 // Now send PACKAGE_REMOVED + EXTRA_REPLACING broadcast. 2969 final PackageRemovedInfo info = new PackageRemovedInfo(); 2970 info.mRemovedPackage = packageName; 2971 info.mInstallerPackageName = request.getInstallerPackageName(); 2972 info.mRemovedUsers = firstUserIds; 2973 info.mBroadcastUsers = firstUserIds; 2974 info.mUid = request.getAppId(); 2975 info.mRemovedPackageVersionCode = request.getPkg().getLongVersionCode(); 2976 info.mRemovedForAllUsers = true; 2977 2978 mBroadcastHelper.sendPackageRemovedBroadcasts(info, mPm, 2979 false /*killApp*/, false /*removedBySystem*/, true /*isArchived*/); 2980 } 2981 } 2982 2983 final boolean deferInstallObserver = succeeded && update; 2984 if (deferInstallObserver) { 2985 if (killApp) { 2986 mPm.scheduleDeferredPendingKillInstallObserver(request); 2987 } else { 2988 mPm.scheduleDeferredNoKillInstallObserver(request); 2989 } 2990 } else { 2991 mPm.notifyInstallObserver(request); 2992 } 2993 2994 // Prune unused static shared libraries which have been cached a period of time 2995 mPm.schedulePruneUnusedStaticSharedLibraries(true /* delay */); 2996 2997 // Log tracing if needed 2998 if (request.getTraceMethod() != null) { 2999 Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, request.getTraceMethod(), 3000 request.getTraceCookie()); 3001 } 3002 } 3003 3004 /** 3005 * Get the "allow unknown sources" setting. 3006 * 3007 * @return the current "allow unknown sources" setting 3008 */ getUnknownSourcesSettings()3009 private int getUnknownSourcesSettings() { 3010 return android.provider.Settings.Secure.getIntForUser(mContext.getContentResolver(), 3011 android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS, 3012 -1, UserHandle.USER_SYSTEM); 3013 } 3014 3015 /** 3016 * Uncompress and install stub applications. 3017 * <p>In order to save space on the system partition, some applications are shipped in a 3018 * compressed form. In addition the compressed bits for the full application, the 3019 * system image contains a tiny stub comprised of only the Android manifest. 3020 * <p>During the first boot, attempt to uncompress and install the full application. If 3021 * the application can't be installed for any reason, disable the stub and prevent 3022 * uncompressing the full application during future boots. 3023 * <p>In order to forcefully attempt an installation of a full application, go to app 3024 * settings and enable the application. 3025 */ 3026 @GuardedBy({"mPm.mLock", "mPm.mInstallLock"}) installSystemStubPackages(@onNull List<String> systemStubPackageNames, @PackageManagerService.ScanFlags int scanFlags)3027 void installSystemStubPackages(@NonNull List<String> systemStubPackageNames, 3028 @PackageManagerService.ScanFlags int scanFlags) { 3029 for (int i = systemStubPackageNames.size() - 1; i >= 0; --i) { 3030 final String packageName = systemStubPackageNames.get(i); 3031 // skip if the system package is already disabled 3032 if (mPm.mSettings.isDisabledSystemPackageLPr(packageName)) { 3033 systemStubPackageNames.remove(i); 3034 continue; 3035 } 3036 // skip if the package isn't installed (?!); this should never happen 3037 final AndroidPackage pkg = mPm.mPackages.get(packageName); 3038 if (pkg == null) { 3039 systemStubPackageNames.remove(i); 3040 continue; 3041 } 3042 // skip if the package has been disabled by the user 3043 final PackageSetting ps = mPm.mSettings.getPackageLPr(packageName); 3044 if (ps != null) { 3045 final int enabledState = ps.getEnabled(UserHandle.USER_SYSTEM); 3046 if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) { 3047 systemStubPackageNames.remove(i); 3048 continue; 3049 } 3050 } 3051 3052 // install the package to replace the stub on /system 3053 try { 3054 installStubPackageLI(pkg, 0, scanFlags); 3055 ps.setEnabled(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 3056 UserHandle.USER_SYSTEM, "android"); 3057 systemStubPackageNames.remove(i); 3058 } catch (PackageManagerException e) { 3059 Slog.e(TAG, "Failed to parse uncompressed system package: " + e.getMessage()); 3060 } 3061 3062 // any failed attempt to install the package will be cleaned up later 3063 } 3064 3065 // disable any stub still left; these failed to install the full application 3066 for (int i = systemStubPackageNames.size() - 1; i >= 0; --i) { 3067 final String pkgName = systemStubPackageNames.get(i); 3068 final PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName); 3069 ps.setEnabled(PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 3070 UserHandle.USER_SYSTEM, "android"); 3071 logCriticalInfo(Log.ERROR, "Stub disabled; pkg: " + pkgName); 3072 } 3073 } 3074 3075 /** 3076 * Extract, install and enable a stub package. 3077 * <p>If the compressed file can not be extracted / installed for any reason, the stub 3078 * APK will be installed and the package will be disabled. To recover from this situation, 3079 * the user will need to go into system settings and re-enable the package. 3080 */ enableCompressedPackage(AndroidPackage stubPkg, @NonNull PackageSetting stubPkgSetting)3081 boolean enableCompressedPackage(AndroidPackage stubPkg, 3082 @NonNull PackageSetting stubPkgSetting) { 3083 final int parseFlags = mPm.getDefParseFlags() | ParsingPackageUtils.PARSE_CHATTY 3084 | ParsingPackageUtils.PARSE_ENFORCE_CODE; 3085 try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { 3086 final AndroidPackage pkg; 3087 try (PackageFreezer freezer = 3088 mPm.freezePackage(stubPkg.getPackageName(), UserHandle.USER_ALL, 3089 "setEnabledSetting", 3090 ApplicationExitInfo.REASON_PACKAGE_UPDATED, null /* request */)) { 3091 pkg = installStubPackageLI(stubPkg, parseFlags, 0 /*scanFlags*/); 3092 mAppDataHelper.prepareAppDataAfterInstallLIF(pkg); 3093 synchronized (mPm.mLock) { 3094 try { 3095 mSharedLibraries.updateSharedLibraries( 3096 pkg, stubPkgSetting, null, null, 3097 Collections.unmodifiableMap(mPm.mPackages)); 3098 } catch (PackageManagerException e) { 3099 Slog.w(TAG, "updateAllSharedLibrariesLPw failed: ", e); 3100 } 3101 mPm.mPermissionManager.onPackageInstalled(pkg, 3102 Process.INVALID_UID /* previousAppId */, 3103 PermissionManagerServiceInternal.PackageInstalledParams.DEFAULT, 3104 UserHandle.USER_ALL); 3105 mPm.writeSettingsLPrTEMP(); 3106 // Since compressed package can be system app only, we do not need to 3107 // set restricted settings on it. 3108 } 3109 } catch (PackageManagerException e) { 3110 // Whoops! Something went very wrong; roll back to the stub and disable the package 3111 try (PackageFreezer freezer = 3112 mPm.freezePackage(stubPkg.getPackageName(), UserHandle.USER_ALL, 3113 "setEnabledSetting", 3114 ApplicationExitInfo.REASON_PACKAGE_UPDATED, 3115 null /* request */)) { 3116 synchronized (mPm.mLock) { 3117 // NOTE: Ensure the system package is enabled; even for a compressed stub. 3118 // If we don't, installing the system package fails during scan 3119 mPm.mSettings.enableSystemPackageLPw(stubPkg.getPackageName()); 3120 } 3121 installPackageFromSystemLIF(stubPkg.getPath(), 3122 mPm.mUserManager.getUserIds() /*allUserHandles*/, 3123 null /*origUserHandles*/, 3124 true /*writeSettings*/); 3125 } catch (PackageManagerException pme) { 3126 // Serious WTF; we have to be able to install the stub 3127 Slog.wtf(TAG, "Failed to restore system package:" + stubPkg.getPackageName(), 3128 pme); 3129 } finally { 3130 // Disable the package; the stub by itself is not runnable 3131 synchronized (mPm.mLock) { 3132 final PackageSetting stubPs = mPm.mSettings.getPackageLPr( 3133 stubPkg.getPackageName()); 3134 if (stubPs != null) { 3135 stubPs.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, 3136 UserHandle.USER_SYSTEM, "android"); 3137 } 3138 mPm.writeSettingsLPrTEMP(); 3139 } 3140 } 3141 return false; 3142 } 3143 mAppDataHelper.clearAppDataLIF(pkg, UserHandle.USER_ALL, 3144 FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL 3145 | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); 3146 mDexManager.notifyPackageUpdated(pkg.getPackageName(), 3147 pkg.getBaseApkPath(), pkg.getSplitCodePaths()); 3148 } 3149 return true; 3150 } 3151 3152 @GuardedBy("mPm.mInstallLock") installStubPackageLI(AndroidPackage stubPkg, @ParsingPackageUtils.ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags)3153 private AndroidPackage installStubPackageLI(AndroidPackage stubPkg, 3154 @ParsingPackageUtils.ParseFlags int parseFlags, 3155 @PackageManagerService.ScanFlags int scanFlags) 3156 throws PackageManagerException { 3157 if (DEBUG_COMPRESSION) { 3158 Slog.i(TAG, "Uncompressing system stub; pkg: " + stubPkg.getPackageName()); 3159 } 3160 // uncompress the binary to its eventual destination on /data 3161 final File scanFile = decompressPackage(stubPkg.getPackageName(), stubPkg.getPath()); 3162 if (scanFile == null) { 3163 throw PackageManagerException.ofInternalError( 3164 "Unable to decompress stub at " + stubPkg.getPath(), 3165 PackageManagerException.INTERNAL_ERROR_DECOMPRESS_STUB); 3166 } 3167 synchronized (mPm.mLock) { 3168 mPm.mSettings.disableSystemPackageLPw(stubPkg.getPackageName(), true /*replaced*/); 3169 } 3170 mRemovePackageHelper.removePackage(stubPkg, true /*chatty*/); 3171 try { 3172 return initPackageTracedLI(scanFile, parseFlags, scanFlags); 3173 } catch (PackageManagerException e) { 3174 Slog.w(TAG, "Failed to install compressed system package:" + stubPkg.getPackageName(), 3175 e); 3176 // Remove the failed install 3177 mRemovePackageHelper.removeCodePath(scanFile); 3178 throw e; 3179 } 3180 } 3181 3182 /** 3183 * Decompresses the given package on the system image onto 3184 * the /data partition. 3185 * @return The directory the package was decompressed into. Otherwise, {@code null}. 3186 */ 3187 @GuardedBy("mPm.mInstallLock") decompressPackage(String packageName, String codePath)3188 private File decompressPackage(String packageName, String codePath) { 3189 if (!compressedFileExists(codePath)) { 3190 if (DEBUG_COMPRESSION) { 3191 Slog.i(TAG, "No files to decompress at: " + codePath); 3192 } 3193 return null; 3194 } 3195 final File dstCodePath = 3196 PackageManagerServiceUtils.getNextCodePath(Environment.getDataAppDirectory(null), 3197 packageName); 3198 int ret = PackageManagerServiceUtils.decompressFiles(codePath, dstCodePath, packageName); 3199 if (ret == PackageManager.INSTALL_SUCCEEDED) { 3200 ret = PackageManagerServiceUtils.extractNativeBinaries(dstCodePath, packageName); 3201 } 3202 if (ret == PackageManager.INSTALL_SUCCEEDED) { 3203 // NOTE: During boot, we have to delay releasing cblocks for no other reason than 3204 // we cannot retrieve the setting {@link Secure#RELEASE_COMPRESS_BLOCKS_ON_INSTALL}. 3205 // When we no longer need to read that setting, cblock release can occur always 3206 // occur here directly 3207 if (!mPm.isSystemReady()) { 3208 if (mPm.mReleaseOnSystemReady == null) { 3209 mPm.mReleaseOnSystemReady = new ArrayList<>(); 3210 } 3211 mPm.mReleaseOnSystemReady.add(dstCodePath); 3212 } else { 3213 final ContentResolver resolver = mContext.getContentResolver(); 3214 F2fsUtils.releaseCompressedBlocks(resolver, dstCodePath); 3215 } 3216 } else { 3217 if (!dstCodePath.exists()) { 3218 return null; 3219 } 3220 mRemovePackageHelper.removeCodePath(dstCodePath); 3221 return null; 3222 } 3223 3224 return dstCodePath; 3225 } 3226 3227 /** 3228 * Tries to restore the disabled system package after an update has been deleted. 3229 */ restoreDisabledSystemPackageLIF(DeletePackageAction action, @NonNull int[] allUserHandles, boolean writeSettings)3230 public void restoreDisabledSystemPackageLIF(DeletePackageAction action, 3231 @NonNull int[] allUserHandles, boolean writeSettings) throws SystemDeleteException { 3232 final PackageSetting deletedPs = action.mDeletingPs; 3233 final PackageRemovedInfo outInfo = action.mRemovedInfo; 3234 final PackageSetting disabledPs = action.mDisabledPs; 3235 3236 synchronized (mPm.mLock) { 3237 // NOTE: The system package always needs to be enabled; even if it's for 3238 // a compressed stub. If we don't, installing the system package fails 3239 // during scan [scanning checks the disabled packages]. We will reverse 3240 // this later, after we've "installed" the stub. 3241 // Reinstate the old system package 3242 mPm.mSettings.enableSystemPackageLPw(disabledPs.getPkg().getPackageName()); 3243 // Remove any native libraries from the upgraded package. 3244 PackageManagerServiceUtils.removeNativeBinariesLI(deletedPs); 3245 } 3246 // Install the system package 3247 if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs); 3248 try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { 3249 final int[] origUsers = outInfo == null ? null : outInfo.mOrigUsers; 3250 installPackageFromSystemLIF(disabledPs.getPathString(), allUserHandles, 3251 origUsers, writeSettings); 3252 } catch (PackageManagerException e) { 3253 Slog.w(TAG, "Failed to restore system package:" + deletedPs.getPackageName() + ": " 3254 + e.getMessage()); 3255 // TODO(b/194319951): can we avoid this; throw would come from scan... 3256 throw new SystemDeleteException(e); 3257 } finally { 3258 if (disabledPs.getPkg().isStub()) { 3259 // We've re-installed the stub; make sure it's disabled here. If package was 3260 // originally enabled, we'll install the compressed version of the application 3261 // and re-enable it afterward. 3262 synchronized (mPm.mLock) { 3263 disableStubPackage(action, deletedPs, allUserHandles); 3264 } 3265 } 3266 } 3267 } 3268 3269 @GuardedBy("mPm.mLock") disableStubPackage(DeletePackageAction action, PackageSetting deletedPs, @NonNull int[] allUserHandles)3270 private void disableStubPackage(DeletePackageAction action, PackageSetting deletedPs, 3271 @NonNull int[] allUserHandles) { 3272 final PackageSetting stubPs = mPm.mSettings.getPackageLPr( 3273 deletedPs.getPackageName()); 3274 if (stubPs != null) { 3275 int userId = action.mUser == null 3276 ? UserHandle.USER_ALL : action.mUser.getIdentifier(); 3277 if (userId == UserHandle.USER_ALL) { 3278 for (int aUserId : allUserHandles) { 3279 stubPs.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, aUserId, "android"); 3280 } 3281 } else if (userId >= UserHandle.USER_SYSTEM) { 3282 stubPs.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, userId, "android"); 3283 } 3284 } 3285 } 3286 3287 /** 3288 * Installs a package that's already on the system partition. 3289 */ 3290 @GuardedBy("mPm.mInstallLock") installPackageFromSystemLIF(@onNull String codePathString, @NonNull int[] allUserHandles, @Nullable int[] origUserHandles, boolean writeSettings)3291 private void installPackageFromSystemLIF(@NonNull String codePathString, 3292 @NonNull int[] allUserHandles, @Nullable int[] origUserHandles, 3293 boolean writeSettings) 3294 throws PackageManagerException { 3295 final File codePath = new File(codePathString); 3296 @ParsingPackageUtils.ParseFlags int parseFlags = 3297 mPm.getDefParseFlags() 3298 | ParsingPackageUtils.PARSE_MUST_BE_APK 3299 | ParsingPackageUtils.PARSE_IS_SYSTEM_DIR; 3300 @PackageManagerService.ScanFlags int scanFlags = mPm.getSystemPackageScanFlags(codePath); 3301 final AndroidPackage pkg = initPackageTracedLI(codePath, parseFlags, scanFlags); 3302 3303 synchronized (mPm.mLock) { 3304 PackageSetting pkgSetting = mPm.mSettings.getPackageLPr(pkg.getPackageName()); 3305 try { 3306 // update shared libraries for the newly re-installed system package 3307 mSharedLibraries.updateSharedLibraries(pkg, pkgSetting, null, null, 3308 Collections.unmodifiableMap(mPm.mPackages)); 3309 } catch (PackageManagerException e) { 3310 Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage()); 3311 } 3312 } 3313 setPackageInstalledForSystemPackage(pkg, allUserHandles, origUserHandles, writeSettings); 3314 3315 mAppDataHelper.prepareAppDataAfterInstallLIF(pkg); 3316 } 3317 setPackageInstalledForSystemPackage(@onNull AndroidPackage pkg, @NonNull int[] allUserHandles, @Nullable int[] origUserHandles, boolean writeSettings)3318 private void setPackageInstalledForSystemPackage(@NonNull AndroidPackage pkg, 3319 @NonNull int[] allUserHandles, @Nullable int[] origUserHandles, 3320 boolean writeSettings) { 3321 // writer 3322 synchronized (mPm.mLock) { 3323 PackageSetting ps = mPm.mSettings.getPackageLPr(pkg.getPackageName()); 3324 3325 final boolean applyUserRestrictions = origUserHandles != null; 3326 if (applyUserRestrictions) { 3327 boolean installedStateChanged = false; 3328 if (DEBUG_REMOVE) { 3329 Slog.d(TAG, "Propagating install state across reinstall"); 3330 } 3331 for (int userId : allUserHandles) { 3332 final boolean installed = ArrayUtils.contains(origUserHandles, userId); 3333 if (DEBUG_REMOVE) { 3334 Slog.d(TAG, " user " + userId + " => " + installed); 3335 } 3336 if (installed != ps.getInstalled(userId)) { 3337 installedStateChanged = true; 3338 } 3339 ps.setInstalled(installed, userId); 3340 if (installed) { 3341 ps.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userId); 3342 } 3343 } 3344 // Regardless of writeSettings we need to ensure that this restriction 3345 // state propagation is persisted 3346 mPm.mSettings.writeAllUsersPackageRestrictionsLPr(); 3347 if (installedStateChanged) { 3348 mPm.mSettings.writeKernelMappingLPr(ps); 3349 } 3350 } 3351 3352 // The method below will take care of removing obsolete permissions and granting 3353 // install permissions. 3354 mPm.mPermissionManager.onPackageInstalled(pkg, Process.INVALID_UID, 3355 PermissionManagerServiceInternal.PackageInstalledParams.DEFAULT, 3356 UserHandle.USER_ALL); 3357 for (final int userId : allUserHandles) { 3358 if (applyUserRestrictions) { 3359 mPm.mSettings.writePermissionStateForUserLPr(userId, false); 3360 } 3361 } 3362 3363 // can downgrade to reader here 3364 if (writeSettings) { 3365 mPm.writeSettingsLPrTEMP(); 3366 } 3367 } 3368 } 3369 3370 @GuardedBy("mPm.mLock") prepareSystemPackageCleanUp( WatchedArrayMap<String, PackageSetting> packageSettings, List<String> possiblyDeletedUpdatedSystemApps, ArrayMap<String, File> expectingBetter, int[] userIds)3371 public void prepareSystemPackageCleanUp( 3372 WatchedArrayMap<String, PackageSetting> packageSettings, 3373 List<String> possiblyDeletedUpdatedSystemApps, 3374 ArrayMap<String, File> expectingBetter, int[] userIds) { 3375 // Iterates PackageSettings in reversed order because the item could be removed 3376 // during the iteration. 3377 for (int index = packageSettings.size() - 1; index >= 0; index--) { 3378 final PackageSetting ps = packageSettings.valueAt(index); 3379 final String packageName = ps.getPackageName(); 3380 /* 3381 * If this is not a system app, it can't be a 3382 * disable system app. 3383 */ 3384 if (!ps.isSystem()) { 3385 continue; 3386 } 3387 3388 /* 3389 * If the package is scanned, it's not erased. 3390 */ 3391 final AndroidPackage scannedPkg = mPm.mPackages.get(packageName); 3392 final PackageSetting disabledPs = 3393 mPm.mSettings.getDisabledSystemPkgLPr(packageName); 3394 if (scannedPkg != null) { 3395 if (scannedPkg.isApex()) { 3396 // APEX on /data has been scanned. No need to expect better. 3397 continue; 3398 } 3399 /* 3400 * If the system app is both scanned and in the 3401 * disabled packages list, then it must have been 3402 * added via OTA. Remove it from the currently 3403 * scanned package so the previously user-installed 3404 * application can be scanned. 3405 */ 3406 if (disabledPs != null) { 3407 logCriticalInfo(Log.WARN, 3408 "Expecting better updated system app for " 3409 + packageName 3410 + "; removing system app. Last known" 3411 + " codePath=" + ps.getPathString() 3412 + ", versionCode=" + ps.getVersionCode() 3413 + "; scanned versionCode=" 3414 + scannedPkg.getLongVersionCode()); 3415 mRemovePackageHelper.removePackage(scannedPkg, true); 3416 expectingBetter.put(ps.getPackageName(), ps.getPath()); 3417 } 3418 3419 continue; 3420 } 3421 3422 if (disabledPs == null) { 3423 logCriticalInfo(Log.WARN, "System package " + packageName 3424 + " no longer exists; its data will be wiped"); 3425 mRemovePackageHelper.removePackageData(ps, userIds); 3426 } else { 3427 // we still have a disabled system package, but, it still might have 3428 // been removed. check the code path still exists and check there's 3429 // still a package. the latter can happen if an OTA keeps the same 3430 // code path, but, changes the package name. 3431 if (disabledPs.getPath() == null || !disabledPs.getPath().exists() 3432 || disabledPs.getPkg() == null) { 3433 possiblyDeletedUpdatedSystemApps.add(packageName); 3434 } else { 3435 // We're expecting that the system app should remain disabled, but add 3436 // it to expecting better to recover in case the data version cannot 3437 // be scanned. 3438 expectingBetter.put(disabledPs.getPackageName(), disabledPs.getPath()); 3439 } 3440 } 3441 } 3442 } 3443 3444 @GuardedBy("mPm.mLock") 3445 // Remove disable package settings for updated system apps that were 3446 // removed via an OTA. If the update is no longer present, remove the 3447 // app completely. Otherwise, revoke their system privileges. cleanupDisabledPackageSettings(List<String> possiblyDeletedUpdatedSystemApps, int[] userIds, int scanFlags)3448 public void cleanupDisabledPackageSettings(List<String> possiblyDeletedUpdatedSystemApps, 3449 int[] userIds, int scanFlags) { 3450 for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) { 3451 final String packageName = possiblyDeletedUpdatedSystemApps.get(i); 3452 final AndroidPackage pkg = mPm.mPackages.get(packageName); 3453 final String msg; 3454 3455 // remove from the disabled system list; do this first so any future 3456 // scans of this package are performed without this state 3457 mPm.mSettings.removeDisabledSystemPackageLPw(packageName); 3458 3459 if (pkg == null) { 3460 // should have found an update, but, we didn't; remove everything 3461 msg = "Updated system package " + packageName 3462 + " no longer exists; removing its data"; 3463 // Actual deletion of code and data will be handled by later 3464 // reconciliation step 3465 } else { 3466 // found an update; revoke system privileges 3467 msg = "Updated system package " + packageName 3468 + " no longer exists; rescanning package on data"; 3469 3470 // NOTE: We don't do anything special if a stub is removed from the 3471 // system image. But, if we were [like removing the uncompressed 3472 // version from the /data partition], this is where it'd be done. 3473 3474 // remove the package from the system and re-scan it without any 3475 // special privileges 3476 mRemovePackageHelper.removePackage(pkg, true); 3477 PackageSetting ps = mPm.mSettings.getPackageLPr(packageName); 3478 if (ps != null) { 3479 ps.getPkgState().setUpdatedSystemApp(false); 3480 } 3481 final File codePath = new File(pkg.getPath()); 3482 try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { 3483 initPackageTracedLI(codePath, 0, scanFlags); 3484 } catch (PackageManagerException e) { 3485 Slog.e(TAG, "Failed to parse updated, ex-system package: " 3486 + e.getMessage()); 3487 } 3488 } 3489 3490 // one final check. if we still have a package setting [ie. it was 3491 // previously scanned and known to the system], but, we don't have 3492 // a package [ie. there was an error scanning it from the /data 3493 // partition], completely remove the package data. 3494 final PackageSetting ps = mPm.mSettings.getPackageLPr(packageName); 3495 if (ps != null && mPm.mPackages.get(packageName) == null) { 3496 mRemovePackageHelper.removePackageData(ps, userIds); 3497 } 3498 logCriticalInfo(Log.WARN, msg); 3499 } 3500 } 3501 3502 /** 3503 * Scans APEX packages and registers them with the system. 3504 * 3505 * apexd has its own policy to decide which APEX to activate and which not. The policy might 3506 * conflicts that of PMS. The APEX package info stored in PMS is a mirror of that managed by 3507 * apexd. To keep things simple and keep activation status in sync for both apexd and PMS, we 3508 * don't persist APEX in settings and always scan APEX from scratch during boot. However, some 3509 * data like lastUpdateTime will be lost if PackageSetting is not persisted for APEX. 3510 * 3511 * TODO(b/225756739): Read lastUpdateTime from ApexInfoList to populate PackageSetting correctly 3512 */ 3513 @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) scanApexPackages(ApexInfo[] allPackages, int parseFlags, int scanFlags, PackageParser2 packageParser, ExecutorService executorService)3514 public List<ApexManager.ScanResult> scanApexPackages(ApexInfo[] allPackages, int parseFlags, 3515 int scanFlags, PackageParser2 packageParser, ExecutorService executorService) { 3516 if (allPackages == null) { 3517 return Collections.EMPTY_LIST; 3518 } 3519 3520 ParallelPackageParser parallelPackageParser = 3521 new ParallelPackageParser(packageParser, executorService); 3522 3523 // Submit files for parsing in parallel 3524 ArrayMap<File, ApexInfo> parsingApexInfo = new ArrayMap<>(); 3525 for (ApexInfo ai : allPackages) { 3526 File apexFile = new File(ai.modulePath); 3527 parallelPackageParser.submit(apexFile, parseFlags); 3528 parsingApexInfo.put(apexFile, ai); 3529 } 3530 3531 List<ParallelPackageParser.ParseResult> parseResults = 3532 new ArrayList<>(parsingApexInfo.size()); 3533 for (int i = 0; i < parsingApexInfo.size(); i++) { 3534 ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take(); 3535 parseResults.add(parseResult); 3536 } 3537 // Sort the list to ensure we always process factory packages first 3538 Collections.sort(parseResults, (a, b) -> { 3539 ApexInfo i1 = parsingApexInfo.get(a.scanFile); 3540 ApexInfo i2 = parsingApexInfo.get(b.scanFile); 3541 return Boolean.compare(i2.isFactory, i1.isFactory); 3542 }); 3543 3544 3545 // Process results one by one 3546 List<ApexManager.ScanResult> results = new ArrayList<>(parsingApexInfo.size()); 3547 for (int i = 0; i < parseResults.size(); i++) { 3548 ParallelPackageParser.ParseResult parseResult = parseResults.get(i); 3549 Throwable throwable = parseResult.throwable; 3550 ApexInfo ai = parsingApexInfo.get(parseResult.scanFile); 3551 int newParseFlags = parseFlags; 3552 int newScanFlags = scanFlags | SCAN_AS_APEX 3553 | mPm.getSystemPackageScanFlags(parseResult.scanFile); 3554 if (!ai.isFactory) { 3555 newParseFlags &= ~ParsingPackageUtils.PARSE_IS_SYSTEM_DIR; 3556 newScanFlags |= SCAN_NEW_INSTALL; 3557 } 3558 3559 if (throwable == null) { 3560 try { 3561 addForInitLI(parseResult.parsedPackage, newParseFlags, newScanFlags, null, 3562 new ApexManager.ActiveApexInfo(ai)); 3563 AndroidPackage pkg = parseResult.parsedPackage.hideAsFinal(); 3564 if (ai.isFactory && !ai.isActive) { 3565 disableSystemPackageLPw(pkg); 3566 } 3567 results.add(new ApexManager.ScanResult(ai, pkg, pkg.getPackageName())); 3568 } catch (PackageManagerException e) { 3569 throw new IllegalStateException("Failed to scan: " + ai.modulePath, e); 3570 } 3571 } else if (throwable instanceof PackageManagerException) { 3572 throw new IllegalStateException("Unable to parse: " + ai.modulePath, throwable); 3573 } else { 3574 throw new IllegalStateException("Unexpected exception occurred while parsing " 3575 + ai.modulePath, throwable); 3576 } 3577 } 3578 3579 return results; 3580 } 3581 3582 @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) installPackagesFromDir(File scanDir, int parseFlags, int scanFlags, PackageParser2 packageParser, ExecutorService executorService, @Nullable ApexManager.ActiveApexInfo apexInfo)3583 public void installPackagesFromDir(File scanDir, int parseFlags, 3584 int scanFlags, PackageParser2 packageParser, ExecutorService executorService, 3585 @Nullable ApexManager.ActiveApexInfo apexInfo) { 3586 final File[] files = scanDir.listFiles(); 3587 if (ArrayUtils.isEmpty(files)) { 3588 Log.d(TAG, "No files in app dir " + scanDir); 3589 return; 3590 } 3591 3592 if (DEBUG_PACKAGE_SCANNING) { 3593 Log.d(TAG, "Scanning app dir " + scanDir + " scanFlags=" + scanFlags 3594 + " flags=0x" + Integer.toHexString(parseFlags)); 3595 } 3596 ParallelPackageParser parallelPackageParser = 3597 new ParallelPackageParser(packageParser, executorService); 3598 3599 // Submit files for parsing in parallel 3600 int fileCount = 0; 3601 for (File file : files) { 3602 final boolean isPackage = (isApkFile(file) || file.isDirectory()) 3603 && !PackageInstallerService.isStageName(file.getName()); 3604 if (!isPackage) { 3605 // Ignore entries which are not packages 3606 continue; 3607 } 3608 if ((scanFlags & SCAN_DROP_CACHE) != 0) { 3609 final PackageCacher cacher = new PackageCacher(mPm.getCacheDir(), 3610 mPm.mPackageParserCallback); 3611 Log.w(TAG, "Dropping cache of " + file.getAbsolutePath()); 3612 cacher.cleanCachedResult(file); 3613 } 3614 parallelPackageParser.submit(file, parseFlags); 3615 fileCount++; 3616 } 3617 3618 // Process results one by one 3619 for (; fileCount > 0; fileCount--) { 3620 ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take(); 3621 Throwable throwable = parseResult.throwable; 3622 int errorCode = PackageManager.INSTALL_SUCCEEDED; 3623 String errorMsg = null; 3624 3625 if (throwable == null) { 3626 try { 3627 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "addForInitLI"); 3628 addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags, 3629 new UserHandle(UserHandle.USER_SYSTEM), apexInfo); 3630 } catch (PackageManagerException e) { 3631 errorCode = e.error; 3632 errorMsg = "Failed to scan " + parseResult.scanFile + ": " + e.getMessage(); 3633 Slog.w(TAG, errorMsg); 3634 } finally { 3635 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 3636 } 3637 } else if (throwable instanceof PackageManagerException) { 3638 PackageManagerException e = (PackageManagerException) throwable; 3639 errorCode = e.error; 3640 errorMsg = "Failed to parse " + parseResult.scanFile + ": " + e.getMessage(); 3641 Slog.w(TAG, errorMsg); 3642 } else { 3643 throw new IllegalStateException("Unexpected exception occurred while parsing " 3644 + parseResult.scanFile, throwable); 3645 } 3646 3647 if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0 && errorCode != INSTALL_SUCCEEDED) { 3648 mApexManager.reportErrorWithApkInApex(scanDir.getAbsolutePath(), errorMsg); 3649 } 3650 3651 // Delete invalid userdata apps 3652 if ((scanFlags & SCAN_AS_SYSTEM) == 0 3653 && errorCode != PackageManager.INSTALL_SUCCEEDED) { 3654 logCriticalInfo(Log.WARN, 3655 "Deleting invalid package at " + parseResult.scanFile); 3656 mRemovePackageHelper.removeCodePath(parseResult.scanFile); 3657 } 3658 } 3659 } 3660 3661 /** 3662 * Make sure all system apps that we expected to appear on 3663 * the userdata partition actually showed up. If they never 3664 * appeared, crawl back and revive the system version. 3665 */ 3666 @GuardedBy("mPm.mLock") checkExistingBetterPackages(ArrayMap<String, File> expectingBetterPackages, List<String> stubSystemApps, int systemScanFlags, int systemParseFlags)3667 public void checkExistingBetterPackages(ArrayMap<String, File> expectingBetterPackages, 3668 List<String> stubSystemApps, int systemScanFlags, int systemParseFlags) { 3669 for (int i = 0; i < expectingBetterPackages.size(); i++) { 3670 final String packageName = expectingBetterPackages.keyAt(i); 3671 if (mPm.mPackages.containsKey(packageName)) { 3672 continue; 3673 } 3674 final File scanFile = expectingBetterPackages.valueAt(i); 3675 3676 logCriticalInfo(Log.WARN, "Expected better " + packageName 3677 + " but never showed up; reverting to system"); 3678 3679 final Pair<Integer, Integer> rescanAndReparseFlags = 3680 mPm.getSystemPackageRescanFlagsAndReparseFlags(scanFile, 3681 systemScanFlags, systemParseFlags); 3682 @PackageManagerService.ScanFlags int rescanFlags = rescanAndReparseFlags.first; 3683 @ParsingPackageUtils.ParseFlags int reparseFlags = rescanAndReparseFlags.second; 3684 3685 if (rescanFlags == 0) { 3686 Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile); 3687 continue; 3688 } 3689 mPm.mSettings.enableSystemPackageLPw(packageName); 3690 3691 try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { 3692 final AndroidPackage newPkg = initPackageTracedLI( 3693 scanFile, reparseFlags, rescanFlags); 3694 // We rescanned a stub, add it to the list of stubbed system packages 3695 if (newPkg.isStub()) { 3696 stubSystemApps.add(packageName); 3697 } 3698 } catch (PackageManagerException e) { 3699 Slog.e(TAG, "Failed to parse original system package: " 3700 + e.getMessage()); 3701 } 3702 } 3703 } 3704 3705 /** 3706 * Traces a package scan and registers it with the system. 3707 * @see #initPackageLI(File, int, int) 3708 */ 3709 @GuardedBy("mPm.mInstallLock") initPackageTracedLI(File scanFile, final int parseFlags, int scanFlags)3710 public AndroidPackage initPackageTracedLI(File scanFile, final int parseFlags, int scanFlags) 3711 throws PackageManagerException { 3712 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage [" + scanFile.toString() + "]"); 3713 try { 3714 return initPackageLI(scanFile, parseFlags, scanFlags); 3715 } finally { 3716 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 3717 } 3718 } 3719 3720 /** 3721 * Scans a package, registers it with the system and returns the newly parsed package. 3722 * Returns {@code null} in case of errors and the error code is stored in mLastScanError 3723 */ 3724 @GuardedBy("mPm.mInstallLock") initPackageLI(File scanFile, int parseFlags, int scanFlags)3725 private AndroidPackage initPackageLI(File scanFile, int parseFlags, int scanFlags) 3726 throws PackageManagerException { 3727 if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile); 3728 3729 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage"); 3730 final ParsedPackage parsedPackage; 3731 try (PackageParser2 pp = mPm.mInjector.getScanningPackageParser()) { 3732 parsedPackage = pp.parsePackage(scanFile, parseFlags, false); 3733 } catch (PackageParserException e) { 3734 throw new PackageManagerException(e.error, e.getMessage(), e); 3735 } finally { 3736 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 3737 } 3738 3739 return addForInitLI(parsedPackage, parseFlags, scanFlags, 3740 new UserHandle(UserHandle.USER_SYSTEM), null); 3741 } 3742 3743 /** 3744 * Adds a new package to the internal data structures during platform initialization. 3745 * <p>After adding, the package is known to the system and available for querying. 3746 * <p>For packages located on the device ROM [eg. packages located in /system, /vendor, 3747 * etc...], additional checks are performed. Basic verification [such as ensuring 3748 * matching signatures, checking version codes, etc...] occurs if the package is 3749 * identical to a previously known package. If the package fails a signature check, 3750 * the version installed on /data will be removed. If the version of the new package 3751 * is less than or equal than the version on /data, it will be ignored. 3752 * <p>Regardless of the package location, the results are applied to the internal 3753 * structures and the package is made available to the rest of the system. 3754 * <p>NOTE: The return value should be removed. It's the passed in package object. 3755 */ 3756 @GuardedBy("mPm.mInstallLock") addForInitLI(ParsedPackage parsedPackage, @ParsingPackageUtils.ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags, @Nullable UserHandle user, @Nullable ApexManager.ActiveApexInfo activeApexInfo)3757 private AndroidPackage addForInitLI(ParsedPackage parsedPackage, 3758 @ParsingPackageUtils.ParseFlags int parseFlags, 3759 @PackageManagerService.ScanFlags int scanFlags, 3760 @Nullable UserHandle user, @Nullable ApexManager.ActiveApexInfo activeApexInfo) 3761 throws PackageManagerException { 3762 PackageSetting disabledPkgSetting; 3763 synchronized (mPm.mLock) { 3764 // Static shared libraries have synthetic package names 3765 if (activeApexInfo == null && parsedPackage.isStaticSharedLibrary()) { 3766 PackageManagerService.renameStaticSharedLibraryPackage(parsedPackage); 3767 } 3768 disabledPkgSetting = 3769 mPm.mSettings.getDisabledSystemPkgLPr(parsedPackage.getPackageName()); 3770 if (activeApexInfo != null && disabledPkgSetting != null) { 3771 // When a disabled system package is scanned, its final PackageSetting is actually 3772 // skipped and not added to any data structures, instead relying on the disabled 3773 // setting read from the persisted Settings XML file. This persistence does not 3774 // include the APEX module name, so here, re-set it from the active APEX info. 3775 // 3776 // This also has the (beneficial) side effect where if a package disappears from an 3777 // APEX, leaving only a /data copy, it will lose its apexModuleName. 3778 // 3779 // This must be done before scanSystemPackageLI as that will throw in the case of a 3780 // system -> data package. 3781 disabledPkgSetting.setApexModuleName(activeApexInfo.apexModuleName); 3782 } 3783 } 3784 3785 final Pair<ScanResult, Boolean> scanResultPair = scanSystemPackageLI( 3786 parsedPackage, parseFlags, scanFlags, user); 3787 final ScanResult scanResult = scanResultPair.first; 3788 boolean shouldHideSystemApp = scanResultPair.second; 3789 final InstallRequest installRequest = new InstallRequest( 3790 parsedPackage, parseFlags, scanFlags, user, scanResult, disabledPkgSetting); 3791 3792 String existingApexModuleName = null; 3793 synchronized (mPm.mLock) { 3794 var existingPkgSetting = mPm.mSettings.getPackageLPr(parsedPackage.getPackageName()); 3795 if (existingPkgSetting != null) { 3796 existingApexModuleName = existingPkgSetting.getApexModuleName(); 3797 } 3798 } 3799 3800 if (activeApexInfo != null) { 3801 installRequest.setApexModuleName(activeApexInfo.apexModuleName); 3802 } else { 3803 if (disabledPkgSetting != null) { 3804 installRequest.setApexModuleName(disabledPkgSetting.getApexModuleName()); 3805 } else if (existingApexModuleName != null) { 3806 installRequest.setApexModuleName(existingApexModuleName); 3807 } 3808 } 3809 3810 synchronized (mPm.mLock) { 3811 boolean appIdCreated = false; 3812 try { 3813 final String pkgName = scanResult.mPkgSetting.getPackageName(); 3814 final List<ReconciledPackage> reconcileResult = 3815 ReconcilePackageUtils.reconcilePackages( 3816 Collections.singletonList(installRequest), 3817 mPm.mPackages, Collections.singletonMap(pkgName, 3818 mPm.getSettingsVersionForPackage(parsedPackage)), 3819 mSharedLibraries, mPm.mSettings.getKeySetManagerService(), 3820 mPm.mSettings, mPm.mInjector.getSystemConfig()); 3821 if ((scanFlags & SCAN_AS_APEX) == 0) { 3822 appIdCreated = optimisticallyRegisterAppId(installRequest); 3823 } else { 3824 installRequest.setScannedPackageSettingAppId(Process.INVALID_UID); 3825 } 3826 commitReconciledScanResultLocked(reconcileResult.get(0), 3827 mPm.mUserManager.getUserIds()); 3828 } catch (PackageManagerException e) { 3829 if (appIdCreated) { 3830 cleanUpAppIdCreation(installRequest); 3831 } 3832 throw e; 3833 } 3834 } 3835 3836 if (shouldHideSystemApp) { 3837 synchronized (mPm.mLock) { 3838 mPm.mSettings.disableSystemPackageLPw(parsedPackage.getPackageName(), true); 3839 } 3840 } 3841 3842 if (mIncrementalManager != null && isIncrementalPath(parsedPackage.getPath())) { 3843 if (scanResult.mPkgSetting != null && scanResult.mPkgSetting.isLoading()) { 3844 // Continue monitoring loading progress of active incremental packages 3845 mIncrementalManager.registerLoadingProgressCallback(parsedPackage.getPath(), 3846 new IncrementalProgressListener(parsedPackage.getPackageName(), mPm)); 3847 } 3848 } 3849 3850 if (Flags.aslInApkAppMetadataSource() 3851 && scanResult.mPkgSetting.getAppMetadataSource() == APP_METADATA_SOURCE_APK) { 3852 if (!extractAppMetadataFromApk(parsedPackage, 3853 scanResult.mPkgSetting.getAppMetadataFilePath(), 3854 scanResult.mPkgSetting.isSystem())) { 3855 synchronized (mPm.mLock) { 3856 scanResult.mPkgSetting.setAppMetadataFilePath(null) 3857 .setAppMetadataSource(APP_METADATA_SOURCE_UNKNOWN); 3858 } 3859 } 3860 } 3861 return scanResult.mPkgSetting.getPkg(); 3862 } 3863 3864 /** 3865 * Prepares the system to commit a {@link ScanResult} in a way that will not fail by registering 3866 * the app ID required for reconcile. 3867 * @return {@code true} if a new app ID was registered and will need to be cleaned up on 3868 * failure. 3869 */ optimisticallyRegisterAppId(@onNull InstallRequest installRequest)3870 private boolean optimisticallyRegisterAppId(@NonNull InstallRequest installRequest) 3871 throws PackageManagerException { 3872 if (!installRequest.isExistingSettingCopied() || installRequest.needsNewAppId()) { 3873 synchronized (mPm.mLock) { 3874 // THROWS: when we can't allocate a user id. add call to check if there's 3875 // enough space to ensure we won't throw; otherwise, don't modify state 3876 return mPm.mSettings.registerAppIdLPw(installRequest.getScannedPackageSetting(), 3877 installRequest.needsNewAppId()); 3878 } 3879 } 3880 return false; 3881 } 3882 3883 /** 3884 * Reverts any app ID creation that were made by 3885 * {@link #optimisticallyRegisterAppId(InstallRequest)}. Note: this is only necessary if the 3886 * referenced method returned true. 3887 */ cleanUpAppIdCreation(@onNull InstallRequest installRequest)3888 private void cleanUpAppIdCreation(@NonNull InstallRequest installRequest) { 3889 // iff we've acquired an app ID for a new package setting, remove it so that it can be 3890 // acquired by another request. 3891 if (installRequest.getScannedPackageSetting() != null 3892 && installRequest.getScannedPackageSetting().getAppId() > 0) { 3893 synchronized (mPm.mLock) { 3894 mPm.mSettings.removeAppIdLPw(installRequest.getScannedPackageSetting().getAppId()); 3895 } 3896 } 3897 } 3898 3899 @GuardedBy("mPm.mInstallLock") scanPackageTracedLI(ParsedPackage parsedPackage, final @ParsingPackageUtils.ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags, long currentTime, @Nullable UserHandle user, String cpuAbiOverride)3900 private ScanResult scanPackageTracedLI(ParsedPackage parsedPackage, 3901 final @ParsingPackageUtils.ParseFlags int parseFlags, 3902 @PackageManagerService.ScanFlags int scanFlags, long currentTime, 3903 @Nullable UserHandle user, String cpuAbiOverride) throws PackageManagerException { 3904 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage"); 3905 try { 3906 return scanPackageNewLI(parsedPackage, parseFlags, scanFlags, currentTime, user, 3907 cpuAbiOverride); 3908 } finally { 3909 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 3910 } 3911 } 3912 prepareInitialScanRequest(@onNull ParsedPackage parsedPackage, @ParsingPackageUtils.ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags, @Nullable UserHandle user, String cpuAbiOverride)3913 private ScanRequest prepareInitialScanRequest(@NonNull ParsedPackage parsedPackage, 3914 @ParsingPackageUtils.ParseFlags int parseFlags, 3915 @PackageManagerService.ScanFlags int scanFlags, 3916 @Nullable UserHandle user, String cpuAbiOverride) 3917 throws PackageManagerException { 3918 final AndroidPackage platformPackage; 3919 final String realPkgName; 3920 final PackageSetting disabledPkgSetting; 3921 final PackageSetting installedPkgSetting; 3922 final PackageSetting originalPkgSetting; 3923 final SharedUserSetting sharedUserSetting; 3924 SharedUserSetting oldSharedUserSetting = null; 3925 3926 synchronized (mPm.mLock) { 3927 platformPackage = mPm.getPlatformPackage(); 3928 var isSystemApp = AndroidPackageLegacyUtils.isSystem(parsedPackage); 3929 final String renamedPkgName = mPm.mSettings.getRenamedPackageLPr( 3930 AndroidPackageUtils.getRealPackageOrNull(parsedPackage, isSystemApp)); 3931 realPkgName = ScanPackageUtils.getRealPackageName(parsedPackage, renamedPkgName, 3932 isSystemApp); 3933 if (realPkgName != null) { 3934 ScanPackageUtils.ensurePackageRenamed(parsedPackage, renamedPkgName); 3935 } 3936 originalPkgSetting = getOriginalPackageLocked(parsedPackage, renamedPkgName); 3937 installedPkgSetting = mPm.mSettings.getPackageLPr(parsedPackage.getPackageName()); 3938 if (mPm.mTransferredPackages.contains(parsedPackage.getPackageName())) { 3939 Slog.w(TAG, "Package " + parsedPackage.getPackageName() 3940 + " was transferred to another, but its .apk remains"); 3941 } 3942 disabledPkgSetting = mPm.mSettings.getDisabledSystemPkgLPr( 3943 parsedPackage.getPackageName()); 3944 3945 boolean ignoreSharedUserId = false; 3946 if (installedPkgSetting == null || !installedPkgSetting.hasSharedUser()) { 3947 // Directly ignore sharedUserSetting for new installs, or if the app has 3948 // already left shared UID 3949 ignoreSharedUserId = parsedPackage.isLeavingSharedUser(); 3950 } 3951 3952 if (!ignoreSharedUserId && parsedPackage.getSharedUserId() != null) { 3953 sharedUserSetting = mPm.mSettings.getSharedUserLPw( 3954 parsedPackage.getSharedUserId(), 3955 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, true /*create*/); 3956 } else { 3957 sharedUserSetting = null; 3958 } 3959 if (DEBUG_PACKAGE_SCANNING 3960 && (parseFlags & ParsingPackageUtils.PARSE_CHATTY) != 0 3961 && sharedUserSetting != null) { 3962 Log.d(TAG, "Shared UserID " + parsedPackage.getSharedUserId() 3963 + " (uid=" + sharedUserSetting.mAppId + "):" 3964 + " packages=" + sharedUserSetting.getPackageStates()); 3965 } 3966 if (installedPkgSetting != null) { 3967 oldSharedUserSetting = mPm.mSettings.getSharedUserSettingLPr(installedPkgSetting); 3968 } 3969 } 3970 3971 final boolean isPlatformPackage = platformPackage != null 3972 && platformPackage.getPackageName().equals(parsedPackage.getPackageName()); 3973 3974 return new ScanRequest(parsedPackage, oldSharedUserSetting, 3975 installedPkgSetting == null ? null : installedPkgSetting.getPkg() /* oldPkg */, 3976 installedPkgSetting /* packageSetting */, 3977 sharedUserSetting, 3978 disabledPkgSetting /* disabledPackageSetting */, 3979 originalPkgSetting /* originalPkgSetting */, 3980 realPkgName, parseFlags, scanFlags, isPlatformPackage, user, cpuAbiOverride); 3981 } 3982 3983 @GuardedBy("mPm.mInstallLock") scanPackageNewLI(@onNull ParsedPackage parsedPackage, final @ParsingPackageUtils.ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags, long currentTime, @Nullable UserHandle user, String cpuAbiOverride)3984 private ScanResult scanPackageNewLI(@NonNull ParsedPackage parsedPackage, 3985 final @ParsingPackageUtils.ParseFlags int parseFlags, 3986 @PackageManagerService.ScanFlags int scanFlags, long currentTime, 3987 @Nullable UserHandle user, String cpuAbiOverride) 3988 throws PackageManagerException { 3989 final ScanRequest initialScanRequest = prepareInitialScanRequest(parsedPackage, parseFlags, 3990 scanFlags, user, cpuAbiOverride); 3991 final PackageSetting installedPkgSetting = initialScanRequest.mPkgSetting; 3992 final PackageSetting disabledPkgSetting = initialScanRequest.mDisabledPkgSetting; 3993 3994 boolean isUpdatedSystemApp; 3995 if (installedPkgSetting != null) { 3996 isUpdatedSystemApp = installedPkgSetting.isUpdatedSystemApp(); 3997 } else { 3998 isUpdatedSystemApp = disabledPkgSetting != null; 3999 } 4000 4001 final int newScanFlags = adjustScanFlags(scanFlags, installedPkgSetting, disabledPkgSetting, 4002 user, parsedPackage); 4003 ScanPackageUtils.applyPolicy(parsedPackage, newScanFlags, 4004 mPm.getPlatformPackage(), isUpdatedSystemApp); 4005 4006 synchronized (mPm.mLock) { 4007 assertPackageIsValid(parsedPackage, parseFlags, newScanFlags); 4008 final ScanRequest request = new ScanRequest(parsedPackage, 4009 initialScanRequest.mOldSharedUserSetting, 4010 initialScanRequest.mOldPkg, installedPkgSetting, 4011 initialScanRequest.mSharedUserSetting, disabledPkgSetting, 4012 initialScanRequest.mOriginalPkgSetting, initialScanRequest.mRealPkgName, 4013 parseFlags, scanFlags, initialScanRequest.mIsPlatformPackage, user, 4014 cpuAbiOverride); 4015 return ScanPackageUtils.scanPackageOnlyLI(request, mPm.mInjector, mPm.mFactoryTest, 4016 currentTime); 4017 } 4018 } 4019 scanSystemPackageLI(ParsedPackage parsedPackage, @ParsingPackageUtils.ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags, @Nullable UserHandle user)4020 private Pair<ScanResult, Boolean> scanSystemPackageLI(ParsedPackage parsedPackage, 4021 @ParsingPackageUtils.ParseFlags int parseFlags, 4022 @PackageManagerService.ScanFlags int scanFlags, 4023 @Nullable UserHandle user) throws PackageManagerException { 4024 final boolean scanSystemPartition = 4025 (parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) != 0; 4026 final ScanRequest initialScanRequest = prepareInitialScanRequest(parsedPackage, parseFlags, 4027 scanFlags, user, null); 4028 final PackageSetting installedPkgSetting = initialScanRequest.mPkgSetting; 4029 final PackageSetting originalPkgSetting = initialScanRequest.mOriginalPkgSetting; 4030 final PackageSetting pkgSetting = 4031 originalPkgSetting == null ? installedPkgSetting : originalPkgSetting; 4032 final boolean pkgAlreadyExists = pkgSetting != null; 4033 final String disabledPkgName = pkgAlreadyExists 4034 ? pkgSetting.getPackageName() : parsedPackage.getPackageName(); 4035 final boolean isSystemPkgUpdated; 4036 final PackageSetting disabledPkgSetting; 4037 final boolean isUpgrade; 4038 synchronized (mPm.mLock) { 4039 isUpgrade = mPm.isDeviceUpgrading(); 4040 if (scanSystemPartition && !pkgAlreadyExists 4041 && mPm.mSettings.getDisabledSystemPkgLPr(disabledPkgName) != null) { 4042 // The updated-package data for /system apk remains inconsistently 4043 // after the package data for /data apk is lost accidentally. 4044 // To recover it, enable /system apk and install it as non-updated system app. 4045 Slog.w(TAG, "Inconsistent package setting of updated system app for " 4046 + disabledPkgName + ". To recover it, enable the system app " 4047 + "and install it as non-updated system app."); 4048 mPm.mSettings.removeDisabledSystemPackageLPw(disabledPkgName); 4049 } 4050 disabledPkgSetting = mPm.mSettings.getDisabledSystemPkgLPr(disabledPkgName); 4051 isSystemPkgUpdated = disabledPkgSetting != null; 4052 4053 if (DEBUG_INSTALL && isSystemPkgUpdated) { 4054 Slog.d(TAG, "updatedPkg = " + disabledPkgSetting); 4055 } 4056 4057 if (scanSystemPartition && isSystemPkgUpdated) { 4058 // we're updating the disabled package, so, scan it as the package setting 4059 final ScanRequest request = new ScanRequest(parsedPackage, 4060 mPm.mSettings.getSharedUserSettingLPr(disabledPkgSetting), 4061 null, disabledPkgSetting /* pkgSetting */, 4062 initialScanRequest.mSharedUserSetting, 4063 null /* disabledPkgSetting */, null /* originalPkgSetting */, 4064 null, parseFlags, scanFlags, 4065 initialScanRequest.mIsPlatformPackage, user, null); 4066 ScanPackageUtils.applyPolicy(parsedPackage, scanFlags, 4067 mPm.getPlatformPackage(), true); 4068 final ScanResult scanResult = 4069 ScanPackageUtils.scanPackageOnlyLI(request, mPm.mInjector, 4070 mPm.mFactoryTest, -1L); 4071 if (scanResult.mExistingSettingCopied 4072 && scanResult.mRequest.mPkgSetting != null) { 4073 scanResult.mRequest.mPkgSetting.updateFrom(scanResult.mPkgSetting); 4074 } 4075 } 4076 } // End of mLock 4077 4078 final boolean newPkgChangedPaths = pkgAlreadyExists 4079 && !pkgSetting.getPathString().equals(parsedPackage.getPath()); 4080 final boolean newPkgVersionGreater = pkgAlreadyExists 4081 && parsedPackage.getLongVersionCode() > pkgSetting.getVersionCode(); 4082 final boolean newSharedUserSetting = pkgAlreadyExists 4083 && (initialScanRequest.mOldSharedUserSetting 4084 != initialScanRequest.mSharedUserSetting); 4085 final boolean isSystemPkgBetter = scanSystemPartition && isSystemPkgUpdated 4086 && newPkgChangedPaths && (newPkgVersionGreater || newSharedUserSetting); 4087 if (isSystemPkgBetter) { 4088 // The version of the application on /system is greater than the version on 4089 // /data. Switch back to the application on /system. 4090 // It's safe to assume the application on /system will correctly scan. If not, 4091 // there won't be a working copy of the application. 4092 // Also, if the sharedUserSetting of the application on /system is different 4093 // from the sharedUserSetting on /data, switch back to the application on /system. 4094 // We should trust the sharedUserSetting on /system, even if the application 4095 // version on /system is smaller than the version on /data. 4096 synchronized (mPm.mLock) { 4097 // just remove the loaded entries from package lists 4098 mPm.mPackages.remove(pkgSetting.getPackageName()); 4099 } 4100 4101 logCriticalInfo(Log.WARN, 4102 "System package updated;" 4103 + " name: " + pkgSetting.getPackageName() 4104 + "; " + pkgSetting.getVersionCode() + " --> " 4105 + parsedPackage.getLongVersionCode() 4106 + "; " + pkgSetting.getPathString() 4107 + " --> " + parsedPackage.getPath()); 4108 4109 mRemovePackageHelper.cleanUpResources(pkgSetting.getPackageName(), 4110 new File(pkgSetting.getPathString()), 4111 getAppDexInstructionSets(pkgSetting.getPrimaryCpuAbiLegacy(), 4112 pkgSetting.getSecondaryCpuAbiLegacy())); 4113 synchronized (mPm.mLock) { 4114 mPm.mSettings.enableSystemPackageLPw(pkgSetting.getPackageName()); 4115 } 4116 } 4117 4118 // The version of the application on the /system partition is less than or 4119 // equal to the version on the /data partition. Throw an exception and use 4120 // the application already installed on the /data partition. 4121 if (scanSystemPartition && isSystemPkgUpdated && !isSystemPkgBetter) { 4122 // For some updated system packages, during addForInit we want to ensure the 4123 // PackageSetting has the correct SigningDetails compares to the original version on 4124 // the system partition. For the check to happen later during the /data scan, update 4125 // the disabled package setting per the original APK on a system partition so that it 4126 // can be trusted during reconcile. 4127 if (needSignatureMatchToSystem(parsedPackage.getPackageName())) { 4128 final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing(); 4129 final ParseResult<SigningDetails> result = 4130 ParsingPackageUtils.getSigningDetails(input, parsedPackage, 4131 false /*skipVerify*/); 4132 if (result.isError()) { 4133 throw new PrepareFailure("Failed collect during scanSystemPackageLI", 4134 result.getException()); 4135 } 4136 disabledPkgSetting.setSigningDetails(result.getResult()); 4137 } 4138 4139 // In the case of a skipped package, commitReconciledScanResultLocked is not called to 4140 // add the object to the "live" data structures, so this is the final mutation step 4141 // for the package. Which means it needs to be finalized here to cache derived fields. 4142 // This is relevant for cases where the disabled system package is used for flags or 4143 // other metadata. 4144 parsedPackage.hideAsFinal(); 4145 throw PackageManagerException.ofInternalError( 4146 "Package " + parsedPackage.getPackageName() 4147 + " at " + parsedPackage.getPath() + " ignored: updated version " 4148 + (pkgAlreadyExists ? String.valueOf(pkgSetting.getVersionCode()) : "unknown") 4149 + " better than this " + parsedPackage.getLongVersionCode(), 4150 PackageManagerException.INTERNAL_ERROR_UPDATED_VERSION_BETTER_THAN_SYSTEM); 4151 } 4152 4153 // Verify certificates against what was last scanned. Force re-collecting certificate in two 4154 // special cases: 4155 // 1) when scanning system, force re-collect only if system is upgrading. 4156 // 2) when scanning /data, force re-collect only if the package name is allowlisted. 4157 final boolean forceCollect = scanSystemPartition ? isUpgrade 4158 : pkgAlreadyExists && needSignatureMatchToSystem(pkgSetting.getPackageName()); 4159 if (DEBUG_VERIFY && forceCollect) { 4160 Slog.d(TAG, "Force collect certificate of " + parsedPackage.getPackageName()); 4161 } 4162 4163 // APK verification can be skipped during certificate collection, only if the file is in a 4164 // verified partition. 4165 final boolean skipVerify = scanSystemPartition; 4166 ScanPackageUtils.collectCertificatesLI(pkgSetting, parsedPackage, 4167 mPm.getSettingsVersionForPackage(parsedPackage), forceCollect, skipVerify, 4168 mPm.isPreNMR1Upgrade()); 4169 4170 // Reset profile if the application version is changed 4171 maybeClearProfilesForUpgradesLI(pkgSetting, parsedPackage); 4172 4173 /* 4174 * A new system app appeared, but we already had a non-system one of the 4175 * same name installed earlier. 4176 */ 4177 boolean shouldHideSystemApp = false; 4178 // A new application appeared on /system, but, we already have a copy of 4179 // the application installed on /data. 4180 if (scanSystemPartition && !isSystemPkgUpdated && pkgAlreadyExists 4181 && !pkgSetting.isSystem()) { 4182 4183 if (!parsedPackage.getSigningDetails() 4184 .checkCapability(pkgSetting.getSigningDetails(), 4185 SigningDetails.CertCapabilities.INSTALLED_DATA) 4186 && !pkgSetting.getSigningDetails().checkCapability( 4187 parsedPackage.getSigningDetails(), 4188 SigningDetails.CertCapabilities.ROLLBACK)) { 4189 logCriticalInfo(Log.WARN, 4190 "System package signature mismatch;" 4191 + " name: " + pkgSetting.getPackageName()); 4192 try (@SuppressWarnings("unused") PackageFreezer freezer = mPm.freezePackage( 4193 parsedPackage.getPackageName(), UserHandle.USER_ALL, 4194 "scanPackageInternalLI", ApplicationExitInfo.REASON_OTHER, 4195 null /* request */)) { 4196 mDeletePackageHelper.deletePackageLIF( 4197 parsedPackage.getPackageName(), null, true, 4198 mPm.mUserManager.getUserIds(), 0, new PackageRemovedInfo(), false); 4199 } 4200 } else if (newPkgVersionGreater || newSharedUserSetting) { 4201 // The application on /system is newer than the application on /data. 4202 // Simply remove the application on /data [keeping application data] 4203 // and replace it with the version on /system. 4204 // Also, if the sharedUserSetting of the application on /system is different 4205 // from the sharedUserSetting on data, we should trust the sharedUserSetting 4206 // on /system, even if the application version on /system is smaller than 4207 // the version on /data. 4208 logCriticalInfo(Log.WARN, 4209 "System package enabled;" 4210 + " name: " + pkgSetting.getPackageName() 4211 + "; " + pkgSetting.getVersionCode() + " --> " 4212 + parsedPackage.getLongVersionCode() 4213 + "; " + pkgSetting.getPathString() + " --> " 4214 + parsedPackage.getPath()); 4215 mRemovePackageHelper.cleanUpResources(pkgSetting.getPackageName(), 4216 new File(pkgSetting.getPathString()), 4217 getAppDexInstructionSets( 4218 pkgSetting.getPrimaryCpuAbiLegacy(), pkgSetting.getSecondaryCpuAbiLegacy())); 4219 } else { 4220 // The application on /system is older than the application on /data. Hide 4221 // the application on /system and the version on /data will be scanned later 4222 // and re-added like an update. 4223 shouldHideSystemApp = true; 4224 logCriticalInfo(Log.INFO, 4225 "System package disabled;" 4226 + " name: " + pkgSetting.getPackageName() 4227 + "; old: " + pkgSetting.getPathString() + " @ " 4228 + pkgSetting.getVersionCode() 4229 + "; new: " + parsedPackage.getPath() + " @ " 4230 + parsedPackage.getLongVersionCode()); 4231 } 4232 } 4233 4234 // A new application appeared on /system, and we are seeing it for the first time. 4235 // Its also not updated as we don't have a copy of it on /data. So, scan it in a 4236 // STOPPED state. 4237 // We'll skip this step under the following conditions: 4238 // - It's "android" 4239 // - It's an APEX or overlay package since stopped state does not affect them. 4240 // - It is enumerated with a <initial-package-state> tag having the stopped attribute 4241 // set to false 4242 // - It doesn't have an enabled and exported launcher activity, which means the user 4243 // wouldn't have a way to un-stop it 4244 final boolean isApexPkg = (scanFlags & SCAN_AS_APEX) != 0; 4245 if (mPm.mShouldStopSystemPackagesByDefault 4246 && scanSystemPartition 4247 && !pkgAlreadyExists 4248 && !isApexPkg 4249 && !parsedPackage.isOverlayIsStatic() 4250 ) { 4251 String packageName = parsedPackage.getPackageName(); 4252 if (!"android".contentEquals(packageName) 4253 && !mPm.mInitialNonStoppedSystemPackages.contains(packageName) 4254 && hasLauncherEntry(parsedPackage)) { 4255 scanFlags |= SCAN_AS_STOPPED_SYSTEM_APP; 4256 } 4257 } 4258 4259 final long firstInstallTime = Flags.fixSystemAppsFirstInstallTime() 4260 ? System.currentTimeMillis() : 0; 4261 final ScanResult scanResult = scanPackageNewLI(parsedPackage, parseFlags, 4262 scanFlags | SCAN_UPDATE_SIGNATURE, firstInstallTime, user, null); 4263 return new Pair<>(scanResult, shouldHideSystemApp); 4264 } 4265 hasLauncherEntry(ParsedPackage parsedPackage)4266 private static boolean hasLauncherEntry(ParsedPackage parsedPackage) { 4267 final HashSet<String> categories = new HashSet<>(); 4268 categories.add(Intent.CATEGORY_LAUNCHER); 4269 final List<ParsedActivity> activities = parsedPackage.getActivities(); 4270 for (int indexActivity = 0; indexActivity < activities.size(); indexActivity++) { 4271 final ParsedActivity activity = activities.get(indexActivity); 4272 if (!activity.isEnabled() || !activity.isExported()) { 4273 continue; 4274 } 4275 final List<ParsedIntentInfo> intents = activity.getIntents(); 4276 for (int indexIntent = 0; indexIntent < intents.size(); indexIntent++) { 4277 final IntentFilter intentFilter = intents.get(indexIntent).getIntentFilter(); 4278 if (intentFilter != null && intentFilter.matchCategories(categories) == null) { 4279 return true; 4280 } 4281 } 4282 } 4283 return false; 4284 } 4285 4286 /** 4287 * Returns whether the package needs a signature verification against the pre-installed version 4288 * at boot. 4289 */ needSignatureMatchToSystem(String packageName)4290 private boolean needSignatureMatchToSystem(String packageName) { 4291 if (!android.security.Flags.extendVbChainToUpdatedApk()) { 4292 return false; 4293 } 4294 return mPm.mInjector.getSystemConfig().getPreinstallPackagesWithStrictSignatureCheck() 4295 .contains(packageName); 4296 } 4297 4298 /** 4299 * Clear the package profile if this was an upgrade and the package 4300 * version was updated. 4301 */ maybeClearProfilesForUpgradesLI( @ullable PackageSetting originalPkgSetting, @NonNull AndroidPackage pkg)4302 private void maybeClearProfilesForUpgradesLI( 4303 @Nullable PackageSetting originalPkgSetting, 4304 @NonNull AndroidPackage pkg) { 4305 if (originalPkgSetting == null || !mPm.isDeviceUpgrading()) { 4306 return; 4307 } 4308 if (originalPkgSetting.getVersionCode() == pkg.getLongVersionCode()) { 4309 return; 4310 } 4311 4312 mAppDataHelper.clearAppProfilesLIF(pkg); 4313 if (DEBUG_INSTALL) { 4314 Slog.d(TAG, originalPkgSetting.getPackageName() 4315 + " clear profile due to version change " 4316 + originalPkgSetting.getVersionCode() + " != " 4317 + pkg.getLongVersionCode()); 4318 } 4319 } 4320 4321 /** 4322 * Returns the original package setting. 4323 * <p>A package can migrate its name during an update. In this scenario, a package 4324 * designates a set of names that it considers as one of its original names. 4325 * <p>An original package must be signed identically and it must have the same 4326 * shared user [if any]. 4327 */ 4328 @GuardedBy("mPm.mLock") 4329 @Nullable getOriginalPackageLocked(@onNull AndroidPackage pkg, @Nullable String renamedPkgName)4330 private PackageSetting getOriginalPackageLocked(@NonNull AndroidPackage pkg, 4331 @Nullable String renamedPkgName) { 4332 if (ScanPackageUtils.isPackageRenamed(pkg, renamedPkgName)) { 4333 return null; 4334 } 4335 for (int i = ArrayUtils.size(pkg.getOriginalPackages()) - 1; i >= 0; --i) { 4336 final PackageSetting originalPs = 4337 mPm.mSettings.getPackageLPr(pkg.getOriginalPackages().get(i)); 4338 if (originalPs != null) { 4339 // the package is already installed under its original name... 4340 // but, should we use it? 4341 if (!verifyPackageUpdateLPr(originalPs, pkg)) { 4342 // the new package is incompatible with the original 4343 continue; 4344 } else if (mPm.mSettings.getSharedUserSettingLPr(originalPs) != null) { 4345 final String sharedUserSettingsName = 4346 mPm.mSettings.getSharedUserSettingLPr(originalPs).name; 4347 if (!sharedUserSettingsName.equals(pkg.getSharedUserId())) { 4348 // the shared user id is incompatible with the original 4349 Slog.w(TAG, "Unable to migrate data from " + originalPs.getPackageName() 4350 + " to " + pkg.getPackageName() + ": old shared user settings name " 4351 + sharedUserSettingsName 4352 + " differs from " + pkg.getSharedUserId()); 4353 continue; 4354 } 4355 // TODO: Add case when shared user id is added [b/28144775] 4356 } else { 4357 if (DEBUG_UPGRADE) { 4358 Log.v(TAG, "Renaming new package " 4359 + pkg.getPackageName() + " to old name " 4360 + originalPs.getPackageName()); 4361 } 4362 } 4363 return originalPs; 4364 } 4365 } 4366 return null; 4367 } 4368 4369 @GuardedBy("mPm.mLock") verifyPackageUpdateLPr(PackageSetting oldPkg, AndroidPackage newPkg)4370 private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, AndroidPackage newPkg) { 4371 if ((oldPkg.getFlags() & ApplicationInfo.FLAG_SYSTEM) == 0) { 4372 Slog.w(TAG, "Unable to update from " + oldPkg.getPackageName() 4373 + " to " + newPkg.getPackageName() 4374 + ": old package not in system partition"); 4375 return false; 4376 } else if (mPm.mPackages.get(oldPkg.getPackageName()) != null) { 4377 Slog.w(TAG, "Unable to update from " + oldPkg.getPackageName() 4378 + " to " + newPkg.getPackageName() 4379 + ": old package still exists"); 4380 return false; 4381 } 4382 return true; 4383 } 4384 4385 /** 4386 * Asserts the parsed package is valid according to the given policy. If the 4387 * package is invalid, for whatever reason, throws {@link PackageManagerException}. 4388 * <p> 4389 * Implementation detail: This method must NOT have any side effects. It would 4390 * ideally be static, but, it requires locks to read system state. 4391 * 4392 * @throws PackageManagerException If the package fails any of the validation checks 4393 */ assertPackageIsValid(AndroidPackage pkg, final @ParsingPackageUtils.ParseFlags int parseFlags, final @PackageManagerService.ScanFlags int scanFlags)4394 private void assertPackageIsValid(AndroidPackage pkg, 4395 final @ParsingPackageUtils.ParseFlags int parseFlags, 4396 final @PackageManagerService.ScanFlags int scanFlags) 4397 throws PackageManagerException { 4398 if ((parseFlags & ParsingPackageUtils.PARSE_ENFORCE_CODE) != 0) { 4399 ScanPackageUtils.assertCodePolicy(pkg); 4400 } 4401 4402 if (pkg.getPath() == null) { 4403 // Bail out. The resource and code paths haven't been set. 4404 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 4405 "Code and resource paths haven't been set correctly"); 4406 } 4407 4408 // Check that there is an APEX package with the same name only during install/first boot 4409 // after OTA. 4410 final boolean isUserInstall = (scanFlags & SCAN_BOOTING) == 0; 4411 final boolean isFirstBootOrUpgrade = (scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0; 4412 // It is allowed to install a new APEX with the same name. But there shouldn't be 4413 // conflicting names between APK and APEX. 4414 final boolean installApex = (scanFlags & SCAN_AS_APEX) != 0; 4415 if ((isUserInstall || isFirstBootOrUpgrade) 4416 && mPm.snapshotComputer().isApexPackage(pkg.getPackageName()) 4417 && !installApex) { 4418 throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE, 4419 pkg.getPackageName() 4420 + " is an APEX package and can't be installed as an APK."); 4421 } 4422 4423 // Make sure we're not adding any bogus keyset info 4424 final KeySetManagerService ksms = mPm.mSettings.getKeySetManagerService(); 4425 ksms.assertScannedPackageValid(pkg); 4426 4427 synchronized (mPm.mLock) { 4428 // The special "android" package can only be defined once 4429 if (pkg.getPackageName().equals("android")) { 4430 if (mPm.getCoreAndroidApplication() != null) { 4431 Slog.w(TAG, "*************************************************"); 4432 Slog.w(TAG, "Core android package being redefined. Skipping."); 4433 Slog.w(TAG, " codePath=" + pkg.getPath()); 4434 Slog.w(TAG, "*************************************************"); 4435 throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE, 4436 "Core android package being redefined. Skipping."); 4437 } 4438 } 4439 4440 // A package name must be unique; don't allow duplicates 4441 if ((scanFlags & SCAN_NEW_INSTALL) == 0 4442 && mPm.mPackages.containsKey(pkg.getPackageName())) { 4443 throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE, 4444 "Application package " + pkg.getPackageName() 4445 + " already installed. Skipping duplicate."); 4446 } 4447 4448 if (pkg.isStaticSharedLibrary()) { 4449 // Static libs have a synthetic package name containing the version 4450 // but we still want the base name to be unique. 4451 if ((scanFlags & SCAN_NEW_INSTALL) == 0 4452 && mPm.mPackages.containsKey(pkg.getManifestPackageName())) { 4453 throw PackageManagerException.ofInternalError( 4454 "Duplicate static shared lib provider package", 4455 PackageManagerException.INTERNAL_ERROR_DUP_STATIC_SHARED_LIB_PROVIDER); 4456 } 4457 ScanPackageUtils.assertStaticSharedLibraryIsValid(pkg, scanFlags); 4458 assertStaticSharedLibraryVersionCodeIsValid(pkg); 4459 } 4460 4461 // If we're only installing presumed-existing packages, require that the 4462 // scanned APK is both already known and at the path previously established 4463 // for it. Previously unknown packages we pick up normally, but if we have an 4464 // a priori expectation about this package's install presence, enforce it. 4465 // With a singular exception for new system packages. When an OTA contains 4466 // a new system package, we allow the codepath to change from a system location 4467 // to the user-installed location. If we don't allow this change, any newer, 4468 // user-installed version of the application will be ignored. 4469 if ((scanFlags & SCAN_REQUIRE_KNOWN) != 0) { 4470 if (mPm.isExpectingBetter(pkg.getPackageName())) { 4471 Slog.w(TAG, "Relax SCAN_REQUIRE_KNOWN requirement for package " 4472 + pkg.getPackageName()); 4473 } else { 4474 PackageSetting known = mPm.mSettings.getPackageLPr(pkg.getPackageName()); 4475 if (known != null) { 4476 if (DEBUG_PACKAGE_SCANNING) { 4477 Log.d(TAG, "Examining " + pkg.getPath() 4478 + " and requiring known path " + known.getPathString()); 4479 } 4480 if (!pkg.getPath().equals(known.getPathString())) { 4481 throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED, 4482 "Application package " + pkg.getPackageName() 4483 + " found at " + pkg.getPath() 4484 + " but expected at " + known.getPathString() 4485 + "; ignoring."); 4486 } 4487 } else { 4488 throw new PackageManagerException(INSTALL_FAILED_INVALID_INSTALL_LOCATION, 4489 "Application package " + pkg.getPackageName() 4490 + " not found; ignoring."); 4491 } 4492 } 4493 } 4494 4495 // Verify that this new package doesn't have any content providers 4496 // that conflict with existing packages. Only do this if the 4497 // package isn't already installed, since we don't want to break 4498 // things that are installed. 4499 if ((scanFlags & SCAN_NEW_INSTALL) != 0) { 4500 mPm.mComponentResolver.assertProvidersNotDefined(pkg); 4501 } 4502 4503 // If this package has defined explicit processes, then ensure that these are 4504 // the only processes used by its components. 4505 ScanPackageUtils.assertProcessesAreValid(pkg); 4506 4507 // Verify that packages sharing a user with a privileged app are marked as privileged. 4508 assertPackageWithSharedUserIdIsPrivileged(pkg); 4509 4510 // Apply policies specific for runtime resource overlays (RROs). 4511 if (pkg.getOverlayTarget() != null) { 4512 assertOverlayIsValid(pkg, parseFlags, scanFlags); 4513 } 4514 4515 // Ensure the package is signed with at least the minimum signature scheme version 4516 // required for its target SDK. 4517 ScanPackageUtils.assertMinSignatureSchemeIsValid(pkg, parseFlags); 4518 } 4519 } 4520 assertStaticSharedLibraryVersionCodeIsValid(AndroidPackage pkg)4521 private void assertStaticSharedLibraryVersionCodeIsValid(AndroidPackage pkg) 4522 throws PackageManagerException { 4523 // The version codes must be ordered as lib versions 4524 long minVersionCode = Long.MIN_VALUE; 4525 long maxVersionCode = Long.MAX_VALUE; 4526 4527 WatchedLongSparseArray<SharedLibraryInfo> versionedLib = 4528 mSharedLibraries.getSharedLibraryInfos(pkg.getStaticSharedLibraryName()); 4529 if (versionedLib != null) { 4530 final int versionCount = versionedLib.size(); 4531 for (int i = 0; i < versionCount; i++) { 4532 SharedLibraryInfo libInfo = versionedLib.valueAt(i); 4533 final long libVersionCode = libInfo.getDeclaringPackage() 4534 .getLongVersionCode(); 4535 if (libInfo.getLongVersion() < pkg.getStaticSharedLibraryVersion()) { 4536 minVersionCode = Math.max(minVersionCode, libVersionCode + 1); 4537 } else if (libInfo.getLongVersion() 4538 > pkg.getStaticSharedLibraryVersion()) { 4539 maxVersionCode = Math.min(maxVersionCode, libVersionCode - 1); 4540 } else { 4541 minVersionCode = maxVersionCode = libVersionCode; 4542 break; 4543 } 4544 } 4545 } 4546 if (pkg.getLongVersionCode() < minVersionCode 4547 || pkg.getLongVersionCode() > maxVersionCode) { 4548 throw PackageManagerException.ofInternalError("Static shared" 4549 + " lib version codes must be ordered as lib versions", 4550 PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_VERSION_CODES_ORDER); 4551 } 4552 } 4553 assertOverlayIsValid(AndroidPackage pkg, @ParsingPackageUtils.ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags)4554 private void assertOverlayIsValid(AndroidPackage pkg, 4555 @ParsingPackageUtils.ParseFlags int parseFlags, 4556 @PackageManagerService.ScanFlags int scanFlags) throws PackageManagerException { 4557 // System overlays have some restrictions on their use of the 'static' state. 4558 if ((scanFlags & SCAN_AS_SYSTEM) != 0) { 4559 // We are scanning a system overlay. This can be the first scan of the 4560 // system/vendor/oem partition, or an update to the system overlay. 4561 if ((parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) == 0) { 4562 // This must be an update to a system overlay. Immutable overlays cannot be 4563 // upgraded. 4564 if (!mPm.isOverlayMutable(pkg.getPackageName())) { 4565 throw PackageManagerException.ofInternalError("Overlay " 4566 + pkg.getPackageName() 4567 + " is static and cannot be upgraded.", 4568 PackageManagerException.INTERNAL_ERROR_SYSTEM_OVERLAY_STATIC); 4569 } 4570 } else { 4571 if ((scanFlags & SCAN_AS_VENDOR) != 0) { 4572 if (pkg.getTargetSdkVersion() < ScanPackageUtils.getVendorPartitionVersion()) { 4573 Slog.w(TAG, "System overlay " + pkg.getPackageName() 4574 + " targets an SDK below the required SDK level of vendor" 4575 + " overlays (" 4576 + ScanPackageUtils.getVendorPartitionVersion() 4577 + ")." 4578 + " This will become an install error in a future release"); 4579 } 4580 } else if (pkg.getTargetSdkVersion() < Build.VERSION.SDK_INT) { 4581 Slog.w(TAG, "System overlay " + pkg.getPackageName() 4582 + " targets an SDK below the required SDK level of system" 4583 + " overlays (" + Build.VERSION.SDK_INT + ")." 4584 + " This will become an install error in a future release"); 4585 } 4586 } 4587 } else { 4588 // A non-preloaded overlay packages must have targetSdkVersion >= Q, or be 4589 // signed with the platform certificate. Check this in increasing order of 4590 // computational cost. 4591 if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.Q) { 4592 final PackageSetting platformPkgSetting; 4593 synchronized (mPm.mLock) { 4594 platformPkgSetting = mPm.mSettings.getPackageLPr("android"); 4595 } 4596 if (!comparePackageSignatures(platformPkgSetting, pkg.getSigningDetails())) { 4597 throw PackageManagerException.ofInternalError("Overlay " 4598 + pkg.getPackageName() 4599 + " must target Q or later, " 4600 + "or be signed with the platform certificate", 4601 PackageManagerException.INTERNAL_ERROR_OVERLAY_LOW_TARGET_SDK); 4602 } 4603 } 4604 4605 // A non-preloaded overlay package, without <overlay android:targetName>, will 4606 // only be used if it is signed with the same certificate as its target OR if 4607 // it is signed with the same certificate as a reference package declared 4608 // in 'overlay-config-signature' tag of SystemConfig. 4609 // If the target is already installed or 'overlay-config-signature' tag in 4610 // SystemConfig is set, check this here to augment the last line of defense 4611 // which is OMS. 4612 if (pkg.getOverlayTargetOverlayableName() == null) { 4613 final PackageSetting targetPkgSetting; 4614 synchronized (mPm.mLock) { 4615 targetPkgSetting = mPm.mSettings.getPackageLPr(pkg.getOverlayTarget()); 4616 } 4617 if (targetPkgSetting != null) { 4618 if (!comparePackageSignatures(targetPkgSetting, pkg.getSigningDetails())) { 4619 // check reference signature 4620 if (mPm.mOverlayConfigSignaturePackage == null) { 4621 throw PackageManagerException.ofInternalError("Overlay " 4622 + pkg.getPackageName() + " and target " 4623 + pkg.getOverlayTarget() + " signed with" 4624 + " different certificates, and the overlay lacks" 4625 + " <overlay android:targetName>", 4626 PackageManagerException.INTERNAL_ERROR_OVERLAY_SIGNATURE1); 4627 } 4628 final PackageSetting refPkgSetting; 4629 synchronized (mPm.mLock) { 4630 refPkgSetting = mPm.mSettings.getPackageLPr( 4631 mPm.mOverlayConfigSignaturePackage); 4632 } 4633 if (!comparePackageSignatures(refPkgSetting, pkg.getSigningDetails())) { 4634 throw PackageManagerException.ofInternalError("Overlay " 4635 + pkg.getPackageName() + " signed with a different " 4636 + "certificate than both the reference package and " 4637 + "target " + pkg.getOverlayTarget() + ", and the " 4638 + "overlay lacks <overlay android:targetName>", 4639 PackageManagerException.INTERNAL_ERROR_OVERLAY_SIGNATURE2); 4640 } 4641 } 4642 } 4643 } 4644 } 4645 } 4646 assertPackageWithSharedUserIdIsPrivileged(AndroidPackage pkg)4647 private void assertPackageWithSharedUserIdIsPrivileged(AndroidPackage pkg) 4648 throws PackageManagerException { 4649 if (!AndroidPackageLegacyUtils.isPrivileged(pkg) 4650 && (pkg.getSharedUserId() != null) 4651 && !pkg.isLeavingSharedUser()) { 4652 SharedUserSetting sharedUserSetting = null; 4653 try { 4654 synchronized (mPm.mLock) { 4655 sharedUserSetting = mPm.mSettings.getSharedUserLPw(pkg.getSharedUserId(), 4656 0, 0, false); 4657 } 4658 } catch (PackageManagerException ignore) { 4659 } 4660 if (sharedUserSetting != null && sharedUserSetting.isPrivileged()) { 4661 // Exempt SharedUsers signed with the platform key. 4662 final PackageSetting platformPkgSetting; 4663 synchronized (mPm.mLock) { 4664 platformPkgSetting = mPm.mSettings.getPackageLPr("android"); 4665 } 4666 if (!comparePackageSignatures(platformPkgSetting, pkg.getSigningDetails())) { 4667 throw PackageManagerException.ofInternalError("Apps that share a user with a " 4668 + "privileged app must themselves be marked as privileged. " 4669 + pkg.getPackageName() + " shares privileged user " 4670 + pkg.getSharedUserId() + ".", 4671 PackageManagerException.INTERNAL_ERROR_NOT_PRIV_SHARED_USER); 4672 } 4673 } 4674 } 4675 } 4676 adjustScanFlags( @ackageManagerService.ScanFlags int scanFlags, @Nullable PackageSetting existingPkgSetting, @Nullable PackageSetting disabledPkgSetting, UserHandle user, @NonNull AndroidPackage pkg)4677 private @PackageManagerService.ScanFlags int adjustScanFlags( 4678 @PackageManagerService.ScanFlags int scanFlags, 4679 @Nullable PackageSetting existingPkgSetting, 4680 @Nullable PackageSetting disabledPkgSetting, UserHandle user, 4681 @NonNull AndroidPackage pkg) { 4682 scanFlags = ScanPackageUtils.adjustScanFlagsWithPackageSetting(scanFlags, existingPkgSetting, 4683 disabledPkgSetting, user); 4684 4685 // Exception for privileged apps that share a user with a priv-app. 4686 final boolean skipVendorPrivilegeScan = ((scanFlags & SCAN_AS_VENDOR) != 0) 4687 && ScanPackageUtils.getVendorPartitionVersion() < 28; 4688 if (((scanFlags & SCAN_AS_PRIVILEGED) == 0) 4689 && !AndroidPackageLegacyUtils.isPrivileged(pkg) 4690 && (pkg.getSharedUserId() != null) 4691 && !skipVendorPrivilegeScan 4692 && !pkg.isLeavingSharedUser()) { 4693 SharedUserSetting sharedUserSetting = null; 4694 synchronized (mPm.mLock) { 4695 try { 4696 sharedUserSetting = mPm.mSettings.getSharedUserLPw(pkg.getSharedUserId(), 0, 4697 0, false); 4698 } catch (PackageManagerException ignore) { 4699 } 4700 if (sharedUserSetting != null && sharedUserSetting.isPrivileged()) { 4701 // Exempt SharedUsers signed with the platform key. 4702 // TODO(b/72378145) Fix this exemption. Force signature apps 4703 // to allowlist their privileged permissions just like other 4704 // priv-apps. 4705 PackageSetting platformPkgSetting = mPm.mSettings.getPackageLPr("android"); 4706 if ((compareSignatures(platformPkgSetting.getSigningDetails(), 4707 pkg.getSigningDetails()) != PackageManager.SIGNATURE_MATCH)) { 4708 scanFlags |= SCAN_AS_PRIVILEGED; 4709 } 4710 } 4711 } 4712 } 4713 4714 return scanFlags; 4715 } 4716 } 4717