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