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