1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.pm; 18 19 import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN; 20 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; 21 import static android.os.incremental.IncrementalManager.isIncrementalPath; 22 import static android.os.storage.StorageManager.FLAG_STORAGE_CE; 23 import static android.os.storage.StorageManager.FLAG_STORAGE_DE; 24 import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL; 25 26 import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL; 27 import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE; 28 import static com.android.server.pm.PackageManagerService.RANDOM_DIR_PREFIX; 29 import static com.android.server.pm.PackageManagerService.TAG; 30 31 import android.annotation.NonNull; 32 import android.annotation.Nullable; 33 import android.annotation.SpecialUsers.CanBeALL; 34 import android.annotation.UserIdInt; 35 import android.content.pm.PackageManager; 36 import android.content.pm.parsing.ApkLiteParseUtils; 37 import android.content.pm.parsing.PackageLite; 38 import android.content.pm.parsing.result.ParseResult; 39 import android.content.pm.parsing.result.ParseTypeImpl; 40 import android.os.Environment; 41 import android.os.Trace; 42 import android.os.UserHandle; 43 import android.os.incremental.IncrementalManager; 44 import android.util.Log; 45 import android.util.Slog; 46 import android.util.SparseBooleanArray; 47 48 import com.android.internal.annotations.GuardedBy; 49 import com.android.internal.pm.parsing.pkg.AndroidPackageLegacyUtils; 50 import com.android.internal.pm.parsing.pkg.PackageImpl; 51 import com.android.internal.pm.pkg.component.ParsedInstrumentation; 52 import com.android.internal.util.ArrayUtils; 53 import com.android.server.pm.parsing.PackageCacher; 54 import com.android.server.pm.permission.PermissionManagerServiceInternal; 55 import com.android.server.pm.pkg.AndroidPackage; 56 import com.android.server.pm.pkg.PackageStateInternal; 57 58 import java.io.File; 59 import java.util.Collections; 60 import java.util.List; 61 62 /** 63 * Removes a package from internal data structures, deletes it data directories if requested, 64 * and clears its app profiles 65 */ 66 final class RemovePackageHelper { 67 private final PackageManagerService mPm; 68 private final IncrementalManager mIncrementalManager; 69 private final Installer mInstaller; 70 private final PermissionManagerServiceInternal mPermissionManager; 71 private final SharedLibrariesImpl mSharedLibraries; 72 private final AppDataHelper mAppDataHelper; 73 private final BroadcastHelper mBroadcastHelper; 74 75 // TODO(b/198166813): remove PMS dependency RemovePackageHelper(PackageManagerService pm, AppDataHelper appDataHelper, BroadcastHelper broadcastHelper)76 RemovePackageHelper(PackageManagerService pm, AppDataHelper appDataHelper, 77 BroadcastHelper broadcastHelper) { 78 mPm = pm; 79 mIncrementalManager = mPm.mInjector.getIncrementalManager(); 80 mInstaller = mPm.mInjector.getInstaller(); 81 mPermissionManager = mPm.mInjector.getPermissionManagerServiceInternal(); 82 mSharedLibraries = mPm.mInjector.getSharedLibrariesImpl(); 83 mAppDataHelper = appDataHelper; 84 mBroadcastHelper = broadcastHelper; 85 } 86 removeCodePath(File codePath)87 public void removeCodePath(File codePath) { 88 try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { 89 removeCodePathLI(codePath); 90 } 91 } 92 93 @GuardedBy("mPm.mInstallLock") removeCodePathLI(File codePath)94 private void removeCodePathLI(File codePath) { 95 if (codePath == null || !codePath.exists()) { 96 return; 97 } 98 if (codePath.isDirectory()) { 99 final File codePathParent = codePath.getParentFile(); 100 final boolean needRemoveParent = codePathParent.getName().startsWith(RANDOM_DIR_PREFIX); 101 try { 102 final boolean isIncremental = (mIncrementalManager != null && isIncrementalPath( 103 codePath.getAbsolutePath())); 104 if (isIncremental) { 105 if (needRemoveParent) { 106 mIncrementalManager.rmPackageDir(codePathParent); 107 } else { 108 mIncrementalManager.rmPackageDir(codePath); 109 } 110 } 111 112 final String packageName = codePath.getName(); 113 mInstaller.rmPackageDir(packageName, codePath.getAbsolutePath()); 114 if (needRemoveParent) { 115 mInstaller.rmPackageDir(packageName, codePathParent.getAbsolutePath()); 116 removeCachedResult(codePathParent); 117 } 118 } catch (Installer.InstallerException e) { 119 Slog.w(TAG, "Failed to remove code path", e); 120 } 121 } else { 122 codePath.delete(); 123 } 124 } 125 removeCachedResult(@onNull File codePath)126 private void removeCachedResult(@NonNull File codePath) { 127 if (mPm.getCacheDir() == null) { 128 return; 129 } 130 131 final PackageCacher cacher = new PackageCacher(mPm.getCacheDir()); 132 // Find and delete the cached result belong to the given codePath. 133 cacher.cleanCachedResult(codePath); 134 } 135 136 // Used for system apps only removePackage(AndroidPackage pkg, boolean chatty)137 public void removePackage(AndroidPackage pkg, boolean chatty) { 138 try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { 139 removePackageLI(pkg, chatty); 140 } 141 } 142 143 @GuardedBy("mPm.mInstallLock") removePackageLI(AndroidPackage pkg, boolean chatty)144 private void removePackageLI(AndroidPackage pkg, boolean chatty) { 145 // Remove the parent package setting 146 PackageStateInternal ps = mPm.snapshotComputer() 147 .getPackageStateInternal(pkg.getPackageName()); 148 if (ps != null) { 149 removePackageLI(ps.getPackageName(), chatty); 150 } else if (DEBUG_REMOVE && chatty) { 151 Log.d(TAG, "Not removing package " + pkg.getPackageName() + "; mExtras == null"); 152 } 153 } 154 155 @GuardedBy("mPm.mInstallLock") removePackageLI(String packageName, boolean chatty)156 private void removePackageLI(String packageName, boolean chatty) { 157 if (DEBUG_INSTALL) { 158 if (chatty) { 159 Log.d(TAG, "Removing package " + packageName); 160 } 161 } 162 163 // writer 164 synchronized (mPm.mLock) { 165 final AndroidPackage removedPackage = mPm.mPackages.remove(packageName); 166 if (removedPackage != null) { 167 // TODO: Use PackageState for isSystem 168 cleanPackageDataStructuresLILPw(removedPackage, 169 AndroidPackageLegacyUtils.isSystem(removedPackage), chatty); 170 } 171 } 172 } 173 174 @GuardedBy("mPm.mLock") cleanPackageDataStructuresLILPw(AndroidPackage pkg, boolean isSystemApp, boolean chatty)175 private void cleanPackageDataStructuresLILPw(AndroidPackage pkg, boolean isSystemApp, 176 boolean chatty) { 177 mPm.mComponentResolver.removeAllComponents(pkg, chatty); 178 mPermissionManager.onPackageRemoved(pkg); 179 mPm.getPackageProperty().removeAllProperties(pkg); 180 181 final int instrumentationSize = ArrayUtils.size(pkg.getInstrumentations()); 182 StringBuilder r = null; 183 int i; 184 for (i = 0; i < instrumentationSize; i++) { 185 ParsedInstrumentation a = pkg.getInstrumentations().get(i); 186 mPm.getInstrumentation().remove(a.getComponentName()); 187 if (DEBUG_REMOVE && chatty) { 188 if (r == null) { 189 r = new StringBuilder(256); 190 } else { 191 r.append(' '); 192 } 193 r.append(a.getName()); 194 } 195 } 196 if (r != null) { 197 if (DEBUG_REMOVE) Log.d(TAG, " Instrumentation: " + r); 198 } 199 200 r = null; 201 if (isSystemApp) { 202 // Only system apps can hold shared libraries. 203 final int libraryNamesSize = pkg.getLibraryNames().size(); 204 for (i = 0; i < libraryNamesSize; i++) { 205 String name = pkg.getLibraryNames().get(i); 206 if (mSharedLibraries.removeSharedLibrary(name, 0)) { 207 if (DEBUG_REMOVE && chatty) { 208 if (r == null) { 209 r = new StringBuilder(256); 210 } else { 211 r.append(' '); 212 } 213 r.append(name); 214 } 215 } 216 } 217 } 218 219 r = null; 220 221 // Any package can hold SDK or static shared libraries. 222 if (pkg.getSdkLibraryName() != null) { 223 if (mSharedLibraries.removeSharedLibrary( 224 pkg.getSdkLibraryName(), pkg.getSdkLibVersionMajor())) { 225 if (DEBUG_REMOVE && chatty) { 226 if (r == null) { 227 r = new StringBuilder(256); 228 } else { 229 r.append(' '); 230 } 231 r.append(pkg.getSdkLibraryName()); 232 } 233 } 234 } 235 if (pkg.getStaticSharedLibraryName() != null) { 236 if (mSharedLibraries.removeSharedLibrary(pkg.getStaticSharedLibraryName(), 237 pkg.getStaticSharedLibraryVersion())) { 238 if (DEBUG_REMOVE && chatty) { 239 if (r == null) { 240 r = new StringBuilder(256); 241 } else { 242 r.append(' '); 243 } 244 r.append(pkg.getStaticSharedLibraryName()); 245 } 246 } 247 } 248 249 if (r != null) { 250 if (DEBUG_REMOVE) Log.d(TAG, " Libraries: " + r); 251 } 252 } 253 254 /** 255 * This method clears the data and states stored in the system that are related to the 256 * package being deleted and the target user, including the data directory. 257 * If the DELETE_KEEP_DATA flag is set, everything is preserved except ART profiles. 258 * Make sure this flag is set for partially installed apps. If not it's meaningless to 259 * delete a partially installed application. 260 */ clearPackageStateForUserLIF(PackageSetting ps, @CanBeALL @UserIdInt int userId, int flags)261 public void clearPackageStateForUserLIF(PackageSetting ps, @CanBeALL @UserIdInt int userId, 262 int flags) { 263 final String packageName = ps.getPackageName(); 264 // Step 1: always destroy app profiles except when explicitly preserved 265 if ((flags & Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES) == 0) { 266 mAppDataHelper.destroyAppProfilesLIF(packageName); 267 } 268 final AndroidPackage pkg; 269 final SharedUserSetting sus; 270 synchronized (mPm.mLock) { 271 pkg = mPm.mPackages.get(packageName); 272 sus = mPm.mSettings.getSharedUserSettingLPr(ps); 273 } 274 275 final AndroidPackage resolvedPkg; 276 if (pkg != null) { 277 resolvedPkg = pkg; 278 } else { 279 // We don't have a parsed package when it lives on an ejected 280 // adopted storage device, so fake something together 281 resolvedPkg = PackageImpl.buildFakeForDeletion(packageName, ps.getVolumeUuid()); 282 } 283 284 int appDataDeletionFlags = FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL 285 | (flags & Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES); 286 // Personal data is preserved if the DELETE_KEEP_DATA flag is on 287 if ((flags & PackageManager.DELETE_KEEP_DATA) != 0) { 288 if ((flags & PackageManager.DELETE_ARCHIVE) != 0) { 289 mAppDataHelper.clearAppDataLIF(resolvedPkg, userId, 290 appDataDeletionFlags | Installer.FLAG_CLEAR_CACHE_ONLY); 291 mAppDataHelper.clearAppDataLIF(resolvedPkg, userId, 292 appDataDeletionFlags | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); 293 } 294 return; 295 } 296 297 // Step 2: destroy app data. 298 mAppDataHelper.destroyAppDataLIF(resolvedPkg, userId, appDataDeletionFlags); 299 if (userId != UserHandle.USER_ALL) { 300 synchronized (mPm.mLock) { 301 ps.setCeDataInode(-1, userId); 302 ps.setDeDataInode(-1, userId); 303 } 304 } 305 306 final PreferredActivityHelper preferredActivityHelper = new PreferredActivityHelper(mPm, 307 mBroadcastHelper); 308 if (userId == UserHandle.USER_ALL) { 309 if (DEBUG_REMOVE) { 310 Slog.d(TAG, "Clear package:" + packageName + " state for all users"); 311 } 312 // Step 3: inform DomainVerificationManager. 313 mPm.mDomainVerificationManager.clearPackage(packageName); 314 synchronized (mPm.mLock) { 315 // Step 3.1 (only for USER_ALL): notify KeySetManagerService. 316 mPm.mSettings.getKeySetManagerService().removeAppKeySetDataLPw(packageName); 317 // Step 3.2 (only for USER_ALL): update installer ownership. 318 mPm.mInjector.getUpdateOwnershipHelper().removeUpdateOwnerDenyList(packageName); 319 // Step 3.3 (only for USER_ALL): update AppsFilter. 320 final Computer snapshot = mPm.snapshotComputer(); 321 mPm.mAppsFilter.removePackage(snapshot, 322 snapshot.getPackageStateInternal(packageName)); 323 // Step 4: clear perferred activities. 324 final SparseBooleanArray changedUsers = new SparseBooleanArray(); 325 mPm.clearPackagePreferredActivitiesLPw( 326 packageName, changedUsers, UserHandle.USER_ALL); 327 mPm.mInjector.getBackgroundHandler().post(() -> { 328 if (changedUsers.size() > 0) { 329 preferredActivityHelper.updateDefaultHomeNotLocked(mPm.snapshotComputer(), 330 changedUsers); 331 mBroadcastHelper.sendPreferredActivityChangedBroadcast(UserHandle.USER_ALL); 332 } 333 }); 334 // Step 5: inform PermissionManager. 335 // This has to be done after the removal from mSettings in removePackageDataLIF. 336 } 337 } else { 338 if (DEBUG_REMOVE) { 339 Slog.d(TAG, "Clear package:" + packageName + " state for user:" + userId); 340 } 341 // Step 3: inform DomainVerificationManager. 342 mPm.mDomainVerificationManager.clearPackageForUser(packageName, userId); 343 // Step 4: clear perferred activities. 344 preferredActivityHelper.clearPackagePreferredActivities(packageName, userId); 345 // Step 5: inform PermissionManager. 346 List<AndroidPackage> sharedUserPkgs = 347 sus != null ? sus.getPackages() : Collections.emptyList(); 348 mPermissionManager.onPackageUninstalled(packageName, ps.getAppId(), ps, pkg, 349 sharedUserPkgs, userId); 350 } 351 352 // Step 6: detroy keystore data. 353 mPm.mInjector.getBackgroundHandler().post(() -> { 354 try { 355 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, 356 "clearKeystoreData:" + ps.getAppId() + " for user: " + userId); 357 mAppDataHelper.clearKeystoreData(userId, ps.getAppId()); 358 } finally { 359 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 360 } 361 }); 362 } 363 364 // Called to clean up disabled system packages removePackageData(final PackageSetting deletedPs, @NonNull int[] allUserHandles)365 public void removePackageData(final PackageSetting deletedPs, @NonNull int[] allUserHandles) { 366 try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { 367 removePackageDataLIF(deletedPs, UserHandle.USER_ALL, allUserHandles, 368 new PackageRemovedInfo(), /* flags= */ 0, /* writeSettings= */ false); 369 } 370 } 371 372 /** 373 * This method deletes the package from internal data structures such as mPackages / mSettings. 374 * 375 * @param targetUserId indicates the target user of the deletion. It equals to 376 * {@link UserHandle#USER_ALL} if the deletion was initiated for all users, 377 * otherwise it equals to the specific user id that the deletion was meant 378 * for. 379 */ 380 @GuardedBy("mPm.mInstallLock") removePackageDataLIF(final PackageSetting deletedPs, @CanBeALL @UserIdInt int targetUserId, @NonNull int[] allUserHandles, @NonNull PackageRemovedInfo outInfo, int flags, boolean writeSettings)381 public void removePackageDataLIF(final PackageSetting deletedPs, 382 @CanBeALL @UserIdInt int targetUserId, @NonNull int[] allUserHandles, 383 @NonNull PackageRemovedInfo outInfo, int flags, boolean writeSettings) { 384 String packageName = deletedPs.getPackageName(); 385 if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + deletedPs); 386 final boolean shouldDeletePackageSetting = 387 shouldDeletePackageSetting(deletedPs, targetUserId, allUserHandles, flags); 388 // Retrieve object to delete permissions for shared user later on 389 final AndroidPackage deletedPkg = deletedPs.getPkg(); 390 391 // Delete all the data and states related to this package. 392 clearPackageStateForUserLIF(deletedPs, 393 shouldDeletePackageSetting ? UserHandle.USER_ALL : targetUserId, flags); 394 395 // Delete from mPackages 396 removePackageLI(packageName, (flags & PackageManager.DELETE_CHATTY) != 0); 397 if (!deletedPs.isSystem()) { 398 // A non-system app's AndroidPackage object has been removed from the service. 399 // Explicitly nullify the corresponding app's PackageSetting's pkg object to 400 // prevent any future usage of it, in case the PackageSetting object will remain because 401 // of DELETE_KEEP_DATA. 402 deletedPs.setPkg(null); 403 } 404 405 if (shouldDeletePackageSetting) { 406 // Delete from mSettings 407 final SparseBooleanArray changedUsers = new SparseBooleanArray(); 408 synchronized (mPm.mLock) { 409 outInfo.mIsAppIdRemoved = mPm.mSettings.removePackageAndAppIdLPw(packageName); 410 if (!mPm.mSettings.isDisabledSystemPackageLPr(packageName)) { 411 final SharedUserSetting sus = mPm.mSettings.getSharedUserSettingLPr(deletedPs); 412 // If we don't have a disabled system package to reinstall, the package is 413 // really gone and its permission state should be removed. 414 final List<AndroidPackage> sharedUserPkgs = 415 sus != null ? sus.getPackages() : Collections.emptyList(); 416 mPermissionManager.onPackageUninstalled(packageName, deletedPs.getAppId(), 417 deletedPs, deletedPkg, sharedUserPkgs, UserHandle.USER_ALL); 418 // After permissions are handled, check if the shared user can be migrated 419 if (sus != null) { 420 mPm.mSettings.checkAndConvertSharedUserSettingsLPw(sus); 421 } 422 } 423 mPm.mSettings.removeRenamedPackageLPw(deletedPs.getRealName()); 424 } 425 } else if (!deletedPs.isSystem() && !outInfo.mIsUpdate 426 && outInfo.mRemovedUsers != null && !deletedPs.isExternalStorage()) { 427 // For non-system uninstalls with DELETE_KEEP_DATA, set the installed state to false 428 // for affected users. This does not apply to app updates where the old apk is replaced 429 // but the old data remains. 430 if (DEBUG_REMOVE) { 431 Slog.d(TAG, "Updating installed state to false because of DELETE_KEEP_DATA"); 432 } 433 final boolean isArchive = (flags & PackageManager.DELETE_ARCHIVE) != 0; 434 final long currentTimeMillis = System.currentTimeMillis(); 435 synchronized (mPm.mLock) { 436 for (int userId : outInfo.mRemovedUsers) { 437 if (DEBUG_REMOVE) { 438 final boolean wasInstalled = deletedPs.getInstalled(userId); 439 Slog.d(TAG, " user " + userId + ": " + wasInstalled + " => " + false); 440 } 441 deletedPs.setInstalled(/* installed= */ false, userId); 442 } 443 444 // Preserve split apk information for downgrade check with DELETE_KEEP_DATA and 445 // archived app cases 446 if (deletedPkg != null && deletedPkg.getSplitNames() != null) { 447 deletedPs.setSplitNames(deletedPkg.getSplitNames()); 448 deletedPs.setSplitRevisionCodes(deletedPkg.getSplitRevisionCodes()); 449 } 450 } 451 } 452 453 // make sure to preserve per-user installed state if this removal was just 454 // a downgrade of a system app to the factory package 455 boolean installedStateChanged = false; 456 if (outInfo.mOrigUsers != null && deletedPs.isSystem()) { 457 if (DEBUG_REMOVE) { 458 Slog.d(TAG, "Propagating install state across downgrade"); 459 } 460 synchronized (mPm.mLock) { 461 for (int userId : allUserHandles) { 462 final boolean installed = ArrayUtils.contains(outInfo.mOrigUsers, userId); 463 if (DEBUG_REMOVE) { 464 Slog.d(TAG, " user " + userId + " => " + installed); 465 } 466 if (installed != deletedPs.getInstalled(userId)) { 467 installedStateChanged = true; 468 } 469 deletedPs.setInstalled(installed, userId); 470 if (installed) { 471 deletedPs.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userId); 472 } 473 } 474 } 475 } 476 synchronized (mPm.mLock) { 477 // can downgrade to reader 478 if (writeSettings) { 479 // Save settings now 480 mPm.writeSettingsLPrTEMP(); 481 } 482 if (installedStateChanged) { 483 mPm.mSettings.writeKernelMappingLPr(deletedPs); 484 } 485 } 486 } 487 shouldDeletePackageSetting(PackageSetting deletedPs, @CanBeALL @UserIdInt int userId, int[] allUserHandles, int flags)488 private static boolean shouldDeletePackageSetting(PackageSetting deletedPs, 489 @CanBeALL @UserIdInt int userId, 490 int[] allUserHandles, int flags) { 491 if ((flags & PackageManager.DELETE_KEEP_DATA) != 0) { 492 return false; 493 } 494 if (userId == UserHandle.USER_ALL) { 495 // Deleting for ALL. Let's wipe the PackageSetting. 496 return true; 497 } 498 if (deletedPs.hasDataOnAnyOtherUser(allUserHandles, userId)) { 499 // We arrived here because we are uninstalling the package for a specified user, and the 500 // package isn't installed on any other user. Before we proceed to completely delete the 501 // PackageSetting from mSettings, let's first check if data exists on any other user. 502 // If so, do not wipe the PackageSetting. 503 return false; 504 } 505 return true; 506 } 507 cleanUpResources(@ullable String packageName, @Nullable File codeFile, @Nullable String[] instructionSets)508 void cleanUpResources(@Nullable String packageName, @Nullable File codeFile, 509 @Nullable String[] instructionSets) { 510 try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { 511 cleanUpResourcesLI(codeFile, instructionSets); 512 } 513 if (packageName == null) { 514 return; 515 } 516 synchronized (mPm.mLock) { 517 PackageSetting ps = mPm.mSettings.getPackageLPr(packageName); 518 if (ps != null) { 519 ps.removeOldPath(codeFile); 520 } 521 } 522 } 523 524 // Need installer lock especially for dex file removal. 525 @GuardedBy("mPm.mInstallLock") cleanUpResourcesLI(@ullable File codeFile, @Nullable String[] instructionSets)526 private void cleanUpResourcesLI(@Nullable File codeFile, @Nullable String[] instructionSets) { 527 // Try enumerating all code paths before deleting 528 List<String> allCodePaths = Collections.EMPTY_LIST; 529 if (codeFile != null && codeFile.exists()) { 530 final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing(); 531 final ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite( 532 input.reset(), codeFile, /* flags */ 0); 533 if (result.isSuccess()) { 534 // Ignore error; we tried our best 535 allCodePaths = result.getResult().getAllApkPaths(); 536 } 537 } 538 539 removeCodePathLI(codeFile); 540 541 // TODO(b/265813358): ART Service currently doesn't support deleting optimized artifacts 542 // relative to an arbitrary APK path. Skip this and rely on its file GC instead. 543 } 544 cleanUpForMoveInstall(String volumeUuid, String packageName, String fromCodePath)545 void cleanUpForMoveInstall(String volumeUuid, String packageName, String fromCodePath) { 546 final String toPathName = new File(fromCodePath).getName(); 547 final File codeFile = new File(Environment.getDataAppDirectory(volumeUuid), toPathName); 548 Slog.d(TAG, "Cleaning up " + packageName + " on " + volumeUuid); 549 final int[] userIds = mPm.mUserManager.getUserIds(); 550 try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) { 551 // Clean up both app data and code 552 // All package moves are frozen until finished 553 554 // We purposefully exclude FLAG_STORAGE_EXTERNAL here, since 555 // this task was only focused on moving data on internal storage. 556 // We don't want ART profiles cleared, because they don't move, 557 // so we would be deleting the only copy (b/149200535). 558 final int flags = FLAG_STORAGE_DE | FLAG_STORAGE_CE 559 | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES; 560 for (int userId : userIds) { 561 try { 562 mPm.mInstaller.destroyAppData(volumeUuid, packageName, userId, flags, 563 0); 564 } catch (Installer.InstallerException e) { 565 Slog.w(TAG, String.valueOf(e)); 566 } 567 } 568 removeCodePathLI(codeFile); 569 } 570 } 571 } 572