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