• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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