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.os.Trace.TRACE_TAG_PACKAGE_MANAGER; 20 21 import static com.android.server.pm.PackageManagerService.TAG; 22 import static com.android.server.pm.PackageManagerServiceUtils.getPackageManagerLocal; 23 import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo; 24 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 27 import android.annotation.UserIdInt; 28 import android.content.pm.PackageManager; 29 import android.content.pm.UserInfo; 30 import android.os.CreateAppDataArgs; 31 import android.os.Environment; 32 import android.os.FileUtils; 33 import android.os.Process; 34 import android.os.Trace; 35 import android.os.UserHandle; 36 import android.os.storage.StorageManager; 37 import android.os.storage.StorageManagerInternal; 38 import android.os.storage.VolumeInfo; 39 import android.security.AndroidKeyStoreMaintenance; 40 import android.system.keystore2.Domain; 41 import android.text.TextUtils; 42 import android.util.Log; 43 import android.util.Slog; 44 import android.util.TimingsTraceLog; 45 46 import com.android.internal.annotations.GuardedBy; 47 import com.android.internal.util.Preconditions; 48 import com.android.server.SystemServerInitThreadPool; 49 import com.android.server.pm.Installer.LegacyDexoptDisabledException; 50 import com.android.server.pm.dex.ArtManagerService; 51 import com.android.server.pm.parsing.pkg.AndroidPackageUtils; 52 import com.android.server.pm.pkg.AndroidPackage; 53 import com.android.server.pm.pkg.PackageState; 54 import com.android.server.pm.pkg.PackageStateInternal; 55 import com.android.server.pm.pkg.SELinuxUtil; 56 57 import dalvik.system.VMRuntime; 58 59 import java.io.File; 60 import java.util.ArrayList; 61 import java.util.List; 62 import java.util.concurrent.CompletableFuture; 63 import java.util.concurrent.Future; 64 65 /** 66 * Prepares app data for users 67 */ 68 public class AppDataHelper { 69 private static final boolean DEBUG_APP_DATA = false; 70 71 private final PackageManagerService mPm; 72 private final Installer mInstaller; 73 private final ArtManagerService mArtManagerService; 74 private final PackageManagerServiceInjector mInjector; 75 76 // TODO(b/198166813): remove PMS dependency AppDataHelper(PackageManagerService pm)77 AppDataHelper(PackageManagerService pm) { 78 mPm = pm; 79 mInjector = mPm.mInjector; 80 mInstaller = mInjector.getInstaller(); 81 mArtManagerService = mInjector.getArtManagerService(); 82 } 83 84 /** 85 * Prepare app data for the given app just after it was installed or 86 * upgraded. This method carefully only touches users that it's installed 87 * for, and it forces a restorecon to handle any seinfo changes. 88 * <p> 89 * Verifies that directories exist and that ownership and labeling is 90 * correct for all installed apps. If there is an ownership mismatch, it 91 * will wipe and recreate the data. 92 * <p> 93 * <em>Note: To avoid a deadlock, do not call this method with {@code mLock} lock held</em> 94 */ 95 @GuardedBy("mPm.mInstallLock") prepareAppDataAfterInstallLIF(AndroidPackage pkg)96 public void prepareAppDataAfterInstallLIF(AndroidPackage pkg) { 97 prepareAppDataPostCommitLIF(pkg, 0 /* previousAppId */); 98 } 99 100 /** 101 * For more details about data verification and previousAppId, check 102 * {@link #prepareAppData(Installer.Batch, AndroidPackage, int, int, int)} 103 * @see #prepareAppDataAfterInstallLIF(AndroidPackage) 104 */ 105 @GuardedBy("mPm.mInstallLock") prepareAppDataPostCommitLIF(AndroidPackage pkg, int previousAppId)106 public void prepareAppDataPostCommitLIF(AndroidPackage pkg, int previousAppId) { 107 final PackageSetting ps; 108 synchronized (mPm.mLock) { 109 ps = mPm.mSettings.getPackageLPr(pkg.getPackageName()); 110 mPm.mSettings.writeKernelMappingLPr(ps); 111 } 112 113 // TODO(b/211761016): should we still create the profile dirs? 114 if (!shouldHaveAppStorage(pkg)) { 115 Slog.w(TAG, "Skipping preparing app data for " + pkg.getPackageName()); 116 return; 117 } 118 119 Installer.Batch batch = new Installer.Batch(); 120 UserManagerInternal umInternal = mInjector.getUserManagerInternal(); 121 StorageManagerInternal smInternal = mInjector.getLocalService( 122 StorageManagerInternal.class); 123 for (UserInfo user : umInternal.getUsers(false /*excludeDying*/)) { 124 final int flags; 125 if (StorageManager.isUserKeyUnlocked(user.id) 126 && smInternal.isCeStoragePrepared(user.id)) { 127 flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE; 128 } else if (umInternal.isUserRunning(user.id)) { 129 flags = StorageManager.FLAG_STORAGE_DE; 130 } else { 131 continue; 132 } 133 134 if (ps.getInstalled(user.id)) { 135 // TODO: when user data is locked, mark that we're still dirty 136 prepareAppData(batch, pkg, previousAppId, user.id, flags).thenRun(() -> { 137 // Note: this code block is executed with the Installer lock 138 // already held, since it's invoked as a side-effect of 139 // executeBatchLI() 140 if (umInternal.isUserUnlockingOrUnlocked(user.id)) { 141 // Prepare app data on external storage; currently this is used to 142 // setup any OBB dirs that were created by the installer correctly. 143 int uid = UserHandle.getUid(user.id, UserHandle.getAppId(pkg.getUid())); 144 smInternal.prepareAppDataAfterInstall(pkg.getPackageName(), uid); 145 } 146 }); 147 } 148 } 149 executeBatchLI(batch); 150 } 151 executeBatchLI(@onNull Installer.Batch batch)152 private void executeBatchLI(@NonNull Installer.Batch batch) { 153 try { 154 batch.execute(mInstaller); 155 } catch (Installer.InstallerException e) { 156 Slog.w(TAG, "Failed to execute pending operations", e); 157 } 158 } 159 160 /** 161 * Prepare app data for the given app. 162 * <p> 163 * Verifies that directories exist and that ownership and labeling is 164 * correct for all installed apps. If there is an ownership mismatch: 165 * <ul> 166 * <li>If previousAppId < 0, app data will be migrated to the new app ID 167 * <li>If previousAppId == 0, no migration will happen and data will be wiped and recreated 168 * <li>If previousAppId > 0, app data owned by previousAppId will be migrated to the new app ID 169 * </ul> 170 */ prepareAppData(@onNull Installer.Batch batch, @Nullable AndroidPackage pkg, int previousAppId, int userId, @StorageManager.StorageFlags int flags)171 private @NonNull CompletableFuture<?> prepareAppData(@NonNull Installer.Batch batch, 172 @Nullable AndroidPackage pkg, int previousAppId, int userId, 173 @StorageManager.StorageFlags int flags) { 174 if (pkg == null) { 175 Slog.wtf(TAG, "Package was null!", new Throwable()); 176 return CompletableFuture.completedFuture(null); 177 } 178 if (!shouldHaveAppStorage(pkg)) { 179 Slog.w(TAG, "Skipping preparing app data for " + pkg.getPackageName()); 180 return CompletableFuture.completedFuture(null); 181 } 182 return prepareAppDataLeaf(batch, pkg, previousAppId, userId, flags); 183 } 184 prepareAppDataAndMigrate(@onNull Installer.Batch batch, @NonNull PackageState packageState, @NonNull AndroidPackage pkg, @UserIdInt int userId, @StorageManager.StorageFlags int flags, boolean maybeMigrateAppData)185 private void prepareAppDataAndMigrate(@NonNull Installer.Batch batch, 186 @NonNull PackageState packageState, @NonNull AndroidPackage pkg, @UserIdInt int userId, 187 @StorageManager.StorageFlags int flags, boolean maybeMigrateAppData) { 188 prepareAppData(batch, pkg, Process.INVALID_UID, userId, flags).thenRun(() -> { 189 // Note: this code block is executed with the Installer lock 190 // already held, since it's invoked as a side-effect of 191 // executeBatchLI() 192 if (maybeMigrateAppData && maybeMigrateAppDataLIF(packageState, pkg, userId)) { 193 // We may have just shuffled around app data directories, so 194 // prepare them one more time 195 final Installer.Batch batchInner = new Installer.Batch(); 196 prepareAppData(batchInner, pkg, Process.INVALID_UID, userId, flags); 197 executeBatchLI(batchInner); 198 } 199 }); 200 } 201 prepareAppDataLeaf(@onNull Installer.Batch batch, @NonNull AndroidPackage pkg, int previousAppId, int userId, int flags)202 private @NonNull CompletableFuture<?> prepareAppDataLeaf(@NonNull Installer.Batch batch, 203 @NonNull AndroidPackage pkg, int previousAppId, int userId, int flags) { 204 if (DEBUG_APP_DATA) { 205 Slog.v(TAG, "prepareAppData for " + pkg.getPackageName() + " u" + userId + " 0x" 206 + Integer.toHexString(flags)); 207 } 208 209 final PackageSetting ps; 210 final String seInfoUser; 211 synchronized (mPm.mLock) { 212 ps = mPm.mSettings.getPackageLPr(pkg.getPackageName()); 213 seInfoUser = SELinuxUtil.getSeinfoUser(ps.readUserState(userId)); 214 } 215 final String volumeUuid = pkg.getVolumeUuid(); 216 final String packageName = pkg.getPackageName(); 217 218 final int appId = UserHandle.getAppId(pkg.getUid()); 219 220 String pkgSeInfo = ps.getSeInfo(); 221 222 Preconditions.checkNotNull(pkgSeInfo); 223 224 final String seInfo = pkgSeInfo + seInfoUser; 225 final int targetSdkVersion = pkg.getTargetSdkVersion(); 226 final boolean usesSdk = !pkg.getUsesSdkLibraries().isEmpty(); 227 final CreateAppDataArgs args = Installer.buildCreateAppDataArgs(volumeUuid, packageName, 228 userId, flags, appId, seInfo, targetSdkVersion, usesSdk); 229 args.previousAppId = previousAppId; 230 231 return batch.createAppData(args).whenComplete((ceDataInode, e) -> { 232 // Note: this code block is executed with the Installer lock 233 // already held, since it's invoked as a side-effect of 234 // executeBatchLI() 235 if (e != null) { 236 logCriticalInfo(Log.WARN, "Failed to create app data for " + packageName 237 + ", but trying to recover: " + e); 238 destroyAppDataLeafLIF(pkg, userId, flags); 239 try { 240 ceDataInode = mInstaller.createAppData(args).ceDataInode; 241 logCriticalInfo(Log.DEBUG, "Recovery succeeded!"); 242 } catch (Installer.InstallerException e2) { 243 logCriticalInfo(Log.DEBUG, "Recovery failed!"); 244 } 245 } 246 247 if (!DexOptHelper.useArtService()) { // ART Service handles this on demand instead. 248 // Prepare the application profiles only for upgrades and 249 // first boot (so that we don't repeat the same operation at 250 // each boot). 251 // 252 // We only have to cover the upgrade and first boot here 253 // because for app installs we prepare the profiles before 254 // invoking dexopt (in installPackageLI). 255 // 256 // We also have to cover non system users because we do not 257 // call the usual install package methods for them. 258 // 259 // NOTE: in order to speed up first boot time we only create 260 // the current profile and do not update the content of the 261 // reference profile. A system image should already be 262 // configured with the right profile keys and the profiles 263 // for the speed-profile prebuilds should already be copied. 264 // That's done in #performDexOptUpgrade. 265 // 266 // TODO(calin, mathieuc): We should use .dm files for 267 // prebuilds profiles instead of manually copying them in 268 // #performDexOptUpgrade. When we do that we should have a 269 // more granular check here and only update the existing 270 // profiles. 271 if (mPm.isDeviceUpgrading() || mPm.isFirstBoot() 272 || (userId != UserHandle.USER_SYSTEM)) { 273 try { 274 mArtManagerService.prepareAppProfiles(pkg, userId, 275 /* updateReferenceProfileContent= */ false); 276 } catch (LegacyDexoptDisabledException e2) { 277 throw new RuntimeException(e2); 278 } 279 } 280 } 281 282 if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && ceDataInode != -1) { 283 // TODO: mark this structure as dirty so we persist it! 284 synchronized (mPm.mLock) { 285 ps.setCeDataInode(ceDataInode, userId); 286 } 287 } 288 289 prepareAppDataContentsLeafLIF(pkg, ps, userId, flags); 290 }); 291 } 292 293 public void prepareAppDataContentsLIF(AndroidPackage pkg, 294 @Nullable PackageStateInternal pkgSetting, int userId, int flags) { 295 if (pkg == null) { 296 Slog.wtf(TAG, "Package was null!", new Throwable()); 297 return; 298 } 299 prepareAppDataContentsLeafLIF(pkg, pkgSetting, userId, flags); 300 } 301 302 private void prepareAppDataContentsLeafLIF(AndroidPackage pkg, 303 @Nullable PackageStateInternal pkgSetting, int userId, int flags) { 304 final String volumeUuid = pkg.getVolumeUuid(); 305 final String packageName = pkg.getPackageName(); 306 307 if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) { 308 // Create a native library symlink only if we have native libraries 309 // and if the native libraries are 32 bit libraries. We do not provide 310 // this symlink for 64 bit libraries. 311 String primaryCpuAbi = pkgSetting == null 312 ? AndroidPackageUtils.getRawPrimaryCpuAbi(pkg) : pkgSetting.getPrimaryCpuAbi(); 313 if (primaryCpuAbi != null && !VMRuntime.is64BitAbi(primaryCpuAbi)) { 314 final String nativeLibPath = pkg.getNativeLibraryDir(); 315 if (!(new File(nativeLibPath).exists())) { 316 return; 317 } 318 try { 319 mInstaller.linkNativeLibraryDirectory(volumeUuid, packageName, 320 nativeLibPath, userId); 321 } catch (Installer.InstallerException e) { 322 Slog.e(TAG, "Failed to link native for " + packageName + ": " + e); 323 } 324 } 325 } 326 } 327 328 /** 329 * For system apps on non-FBE devices, this method migrates any existing 330 * CE/DE data to match the {@code defaultToDeviceProtectedStorage} flag 331 * requested by the app. 332 */ 333 private boolean maybeMigrateAppDataLIF(@NonNull PackageState packageState, 334 @NonNull AndroidPackage pkg, @UserIdInt int userId) { 335 if (packageState.isSystem() && !StorageManager.isFileEncrypted() 336 && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) { 337 final int storageTarget = pkg.isDefaultToDeviceProtectedStorage() 338 ? StorageManager.FLAG_STORAGE_DE : StorageManager.FLAG_STORAGE_CE; 339 try { 340 mInstaller.migrateAppData(pkg.getVolumeUuid(), pkg.getPackageName(), userId, 341 storageTarget); 342 } catch (Installer.InstallerException e) { 343 logCriticalInfo(Log.WARN, 344 "Failed to migrate " + pkg.getPackageName() + ": " + e.getMessage()); 345 } 346 return true; 347 } else { 348 return false; 349 } 350 } 351 352 /** 353 * Reconcile all app data for the given user. 354 * <p> 355 * Verifies that directories exist and that ownership and labeling is 356 * correct for all installed apps on all mounted volumes. 357 */ 358 @NonNull 359 public void reconcileAppsData(int userId, @StorageManager.StorageFlags int flags, 360 boolean migrateAppsData) { 361 final StorageManager storage = mInjector.getSystemService(StorageManager.class); 362 for (VolumeInfo vol : storage.getWritablePrivateVolumes()) { 363 final String volumeUuid = vol.getFsUuid(); 364 synchronized (mPm.mInstallLock) { 365 reconcileAppsDataLI(volumeUuid, userId, flags, migrateAppsData); 366 } 367 } 368 } 369 370 @GuardedBy("mPm.mInstallLock") 371 void reconcileAppsDataLI(String volumeUuid, int userId, @StorageManager.StorageFlags int flags, 372 boolean migrateAppData) { 373 reconcileAppsDataLI(volumeUuid, userId, flags, migrateAppData, false /* onlyCoreApps */); 374 } 375 376 /** 377 * Reconcile all app data on given mounted volume. 378 * <p> 379 * Destroys app data that isn't expected, either due to uninstallation or 380 * reinstallation on another volume. 381 * <p> 382 * Verifies that directories exist and that ownership and labeling is 383 * correct for all installed apps. 384 * 385 * @return list of skipped non-core packages (if {@code onlyCoreApps} is true) 386 */ 387 @GuardedBy("mPm.mInstallLock") 388 private List<String> reconcileAppsDataLI(String volumeUuid, int userId, 389 @StorageManager.StorageFlags int flags, boolean migrateAppData, boolean onlyCoreApps) { 390 Slog.v(TAG, "reconcileAppsData for " + volumeUuid + " u" + userId + " 0x" 391 + Integer.toHexString(flags) + " migrateAppData=" + migrateAppData); 392 List<String> result = onlyCoreApps ? new ArrayList<>() : null; 393 394 try { 395 mInstaller.cleanupInvalidPackageDirs(volumeUuid, userId, flags); 396 } catch (Installer.InstallerException e) { 397 logCriticalInfo(Log.WARN, "Failed to cleanup deleted dirs: " + e); 398 } 399 400 final File ceDir = Environment.getDataUserCeDirectory(volumeUuid, userId); 401 final File deDir = Environment.getDataUserDeDirectory(volumeUuid, userId); 402 403 final Computer snapshot = mPm.snapshotComputer(); 404 // First look for stale data that doesn't belong, and check if things 405 // have changed since we did our last restorecon 406 if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) { 407 if (StorageManager.isFileEncrypted() && !StorageManager.isUserKeyUnlocked(userId)) { 408 throw new RuntimeException( 409 "Yikes, someone asked us to reconcile CE storage while " + userId 410 + " was still locked; this would have caused massive data loss!"); 411 } 412 413 final File[] files = FileUtils.listFilesOrEmpty(ceDir); 414 for (File file : files) { 415 final String packageName = file.getName(); 416 try { 417 assertPackageStorageValid(snapshot, volumeUuid, packageName, userId); 418 } catch (PackageManagerException e) { 419 logCriticalInfo(Log.WARN, "Destroying " + file + " due to: " + e); 420 try { 421 mInstaller.destroyAppData(volumeUuid, packageName, userId, 422 StorageManager.FLAG_STORAGE_CE, 0); 423 } catch (Installer.InstallerException e2) { 424 logCriticalInfo(Log.WARN, "Failed to destroy: " + e2); 425 } 426 } 427 } 428 } 429 if ((flags & StorageManager.FLAG_STORAGE_DE) != 0) { 430 final File[] files = FileUtils.listFilesOrEmpty(deDir); 431 for (File file : files) { 432 final String packageName = file.getName(); 433 try { 434 assertPackageStorageValid(snapshot, volumeUuid, packageName, userId); 435 } catch (PackageManagerException e) { 436 logCriticalInfo(Log.WARN, "Destroying " + file + " due to: " + e); 437 try { 438 mInstaller.destroyAppData(volumeUuid, packageName, userId, 439 StorageManager.FLAG_STORAGE_DE, 0); 440 } catch (Installer.InstallerException e2) { 441 logCriticalInfo(Log.WARN, "Failed to destroy: " + e2); 442 } 443 } 444 } 445 } 446 447 // Ensure that data directories are ready to roll for all packages 448 // installed for this volume and user 449 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "prepareAppDataAndMigrate"); 450 Installer.Batch batch = new Installer.Batch(); 451 List<? extends PackageStateInternal> packages = snapshot.getVolumePackages(volumeUuid); 452 int preparedCount = 0; 453 for (PackageStateInternal ps : packages) { 454 final String packageName = ps.getPackageName(); 455 if (ps.getPkg() == null) { 456 Slog.w(TAG, "Odd, missing scanned package " + packageName); 457 // TODO: might be due to legacy ASEC apps; we should circle back 458 // and reconcile again once they're scanned 459 continue; 460 } 461 // Skip non-core apps if requested 462 if (onlyCoreApps && !ps.getPkg().isCoreApp()) { 463 result.add(packageName); 464 continue; 465 } 466 467 if (ps.getUserStateOrDefault(userId).isInstalled()) { 468 prepareAppDataAndMigrate(batch, ps, ps.getPkg(), userId, flags, migrateAppData); 469 preparedCount++; 470 } 471 } 472 executeBatchLI(batch); 473 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 474 475 Slog.v(TAG, "reconcileAppsData finished " + preparedCount + " packages"); 476 return result; 477 } 478 479 /** 480 * Asserts that storage path is valid by checking that {@code packageName} is present, 481 * installed for the given {@code userId} and can have app data. 482 */ 483 private void assertPackageStorageValid(@NonNull Computer snapshot, String volumeUuid, 484 String packageName, int userId) throws PackageManagerException { 485 final PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName); 486 if (packageState == null) { 487 throw PackageManagerException.ofInternalError("Package " + packageName + " is unknown", 488 PackageManagerException.INTERNAL_ERROR_STORAGE_INVALID_PACKAGE_UNKNOWN); 489 } else if (!TextUtils.equals(volumeUuid, packageState.getVolumeUuid())) { 490 throw PackageManagerException.ofInternalError( 491 "Package " + packageName + " found on unknown volume " + volumeUuid 492 + "; expected volume " + packageState.getVolumeUuid(), 493 PackageManagerException.INTERNAL_ERROR_STORAGE_INVALID_VOLUME_UNKNOWN); 494 } else if (!packageState.getUserStateOrDefault(userId).isInstalled()) { 495 throw PackageManagerException.ofInternalError( 496 "Package " + packageName + " not installed for user " + userId, 497 PackageManagerException.INTERNAL_ERROR_STORAGE_INVALID_NOT_INSTALLED_FOR_USER); 498 } else if (packageState.getPkg() != null 499 && !shouldHaveAppStorage(packageState.getPkg())) { 500 throw PackageManagerException.ofInternalError( 501 "Package " + packageName + " shouldn't have storage", 502 PackageManagerException.INTERNAL_ERROR_STORAGE_INVALID_SHOULD_NOT_HAVE_STORAGE); 503 } 504 } 505 506 /** 507 * Prepare storage for system user really early during boot, 508 * since core system apps like SettingsProvider and SystemUI 509 * can't wait for user to start 510 */ 511 public Future<?> fixAppsDataOnBoot() { 512 final @StorageManager.StorageFlags int storageFlags; 513 if (StorageManager.isFileEncrypted()) { 514 storageFlags = StorageManager.FLAG_STORAGE_DE; 515 } else { 516 storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE; 517 } 518 List<String> deferPackages = reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL, 519 UserHandle.USER_SYSTEM, storageFlags, true /* migrateAppData */, 520 true /* onlyCoreApps */); 521 Future<?> prepareAppDataFuture = SystemServerInitThreadPool.submit(() -> { 522 TimingsTraceLog traceLog = new TimingsTraceLog("SystemServerTimingAsync", 523 Trace.TRACE_TAG_PACKAGE_MANAGER); 524 traceLog.traceBegin("AppDataFixup"); 525 try { 526 mInstaller.fixupAppData(StorageManager.UUID_PRIVATE_INTERNAL, 527 StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE); 528 } catch (Installer.InstallerException e) { 529 Slog.w(TAG, "Trouble fixing GIDs", e); 530 } 531 traceLog.traceEnd(); 532 533 traceLog.traceBegin("AppDataPrepare"); 534 if (deferPackages == null || deferPackages.isEmpty()) { 535 return; 536 } 537 int count = 0; 538 final Installer.Batch batch = new Installer.Batch(); 539 for (String pkgName : deferPackages) { 540 final Computer snapshot = mPm.snapshotComputer(); 541 final PackageStateInternal packageStateInternal = snapshot.getPackageStateInternal( 542 pkgName); 543 if (packageStateInternal != null 544 && packageStateInternal.getUserStateOrDefault( 545 UserHandle.USER_SYSTEM).isInstalled()) { 546 AndroidPackage pkg = packageStateInternal.getPkg(); 547 prepareAppDataAndMigrate(batch, packageStateInternal, pkg, 548 UserHandle.USER_SYSTEM, storageFlags, true /* maybeMigrateAppData */); 549 count++; 550 } 551 } 552 synchronized (mPm.mInstallLock) { 553 executeBatchLI(batch); 554 } 555 traceLog.traceEnd(); 556 Slog.i(TAG, "Deferred reconcileAppsData finished " + count + " packages"); 557 }, "prepareAppData"); 558 return prepareAppDataFuture; 559 } 560 561 void clearAppDataLIF(AndroidPackage pkg, int userId, int flags) { 562 if (pkg == null) { 563 return; 564 } 565 clearAppDataLeafLIF(pkg, userId, flags); 566 567 if ((flags & Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES) == 0) { 568 clearAppProfilesLIF(pkg); 569 } 570 } 571 572 private void clearAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) { 573 final Computer snapshot = mPm.snapshotComputer(); 574 final PackageStateInternal packageStateInternal = 575 snapshot.getPackageStateInternal(pkg.getPackageName()); 576 for (int realUserId : mPm.resolveUserIds(userId)) { 577 final long ceDataInode = (packageStateInternal != null) 578 ? packageStateInternal.getUserStateOrDefault(realUserId).getCeDataInode() : 0; 579 try { 580 mInstaller.clearAppData(pkg.getVolumeUuid(), pkg.getPackageName(), realUserId, 581 flags, ceDataInode); 582 } catch (Installer.InstallerException e) { 583 Slog.w(TAG, String.valueOf(e)); 584 } 585 } 586 } 587 588 void clearAppProfilesLIF(AndroidPackage pkg) { 589 if (pkg == null) { 590 Slog.wtf(TAG, "Package was null!", new Throwable()); 591 return; 592 } 593 if (DexOptHelper.useArtService()) { 594 destroyAppProfilesWithArtService(pkg); 595 } else { 596 try { 597 mArtManagerService.clearAppProfiles(pkg); 598 } catch (LegacyDexoptDisabledException e) { 599 throw new RuntimeException(e); 600 } 601 } 602 } 603 604 public void destroyAppDataLIF(AndroidPackage pkg, int userId, int flags) { 605 if (pkg == null) { 606 Slog.wtf(TAG, "Package was null!", new Throwable()); 607 return; 608 } 609 destroyAppDataLeafLIF(pkg, userId, flags); 610 } 611 612 public void destroyAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) { 613 final Computer snapshot = mPm.snapshotComputer(); 614 final PackageStateInternal packageStateInternal = 615 snapshot.getPackageStateInternal(pkg.getPackageName()); 616 for (int realUserId : mPm.resolveUserIds(userId)) { 617 final long ceDataInode = (packageStateInternal != null) 618 ? packageStateInternal.getUserStateOrDefault(realUserId).getCeDataInode() : 0; 619 try { 620 mInstaller.destroyAppData(pkg.getVolumeUuid(), pkg.getPackageName(), realUserId, 621 flags, ceDataInode); 622 } catch (Installer.InstallerException e) { 623 Slog.w(TAG, String.valueOf(e)); 624 } 625 mPm.getDexManager().notifyPackageDataDestroyed(pkg.getPackageName(), userId); 626 mPm.getDynamicCodeLogger().notifyPackageDataDestroyed(pkg.getPackageName(), userId); 627 } 628 } 629 630 public void destroyAppProfilesLIF(AndroidPackage pkg) { 631 if (pkg == null) { 632 Slog.wtf(TAG, "Package was null!", new Throwable()); 633 return; 634 } 635 destroyAppProfilesLeafLIF(pkg); 636 } 637 638 private void destroyAppProfilesLeafLIF(AndroidPackage pkg) { 639 if (DexOptHelper.useArtService()) { 640 destroyAppProfilesWithArtService(pkg); 641 } else { 642 try { 643 mInstaller.destroyAppProfiles(pkg.getPackageName()); 644 } catch (LegacyDexoptDisabledException e) { 645 throw new RuntimeException(e); 646 } catch (Installer.InstallerException e) { 647 Slog.w(TAG, String.valueOf(e)); 648 } 649 } 650 } 651 652 private void destroyAppProfilesWithArtService(AndroidPackage pkg) { 653 if (!DexOptHelper.artManagerLocalIsInitialized()) { 654 // This function may get called while PackageManagerService is constructed (via e.g. 655 // InitAppsHelper.initSystemApps), and ART Service hasn't yet been started then (it 656 // requires a registered PackageManagerLocal instance). We can skip clearing any stale 657 // app profiles in this case, because ART Service and the runtime will ignore stale or 658 // otherwise invalid ref and cur profiles. 659 return; 660 } 661 662 try (PackageManagerLocal.FilteredSnapshot snapshot = 663 getPackageManagerLocal().withFilteredSnapshot()) { 664 try { 665 DexOptHelper.getArtManagerLocal().clearAppProfiles(snapshot, pkg.getPackageName()); 666 } catch (IllegalArgumentException e) { 667 // Package isn't found, but that should only happen due to race. 668 Slog.w(TAG, e); 669 } 670 } 671 } 672 673 /** 674 * Returns {@code true} if app's internal storage should be created for this {@code pkg}. 675 */ 676 private boolean shouldHaveAppStorage(AndroidPackage pkg) { 677 PackageManager.Property noAppDataProp = 678 pkg.getProperties().get(PackageManager.PROPERTY_NO_APP_DATA_STORAGE); 679 return (noAppDataProp == null || !noAppDataProp.getBoolean()) && pkg.getUid() >= 0; 680 } 681 682 /** 683 * Remove entries from the keystore daemon. Will only remove if the {@code appId} is valid. 684 */ 685 public void clearKeystoreData(int userId, int appId) { 686 if (appId < 0) { 687 return; 688 } 689 690 for (int realUserId : mPm.resolveUserIds(userId)) { 691 AndroidKeyStoreMaintenance.clearNamespace( 692 Domain.APP, UserHandle.getUid(realUserId, appId)); 693 } 694 } 695 } 696