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