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