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.SpecialUsers.CanBeALL; 28 import android.annotation.UserIdInt; 29 import android.content.pm.PackageManager; 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.dex.ArtManagerService; 50 import com.android.server.pm.parsing.pkg.AndroidPackageUtils; 51 import com.android.server.pm.pkg.AndroidPackage; 52 import com.android.server.pm.pkg.PackageStateInternal; 53 import com.android.server.pm.pkg.PackageUserStateInternal; 54 import com.android.server.pm.pkg.SELinuxUtil; 55 56 import dalvik.system.VMRuntime; 57 58 import java.io.File; 59 import java.util.ArrayList; 60 import java.util.Arrays; 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 final PackageSetting ps; 98 synchronized (mPm.mLock) { 99 ps = mPm.mSettings.getPackageLPr(pkg.getPackageName()); 100 } 101 102 prepareAppDataPostCommitLIF(ps, 0 /* previousAppId */, getInstalledUsersForPackage(ps)); 103 } 104 getInstalledUsersForPackage(PackageSetting ps)105 private int[] getInstalledUsersForPackage(PackageSetting ps) { 106 UserManagerInternal umInternal = mInjector.getUserManagerInternal(); 107 var users = umInternal.getUsers(false /*excludeDying*/); 108 int[] userIds = new int[users.size()]; 109 int userIdsCount = 0; 110 for (int i = 0, size = users.size(); i < size; ++i) { 111 int userId = users.get(i).id; 112 if (ps.getInstalled(userId)) { 113 userIds[userIdsCount++] = userId; 114 } 115 } 116 return Arrays.copyOf(userIds, userIdsCount); 117 } 118 119 /** 120 * For more details about data verification and previousAppId, check 121 * {@link #prepareAppData} 122 * @see #prepareAppDataAfterInstallLIF 123 */ 124 @GuardedBy("mPm.mInstallLock") prepareAppDataPostCommitLIF(PackageSetting ps, int previousAppId, int[] userIds)125 public void prepareAppDataPostCommitLIF(PackageSetting ps, int previousAppId, int[] userIds) { 126 synchronized (mPm.mLock) { 127 mPm.mSettings.writeKernelMappingLPr(ps); 128 } 129 130 // TODO(b/211761016): should we still create the profile dirs? 131 if (!shouldHaveAppStorage(ps)) { 132 Slog.w(TAG, "Skipping preparing app data for " + ps.getPackageName()); 133 return; 134 } 135 136 Installer.Batch batch = new Installer.Batch(); 137 UserManagerInternal umInternal = mInjector.getUserManagerInternal(); 138 StorageManagerInternal smInternal = mInjector.getLocalService( 139 StorageManagerInternal.class); 140 for (int userId : userIds) { 141 final int flags; 142 if (StorageManager.isCeStorageUnlocked(userId) 143 && smInternal.isCeStoragePrepared(userId)) { 144 flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE; 145 } else if (umInternal.isUserRunning(userId)) { 146 flags = StorageManager.FLAG_STORAGE_DE; 147 } else { 148 continue; 149 } 150 151 // TODO: when user data is locked, mark that we're still dirty 152 prepareAppData(batch, ps, previousAppId, userId, flags).thenRun(() -> { 153 // Note: this code block is executed with the Installer lock 154 // already held, since it's invoked as a side-effect of 155 // executeBatchLI() 156 if (umInternal.isUserUnlockingOrUnlocked(userId)) { 157 // Prepare app data on external storage; currently this is used to 158 // setup any OBB dirs that were created by the installer correctly. 159 int uid = UserHandle.getUid(userId, ps.getAppId()); 160 smInternal.prepareAppDataAfterInstall(ps.getPackageName(), uid); 161 } 162 }); 163 } 164 executeBatchLI(batch); 165 } 166 executeBatchLI(@onNull Installer.Batch batch)167 private void executeBatchLI(@NonNull Installer.Batch batch) { 168 try { 169 batch.execute(mInstaller); 170 } catch (Installer.InstallerException e) { 171 Slog.w(TAG, "Failed to execute pending operations", e); 172 } 173 } 174 prepareAppDataAndMigrate(@onNull Installer.Batch batch, @NonNull PackageStateInternal psi, @UserIdInt int userId, @StorageManager.StorageFlags int flags, boolean maybeMigrateAppData)175 private void prepareAppDataAndMigrate(@NonNull Installer.Batch batch, 176 @NonNull PackageStateInternal psi, @UserIdInt int userId, 177 @StorageManager.StorageFlags int flags, boolean maybeMigrateAppData) { 178 if (psi == null || psi.getPkg() == null) { 179 Slog.wtf(TAG, "Package was null!", new Throwable()); 180 return; 181 } 182 if (!shouldHaveAppStorage(psi)) { 183 Slog.w(TAG, "Skipping preparing app data for " + psi.getPackageName()); 184 return; 185 } 186 final PackageSetting ps; 187 synchronized (mPm.mLock) { 188 ps = mPm.mSettings.getPackageLPr(psi.getPackageName()); 189 } 190 prepareAppData(batch, ps, Process.INVALID_UID, userId, flags).thenRun(() -> { 191 // Note: this code block is executed with the Installer lock 192 // already held, since it's invoked as a side-effect of 193 // executeBatchLI() 194 if (maybeMigrateAppData && maybeMigrateAppDataLIF(ps, userId)) { 195 // We may have just shuffled around app data directories, so 196 // prepare them one more time 197 final Installer.Batch batchInner = new Installer.Batch(); 198 prepareAppData(batchInner, ps, Process.INVALID_UID, userId, flags); 199 executeBatchLI(batchInner); 200 } 201 }); 202 } 203 204 /** 205 * Prepare app data for the given app. 206 * <p> 207 * Verifies that directories exist and that ownership and labeling is 208 * correct for all installed apps. If there is an ownership mismatch: 209 * <ul> 210 * <li>If previousAppId < 0, app data will be migrated to the new app ID 211 * <li>If previousAppId == 0, no migration will happen and data will be wiped and recreated 212 * <li>If previousAppId > 0, app data owned by previousAppId will be migrated to the new app ID 213 * </ul> 214 */ prepareAppData(@onNull Installer.Batch batch, @NonNull PackageSetting ps, int previousAppId, int userId, int flags)215 private @NonNull CompletableFuture<?> prepareAppData(@NonNull Installer.Batch batch, 216 @NonNull PackageSetting ps, int previousAppId, int userId, int flags) { 217 final String packageName = ps.getPackageName(); 218 219 if (DEBUG_APP_DATA) { 220 Slog.v(TAG, "prepareAppData for " + packageName + " u" + userId + " 0x" 221 + Integer.toHexString(flags)); 222 } 223 224 final String seInfoUser; 225 synchronized (mPm.mLock) { 226 seInfoUser = SELinuxUtil.getSeinfoUser(ps.readUserState(userId)); 227 } 228 229 final AndroidPackage pkg = ps.getPkg(); 230 final String volumeUuid = ps.getVolumeUuid(); 231 final int appId = ps.getAppId(); 232 233 String pkgSeInfo = ps.getSeInfo(); 234 Preconditions.checkNotNull(pkgSeInfo); 235 236 final String seInfo = pkgSeInfo + seInfoUser; 237 final int targetSdkVersion = ps.getTargetSdkVersion(); 238 final boolean usesSdk = ps.getUsesSdkLibraries().length > 0; 239 final CreateAppDataArgs args = Installer.buildCreateAppDataArgs(volumeUuid, packageName, 240 userId, flags, appId, seInfo, targetSdkVersion, usesSdk); 241 args.previousAppId = previousAppId; 242 243 return batch.createAppData(args).whenComplete((createAppDataResult, e) -> { 244 // Note: this code block is executed with the Installer lock 245 // already held, since it's invoked as a side-effect of 246 // executeBatchLI() 247 if (e != null) { 248 logCriticalInfo(Log.WARN, "Failed to create app data for " + packageName 249 + ", but trying to recover: " + e); 250 destroyAppDataLeafLIF(packageName, volumeUuid, userId, flags); 251 try { 252 createAppDataResult = mInstaller.createAppData(args); 253 logCriticalInfo(Log.DEBUG, "Recovery succeeded!"); 254 } catch (Installer.InstallerException e2) { 255 logCriticalInfo(Log.DEBUG, "Recovery failed!"); 256 } 257 } 258 259 final long ceDataInode = createAppDataResult.ceDataInode; 260 final long deDataInode = createAppDataResult.deDataInode; 261 262 if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && ceDataInode != -1) { 263 synchronized (mPm.mLock) { 264 ps.setCeDataInode(ceDataInode, userId); 265 } 266 } 267 if ((flags & StorageManager.FLAG_STORAGE_DE) != 0 && deDataInode != -1) { 268 synchronized (mPm.mLock) { 269 ps.setDeDataInode(deDataInode, userId); 270 } 271 } 272 273 if (pkg != null) { 274 prepareAppDataContentsLeafLIF(pkg, ps, userId, flags); 275 } 276 }); 277 } 278 279 public void prepareAppDataContentsLIF(AndroidPackage pkg, 280 @Nullable PackageStateInternal pkgSetting, int userId, int flags) { 281 if (pkg == null) { 282 Slog.wtf(TAG, "Package was null!", new Throwable()); 283 return; 284 } 285 prepareAppDataContentsLeafLIF(pkg, pkgSetting, userId, flags); 286 } 287 288 private void prepareAppDataContentsLeafLIF(AndroidPackage pkg, 289 @Nullable PackageStateInternal pkgSetting, int userId, int flags) { 290 final String volumeUuid = pkg.getVolumeUuid(); 291 final String packageName = pkg.getPackageName(); 292 293 if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) { 294 // Create a native library symlink only if we have native libraries 295 // and if the native libraries are 32 bit libraries. We do not provide 296 // this symlink for 64 bit libraries. 297 String primaryCpuAbi = pkgSetting == null 298 ? AndroidPackageUtils.getRawPrimaryCpuAbi(pkg) : pkgSetting.getPrimaryCpuAbi(); 299 if (primaryCpuAbi != null && !VMRuntime.is64BitAbi(primaryCpuAbi)) { 300 final String nativeLibPath = pkg.getNativeLibraryDir(); 301 if (!(new File(nativeLibPath).exists())) { 302 return; 303 } 304 try { 305 mInstaller.linkNativeLibraryDirectory(volumeUuid, packageName, 306 nativeLibPath, userId); 307 } catch (Installer.InstallerException e) { 308 Slog.e(TAG, "Failed to link native for " + packageName + ": " + e); 309 } 310 } 311 } 312 } 313 314 /** 315 * For system apps on non-FBE devices, this method migrates any existing 316 * CE/DE data to match the {@code defaultToDeviceProtectedStorage} flag 317 * requested by the app. 318 */ 319 private boolean maybeMigrateAppDataLIF(@NonNull PackageSetting ps, @UserIdInt int userId) { 320 if (ps.isSystem() && !StorageManager.isFileEncrypted() 321 && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) { 322 final int storageTarget = ps.isDefaultToDeviceProtectedStorage() 323 ? StorageManager.FLAG_STORAGE_DE : StorageManager.FLAG_STORAGE_CE; 324 try { 325 mInstaller.migrateAppData(ps.getVolumeUuid(), ps.getPackageName(), userId, 326 storageTarget); 327 } catch (Installer.InstallerException e) { 328 logCriticalInfo(Log.WARN, 329 "Failed to migrate " + ps.getPackageName() + ": " + e.getMessage()); 330 } 331 return true; 332 } else { 333 return false; 334 } 335 } 336 337 /** 338 * Reconcile all app data for the given user. 339 * <p> 340 * Verifies that directories exist and that ownership and labeling is 341 * correct for all installed apps on all mounted volumes. 342 */ 343 @NonNull 344 public void reconcileAppsData(int userId, @StorageManager.StorageFlags int flags, 345 boolean migrateAppsData) { 346 final StorageManager storage = mInjector.getSystemService(StorageManager.class); 347 for (VolumeInfo vol : storage.getWritablePrivateVolumes()) { 348 final String volumeUuid = vol.getFsUuid(); 349 try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { 350 reconcileAppsDataLI(volumeUuid, userId, flags, migrateAppsData); 351 } 352 } 353 } 354 355 @GuardedBy("mPm.mInstallLock") 356 void reconcileAppsDataLI(String volumeUuid, int userId, @StorageManager.StorageFlags int flags, 357 boolean migrateAppData) { 358 reconcileAppsDataLI(volumeUuid, userId, flags, migrateAppData, false /* onlyCoreApps */); 359 } 360 361 /** 362 * Reconcile all app data on given mounted volume. 363 * <p> 364 * Destroys app data that isn't expected, either due to uninstallation or 365 * reinstallation on another volume. 366 * <p> 367 * Verifies that directories exist and that ownership and labeling is 368 * correct for all installed apps. 369 * 370 * @return list of skipped non-core packages (if {@code onlyCoreApps} is true) 371 */ 372 @GuardedBy("mPm.mInstallLock") 373 private List<String> reconcileAppsDataLI(String volumeUuid, int userId, 374 @StorageManager.StorageFlags int flags, boolean migrateAppData, boolean onlyCoreApps) { 375 Slog.v(TAG, "reconcileAppsData for " + volumeUuid + " u" + userId + " 0x" 376 + Integer.toHexString(flags) + " migrateAppData=" + migrateAppData); 377 List<String> result = onlyCoreApps ? new ArrayList<>() : null; 378 379 try { 380 mInstaller.cleanupInvalidPackageDirs(volumeUuid, userId, flags); 381 } catch (Installer.InstallerException e) { 382 logCriticalInfo(Log.WARN, "Failed to cleanup deleted dirs: " + e); 383 } 384 385 final File ceDir = Environment.getDataUserCeDirectory(volumeUuid, userId); 386 final File deDir = Environment.getDataUserDeDirectory(volumeUuid, userId); 387 388 final Computer snapshot = mPm.snapshotComputer(); 389 // First look for stale data that doesn't belong, and check if things 390 // have changed since we did our last restorecon 391 if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) { 392 if (StorageManager.isFileEncrypted() && !StorageManager.isCeStorageUnlocked(userId)) { 393 throw new RuntimeException( 394 "Yikes, someone asked us to reconcile CE storage while " + userId 395 + " was still locked; this would have caused massive data loss!"); 396 } 397 398 final File[] files = FileUtils.listFilesOrEmpty(ceDir); 399 for (File file : files) { 400 final String packageName = file.getName(); 401 try { 402 assertPackageStorageValid(snapshot, volumeUuid, packageName, userId); 403 } catch (PackageManagerException e) { 404 logCriticalInfo(Log.WARN, "Destroying " + file + " due to: " + e); 405 try { 406 mInstaller.destroyAppData(volumeUuid, packageName, userId, 407 StorageManager.FLAG_STORAGE_CE, 0); 408 } catch (Installer.InstallerException e2) { 409 logCriticalInfo(Log.WARN, "Failed to destroy: " + e2); 410 } 411 } 412 } 413 } 414 if ((flags & StorageManager.FLAG_STORAGE_DE) != 0) { 415 final File[] files = FileUtils.listFilesOrEmpty(deDir); 416 for (File file : files) { 417 final String packageName = file.getName(); 418 try { 419 assertPackageStorageValid(snapshot, volumeUuid, packageName, userId); 420 } catch (PackageManagerException e) { 421 logCriticalInfo(Log.WARN, "Destroying " + file + " due to: " + e); 422 try { 423 mInstaller.destroyAppData(volumeUuid, packageName, userId, 424 StorageManager.FLAG_STORAGE_DE, 0); 425 } catch (Installer.InstallerException e2) { 426 logCriticalInfo(Log.WARN, "Failed to destroy: " + e2); 427 } 428 } 429 } 430 } 431 432 // Ensure that data directories are ready to roll for all packages 433 // installed for this volume and user 434 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "prepareAppDataAndMigrate"); 435 Installer.Batch batch = new Installer.Batch(); 436 List<? extends PackageStateInternal> packages = snapshot.getVolumePackages(volumeUuid); 437 int preparedCount = 0; 438 for (PackageStateInternal ps : packages) { 439 final String packageName = ps.getPackageName(); 440 if (ps.getPkg() == null) { 441 Slog.w(TAG, "Odd, missing scanned package " + packageName); 442 // TODO: might be due to legacy ASEC apps; we should circle back 443 // and reconcile again once they're scanned 444 continue; 445 } 446 // Skip non-core apps if requested 447 if (onlyCoreApps && !ps.getPkg().isCoreApp()) { 448 result.add(packageName); 449 continue; 450 } 451 452 if (ps.getUserStateOrDefault(userId).isInstalled()) { 453 prepareAppDataAndMigrate(batch, ps, userId, flags, migrateAppData); 454 preparedCount++; 455 } 456 } 457 executeBatchLI(batch); 458 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 459 460 Slog.v(TAG, "reconcileAppsData finished " + preparedCount + " packages"); 461 return result; 462 } 463 464 /** 465 * Asserts that storage path is valid by checking that {@code packageName} is present, 466 * installed for the given {@code userId} and can have app data. 467 */ 468 private void assertPackageStorageValid(@NonNull Computer snapshot, String volumeUuid, 469 String packageName, int userId) throws PackageManagerException { 470 final PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName); 471 if (packageState == null) { 472 throw PackageManagerException.ofInternalError("Package " + packageName + " is unknown", 473 PackageManagerException.INTERNAL_ERROR_STORAGE_INVALID_PACKAGE_UNKNOWN); 474 } 475 if (!TextUtils.equals(volumeUuid, packageState.getVolumeUuid())) { 476 throw PackageManagerException.ofInternalError( 477 "Package " + packageName + " found on unknown volume " + volumeUuid 478 + "; expected volume " + packageState.getVolumeUuid(), 479 PackageManagerException.INTERNAL_ERROR_STORAGE_INVALID_VOLUME_UNKNOWN); 480 } 481 final PackageUserStateInternal userState = packageState.getUserStateOrDefault(userId); 482 if (!userState.isInstalled() && !userState.dataExists()) { 483 throw PackageManagerException.ofInternalError( 484 "Package " + packageName + " not installed for user " + userId 485 + " or was deleted without DELETE_KEEP_DATA", 486 PackageManagerException.INTERNAL_ERROR_STORAGE_INVALID_NOT_INSTALLED_FOR_USER); 487 } 488 if (!shouldHaveAppStorage(packageState)) { 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 prepareAppDataAndMigrate(batch, packageStateInternal, 539 UserHandle.USER_SYSTEM, storageFlags, true /* maybeMigrateAppData */); 540 count++; 541 } 542 } 543 try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { 544 executeBatchLI(batch); 545 } 546 traceLog.traceEnd(); 547 Slog.i(TAG, "Deferred reconcileAppsData finished " + count + " packages"); 548 }, "prepareAppData"); 549 return prepareAppDataFuture; 550 } 551 552 void clearAppDataLIF(AndroidPackage pkg, @CanBeALL @UserIdInt int userId, int flags) { 553 if (pkg == null) { 554 return; 555 } 556 clearAppDataLeafLIF(pkg.getPackageName(), pkg.getVolumeUuid(), userId, flags); 557 558 if ((flags & Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES) == 0) { 559 clearAppProfilesLIF(pkg); 560 } 561 } 562 563 void clearAppDataLeafLIF(String packageName, String volumeUuid, @CanBeALL @UserIdInt int userId, 564 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 ps}. 641 */ 642 private boolean shouldHaveAppStorage(PackageStateInternal ps) { 643 if (ps.getPkg() == null) { 644 // Keeps the legacy behavior 645 return true; 646 } 647 PackageManager.Property noAppDataProp = 648 ps.getPkg().getProperties().get(PackageManager.PROPERTY_NO_APP_DATA_STORAGE); 649 return (noAppDataProp == null || !noAppDataProp.getBoolean()) && ps.getAppId() >= 0; 650 } 651 652 /** 653 * Remove entries from the keystore daemon. Will only remove if the {@code appId} is valid. 654 */ 655 public void clearKeystoreData(int userId, int appId) { 656 if (appId < 0) { 657 return; 658 } 659 660 for (int realUserId : mPm.resolveUserIds(userId)) { 661 AndroidKeyStoreMaintenance.clearNamespace( 662 Domain.APP, UserHandle.getUid(realUserId, appId)); 663 } 664 } 665 } 666