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.Flags.disallowSdkLibsToBeApps;
20 import static android.content.pm.PackageManager.APP_METADATA_SOURCE_APK;
21 import static android.content.pm.PackageManager.APP_METADATA_SOURCE_INSTALLER;
22 import static android.content.pm.PackageManager.APP_METADATA_SOURCE_UNKNOWN;
23 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
24 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
25 import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
26 import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_PERMISSION_GROUP;
27 import static android.content.pm.PackageManager.INSTALL_FAILED_DEPRECATED_SDK_VERSION;
28 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
29 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION;
30 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION_GROUP;
31 import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
32 import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
33 import static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
34 import static android.content.pm.PackageManager.INSTALL_FAILED_SESSION_INVALID;
35 import static android.content.pm.PackageManager.INSTALL_FAILED_TEST_ONLY;
36 import static android.content.pm.PackageManager.INSTALL_FAILED_UID_CHANGED;
37 import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
38 import static android.content.pm.PackageManager.INSTALL_STAGED;
39 import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
40 import static android.content.pm.PackageManager.PROPERTY_ANDROID_SAFETY_LABEL;
41 import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN;
42 import static android.content.pm.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V4;
43 import static android.content.pm.parsing.ApkLiteParseUtils.isApkFile;
44 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
45 import static android.os.incremental.IncrementalManager.isIncrementalPath;
46 import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
47 import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
48 import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
49 
50 import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
51 import static com.android.server.pm.PackageManagerException.INTERNAL_ERROR_ARCHIVE_NO_INSTALLER_TITLE;
52 import static com.android.server.pm.PackageManagerService.APP_METADATA_FILE_NAME;
53 import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION;
54 import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
55 import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
56 import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE;
57 import static com.android.server.pm.PackageManagerService.DEBUG_UPGRADE;
58 import static com.android.server.pm.PackageManagerService.DEBUG_VERIFY;
59 import static com.android.server.pm.PackageManagerService.MIN_INSTALLABLE_TARGET_SDK;
60 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
61 import static com.android.server.pm.PackageManagerService.POST_INSTALL;
62 import static com.android.server.pm.PackageManagerService.SCAN_AS_APEX;
63 import static com.android.server.pm.PackageManagerService.SCAN_AS_APK_IN_APEX;
64 import static com.android.server.pm.PackageManagerService.SCAN_AS_FACTORY;
65 import static com.android.server.pm.PackageManagerService.SCAN_AS_FULL_APP;
66 import static com.android.server.pm.PackageManagerService.SCAN_AS_INSTANT_APP;
67 import static com.android.server.pm.PackageManagerService.SCAN_AS_ODM;
68 import static com.android.server.pm.PackageManagerService.SCAN_AS_OEM;
69 import static com.android.server.pm.PackageManagerService.SCAN_AS_PRIVILEGED;
70 import static com.android.server.pm.PackageManagerService.SCAN_AS_PRODUCT;
71 import static com.android.server.pm.PackageManagerService.SCAN_AS_STOPPED_SYSTEM_APP;
72 import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM;
73 import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM_EXT;
74 import static com.android.server.pm.PackageManagerService.SCAN_AS_VENDOR;
75 import static com.android.server.pm.PackageManagerService.SCAN_AS_VIRTUAL_PRELOAD;
76 import static com.android.server.pm.PackageManagerService.SCAN_BOOTING;
77 import static com.android.server.pm.PackageManagerService.SCAN_DONT_KILL_APP;
78 import static com.android.server.pm.PackageManagerService.SCAN_DROP_CACHE;
79 import static com.android.server.pm.PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE;
80 import static com.android.server.pm.PackageManagerService.SCAN_IGNORE_FROZEN;
81 import static com.android.server.pm.PackageManagerService.SCAN_INITIAL;
82 import static com.android.server.pm.PackageManagerService.SCAN_MOVE;
83 import static com.android.server.pm.PackageManagerService.SCAN_NEW_INSTALL;
84 import static com.android.server.pm.PackageManagerService.SCAN_NO_DEX;
85 import static com.android.server.pm.PackageManagerService.SCAN_REQUIRE_KNOWN;
86 import static com.android.server.pm.PackageManagerService.SCAN_UPDATE_SIGNATURE;
87 import static com.android.server.pm.PackageManagerService.TAG;
88 import static com.android.server.pm.PackageManagerServiceUtils.comparePackageSignatures;
89 import static com.android.server.pm.PackageManagerServiceUtils.compareSignatures;
90 import static com.android.server.pm.PackageManagerServiceUtils.compressedFileExists;
91 import static com.android.server.pm.PackageManagerServiceUtils.deriveAbiOverride;
92 import static com.android.server.pm.PackageManagerServiceUtils.extractAppMetadataFromApk;
93 import static com.android.server.pm.PackageManagerServiceUtils.isInstalledByAdb;
94 import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
95 import static com.android.server.pm.PackageManagerServiceUtils.makeDirRecursive;
96 import static com.android.server.pm.SharedUidMigration.BEST_EFFORT;
97 
98 import android.annotation.NonNull;
99 import android.annotation.Nullable;
100 import android.annotation.UserIdInt;
101 import android.apex.ApexInfo;
102 import android.app.AppOpsManager;
103 import android.app.ApplicationExitInfo;
104 import android.app.ApplicationPackageManager;
105 import android.app.BroadcastOptions;
106 import android.app.admin.DevicePolicyManagerInternal;
107 import android.app.backup.IBackupManager;
108 import android.content.ContentResolver;
109 import android.content.Context;
110 import android.content.Intent;
111 import android.content.IntentFilter;
112 import android.content.IntentSender;
113 import android.content.pm.ApplicationInfo;
114 import android.content.pm.ArchivedPackageParcel;
115 import android.content.pm.DataLoaderType;
116 import android.content.pm.Flags;
117 import android.content.pm.PackageInfo;
118 import android.content.pm.PackageInfoLite;
119 import android.content.pm.PackageInstaller;
120 import android.content.pm.PackageManager;
121 import android.content.pm.PermissionGroupInfo;
122 import android.content.pm.PermissionInfo;
123 import android.content.pm.SharedLibraryInfo;
124 import android.content.pm.Signature;
125 import android.content.pm.SigningDetails;
126 import android.content.pm.VerifierInfo;
127 import android.content.pm.dex.DexMetadataHelper;
128 import android.content.pm.parsing.result.ParseResult;
129 import android.content.pm.parsing.result.ParseTypeImpl;
130 import android.net.Uri;
131 import android.os.Binder;
132 import android.os.Build;
133 import android.os.Environment;
134 import android.os.FileUtils;
135 import android.os.Message;
136 import android.os.Process;
137 import android.os.RemoteException;
138 import android.os.SELinux;
139 import android.os.Trace;
140 import android.os.UserHandle;
141 import android.os.UserManager;
142 import android.os.incremental.IncrementalManager;
143 import android.os.incremental.IncrementalStorage;
144 import android.system.ErrnoException;
145 import android.system.Os;
146 import android.text.TextUtils;
147 import android.util.ArrayMap;
148 import android.util.ArraySet;
149 import android.util.EventLog;
150 import android.util.ExceptionUtils;
151 import android.util.Log;
152 import android.util.Pair;
153 import android.util.Slog;
154 import android.util.SparseArray;
155 import android.util.SparseIntArray;
156 
157 import com.android.internal.annotations.GuardedBy;
158 import com.android.internal.content.F2fsUtils;
159 import com.android.internal.pm.parsing.PackageParser2;
160 import com.android.internal.pm.parsing.PackageParserException;
161 import com.android.internal.pm.parsing.pkg.AndroidPackageLegacyUtils;
162 import com.android.internal.pm.parsing.pkg.ParsedPackage;
163 import com.android.internal.pm.pkg.component.ComponentMutateUtils;
164 import com.android.internal.pm.pkg.component.ParsedActivity;
165 import com.android.internal.pm.pkg.component.ParsedInstrumentation;
166 import com.android.internal.pm.pkg.component.ParsedIntentInfo;
167 import com.android.internal.pm.pkg.component.ParsedPermission;
168 import com.android.internal.pm.pkg.component.ParsedPermissionGroup;
169 import com.android.internal.pm.pkg.parsing.ParsingPackageUtils;
170 import com.android.internal.security.VerityUtils;
171 import com.android.internal.util.ArrayUtils;
172 import com.android.internal.util.CollectionUtils;
173 import com.android.server.EventLogTags;
174 import com.android.server.SystemConfig;
175 import com.android.server.art.model.DexoptResult;
176 import com.android.server.criticalevents.CriticalEventLog;
177 import com.android.server.pm.dex.ArtManagerService;
178 import com.android.server.pm.dex.DexManager;
179 import com.android.server.pm.dex.DexoptOptions;
180 import com.android.server.pm.parsing.PackageCacher;
181 import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
182 import com.android.server.pm.permission.Permission;
183 import com.android.server.pm.permission.PermissionManagerServiceInternal;
184 import com.android.server.pm.pkg.AndroidPackage;
185 import com.android.server.pm.pkg.PackageStateInternal;
186 import com.android.server.pm.pkg.SharedLibraryWrapper;
187 import com.android.server.rollback.RollbackManagerInternal;
188 import com.android.server.security.FileIntegrityService;
189 import com.android.server.utils.WatchedArrayMap;
190 import com.android.server.utils.WatchedLongSparseArray;
191 
192 import dalvik.system.VMRuntime;
193 
194 import java.io.File;
195 import java.io.FileInputStream;
196 import java.io.IOException;
197 import java.security.DigestException;
198 import java.security.DigestInputStream;
199 import java.security.MessageDigest;
200 import java.security.NoSuchAlgorithmException;
201 import java.security.PublicKey;
202 import java.security.cert.CertificateException;
203 import java.util.ArrayList;
204 import java.util.Arrays;
205 import java.util.Collections;
206 import java.util.HashSet;
207 import java.util.List;
208 import java.util.Map;
209 import java.util.Set;
210 import java.util.concurrent.ExecutorService;
211 
212 final class InstallPackageHelper {
213     private final PackageManagerService mPm;
214     private final AppDataHelper mAppDataHelper;
215     private final BroadcastHelper mBroadcastHelper;
216     private final RemovePackageHelper mRemovePackageHelper;
217     private final DeletePackageHelper mDeletePackageHelper;
218     private final IncrementalManager mIncrementalManager;
219     private final ApexManager mApexManager;
220     private final DexManager mDexManager;
221     private final ArtManagerService mArtManagerService;
222     private final Context mContext;
223     private final PackageDexOptimizer mPackageDexOptimizer;
224     private final PackageAbiHelper mPackageAbiHelper;
225     private final SharedLibrariesImpl mSharedLibraries;
226     private final PackageManagerServiceInjector mInjector;
227     private final UpdateOwnershipHelper mUpdateOwnershipHelper;
228 
229     // TODO(b/198166813): remove PMS dependency
InstallPackageHelper(PackageManagerService pm, AppDataHelper appDataHelper, RemovePackageHelper removePackageHelper, DeletePackageHelper deletePackageHelper, BroadcastHelper broadcastHelper)230     InstallPackageHelper(PackageManagerService pm,
231                          AppDataHelper appDataHelper,
232                          RemovePackageHelper removePackageHelper,
233                          DeletePackageHelper deletePackageHelper,
234                          BroadcastHelper broadcastHelper) {
235         mPm = pm;
236         mInjector = pm.mInjector;
237         mAppDataHelper = appDataHelper;
238         mBroadcastHelper = broadcastHelper;
239         mRemovePackageHelper = removePackageHelper;
240         mDeletePackageHelper = deletePackageHelper;
241         mIncrementalManager = pm.mInjector.getIncrementalManager();
242         mApexManager = pm.mInjector.getApexManager();
243         mDexManager = pm.mInjector.getDexManager();
244         mArtManagerService = pm.mInjector.getArtManagerService();
245         mContext = pm.mInjector.getContext();
246         mPackageDexOptimizer = pm.mInjector.getPackageDexOptimizer();
247         mPackageAbiHelper = pm.mInjector.getAbiHelper();
248         mSharedLibraries = pm.mInjector.getSharedLibrariesImpl();
249         mUpdateOwnershipHelper = pm.mInjector.getUpdateOwnershipHelper();
250     }
251 
252     /**
253      * Commits the package scan and modifies system state.
254      * <p><em>WARNING:</em> The method may throw an exception in the middle
255      * of committing the package, leaving the system in an inconsistent state.
256      * This needs to be fixed so, once we get to this point, no errors are
257      * possible and the system is not left in an inconsistent state.
258      */
259     @GuardedBy("mPm.mLock")
commitReconciledScanResultLocked( @onNull ReconciledPackage reconciledPkg, int[] allUsers)260     private AndroidPackage commitReconciledScanResultLocked(
261             @NonNull ReconciledPackage reconciledPkg, int[] allUsers) {
262         final InstallRequest request = reconciledPkg.mInstallRequest;
263         // TODO(b/135203078): Move this even further away
264         ParsedPackage parsedPackage = request.getParsedPackage();
265         if (parsedPackage != null && "android".equals(parsedPackage.getPackageName())) {
266             // TODO(b/135203078): Move this to initial parse
267             parsedPackage.setVersionCode(mPm.getSdkVersion())
268                     .setVersionCodeMajor(0);
269         }
270 
271         final @PackageManagerService.ScanFlags int scanFlags = request.getScanFlags();
272         final PackageSetting oldPkgSetting = request.getScanRequestOldPackageSetting();
273         final PackageSetting originalPkgSetting = request.getScanRequestOriginalPackageSetting();
274         final String realPkgName = request.getRealPackageName();
275         final PackageSetting pkgSetting;
276         if (request.getScanRequestPackageSetting() != null) {
277             SharedUserSetting requestSharedUserSetting = mPm.mSettings.getSharedUserSettingLPr(
278                     request.getScanRequestPackageSetting());
279             SharedUserSetting resultSharedUserSetting = mPm.mSettings.getSharedUserSettingLPr(
280                     request.getScannedPackageSetting());
281             if (requestSharedUserSetting != null
282                     && requestSharedUserSetting != resultSharedUserSetting) {
283                 // shared user changed, remove from old shared user
284                 requestSharedUserSetting.removePackage(request.getScanRequestPackageSetting());
285                 // Prune unused SharedUserSetting
286                 if (mPm.mSettings.checkAndPruneSharedUserLPw(requestSharedUserSetting, false)) {
287                     // Set the app ID in removed info for UID_REMOVED broadcasts
288                     request.setRemovedAppId(requestSharedUserSetting.mAppId);
289                 }
290             }
291         }
292         if (request.isExistingSettingCopied()) {
293             pkgSetting = request.getScanRequestPackageSetting();
294             pkgSetting.updateFrom(request.getScannedPackageSetting());
295         } else {
296             pkgSetting = request.getScannedPackageSetting();
297             if (originalPkgSetting != null) {
298                 mPm.mSettings.addRenamedPackageLPw(
299                         AndroidPackageUtils.getRealPackageOrNull(parsedPackage,
300                                 pkgSetting.isSystem()),
301                         originalPkgSetting.getPackageName());
302                 mPm.mTransferredPackages.add(originalPkgSetting.getPackageName());
303             } else {
304                 mPm.mSettings.removeRenamedPackageLPw(parsedPackage.getPackageName());
305             }
306         }
307         SharedUserSetting sharedUserSetting = mPm.mSettings.getSharedUserSettingLPr(pkgSetting);
308         if (sharedUserSetting != null) {
309             sharedUserSetting.addPackage(pkgSetting);
310             if (parsedPackage.isLeavingSharedUser()
311                     && SharedUidMigration.applyStrategy(BEST_EFFORT)
312                     && sharedUserSetting.isSingleUser()) {
313                 // Attempt the transparent shared UID migration
314                 mPm.mSettings.convertSharedUserSettingsLPw(sharedUserSetting);
315             }
316         }
317         if (request.isForceQueryableOverride()) {
318             pkgSetting.setForceQueryableOverride(true);
319         }
320 
321         InstallSource installSource = request.getInstallSource();
322         final boolean isApex = (scanFlags & SCAN_AS_APEX) != 0;
323         final boolean pkgAlreadyExists = oldPkgSetting != null;
324         final String oldUpdateOwner =
325                 pkgAlreadyExists ? oldPkgSetting.getInstallSource().mUpdateOwnerPackageName : null;
326         final String updateOwnerFromSysconfig = isApex || !pkgSetting.isSystem() ? null
327                 : mPm.mInjector.getSystemConfig().getSystemAppUpdateOwnerPackageName(
328                         parsedPackage.getPackageName());
329         final boolean isUpdateOwnershipDenylisted =
330                 mUpdateOwnershipHelper.isUpdateOwnershipDenylisted(parsedPackage.getPackageName());
331         final boolean isUpdateOwnershipEnabled = oldUpdateOwner != null;
332 
333         // For standard install (install via session), the installSource isn't null.
334         if (installSource != null) {
335             // If this is part of a standard install, set the initiating package name, else rely on
336             // previous device state.
337             if (!isInstalledByAdb(installSource.mInitiatingPackageName)) {
338                 final PackageSetting ips = mPm.mSettings.getPackageLPr(
339                         installSource.mInitiatingPackageName);
340                 if (ips != null) {
341                     installSource = installSource.setInitiatingPackageSignatures(
342                             ips.getSignatures());
343                 }
344             }
345 
346             // Handle the update ownership enforcement for APK
347             if (!isApex) {
348                 // User installer UID as "current" userId if present; otherwise, use the userId
349                 // from InstallRequest.
350                 final int userId = installSource.mInstallerPackageUid != Process.INVALID_UID
351                         ? UserHandle.getUserId(installSource.mInstallerPackageUid)
352                         : request.getUserId();
353                 // Whether the parsedPackage is installed on the userId
354                 // If the oldPkgSetting doesn't exist, this package isn't installed for all users.
355                 final boolean isUpdate = pkgAlreadyExists && (userId >= UserHandle.USER_SYSTEM
356                         // If userID >= 0, we could check via oldPkgSetting.getInstalled(userId).
357                         ? oldPkgSetting.getInstalled(userId)
358                         // When userId is -1 (USER_ALL) and it's not installed for any user,
359                         // treat it as not installed.
360                         : oldPkgSetting.getNotInstalledUserIds().length
361                                 <= (UserManager.isHeadlessSystemUserMode() ? 1 : 0));
362                 final boolean isRequestUpdateOwnership = (request.getInstallFlags()
363                         & PackageManager.INSTALL_REQUEST_UPDATE_OWNERSHIP) != 0;
364                 final boolean isSameUpdateOwner =
365                         TextUtils.equals(oldUpdateOwner, installSource.mInstallerPackageName);
366                 final boolean isInstallerUpdateOwnerDenylistProvider =
367                         mUpdateOwnershipHelper.isUpdateOwnershipDenyListProvider(
368                                 installSource.mUpdateOwnerPackageName);
369 
370                 // Here we handle the update owner for the package, and the rules are:
371                 // -. Only enabling update ownership enforcement on initial installation if the
372                 //    installer has requested.
373                 // -. Once the installer changes and users agree to proceed, clear the update
374                 //    owner (package state in other users are taken into account as well).
375                 if (!isUpdate) {
376                     if (!isRequestUpdateOwnership
377                             || isUpdateOwnershipDenylisted
378                             || isInstallerUpdateOwnerDenylistProvider) {
379                         installSource = installSource.setUpdateOwnerPackageName(null);
380                     } else if ((!isUpdateOwnershipEnabled && pkgAlreadyExists)
381                             || (isUpdateOwnershipEnabled && !isSameUpdateOwner)) {
382                         installSource = installSource.setUpdateOwnerPackageName(null);
383                     }
384                 } else if (!isSameUpdateOwner
385                         || !isUpdateOwnershipEnabled) {
386                     installSource = installSource.setUpdateOwnerPackageName(null);
387                 }
388             }
389 
390             pkgSetting.setInstallSource(installSource);
391         // For non-standard install (addForInit), installSource is null.
392         } else if (pkgSetting.isSystem()) {
393             // We still honor the manifest attr if the system app wants to opt-out of it.
394             final boolean isSameUpdateOwner = isUpdateOwnershipEnabled
395                     && TextUtils.equals(oldUpdateOwner, updateOwnerFromSysconfig);
396 
397             // Here we handle the update owner for the system package, and the rules are:
398             // -. We use the update owner from sysconfig as the initial value.
399             // -. Once an app becomes to system app later via OTA, only retains the update
400             //    owner if it's consistence with sysconfig.
401             // -. Clear the update owner when update owner changes from sysconfig.
402             if (!pkgAlreadyExists || isSameUpdateOwner) {
403                 pkgSetting.setUpdateOwnerPackage(updateOwnerFromSysconfig);
404             } else {
405                 pkgSetting.setUpdateOwnerPackage(null);
406             }
407         }
408 
409         if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) {
410             boolean isFactory = (scanFlags & SCAN_AS_FACTORY) != 0;
411             pkgSetting.getPkgState().setApkInUpdatedApex(!isFactory);
412         }
413 
414         pkgSetting.getPkgState().setApexModuleName(request.getApexModuleName());
415 
416         // TODO(toddke): Consider a method specifically for modifying the Package object
417         // post scan; or, moving this stuff out of the Package object since it has nothing
418         // to do with the package on disk.
419         // We need to have this here because addUserToSettingLPw() is sometimes responsible
420         // for creating the application ID. If we did this earlier, we would be saving the
421         // correct ID.
422         parsedPackage.setUid(pkgSetting.getAppId());
423         final AndroidPackage pkg = parsedPackage.hideAsFinal();
424 
425         mPm.mSettings.writeUserRestrictionsLPw(pkgSetting, oldPkgSetting);
426 
427         if (realPkgName != null) {
428             mPm.mTransferredPackages.add(pkg.getPackageName());
429         }
430 
431         if (reconciledPkg.mCollectedSharedLibraryInfos != null
432                 || (oldPkgSetting != null
433                 && !oldPkgSetting.getSharedLibraryDependencies().isEmpty())) {
434             // Reconcile if the new package or the old package uses shared libraries.
435             // It is possible that the old package uses shared libraries but the new one doesn't.
436             mSharedLibraries.executeSharedLibrariesUpdate(pkg, pkgSetting, null, null,
437                     reconciledPkg.mCollectedSharedLibraryInfos, allUsers);
438         }
439 
440         final KeySetManagerService ksms = mPm.mSettings.getKeySetManagerService();
441         if (reconciledPkg.mRemoveAppKeySetData) {
442             ksms.removeAppKeySetDataLPw(pkg.getPackageName());
443         }
444         if (reconciledPkg.mSharedUserSignaturesChanged) {
445             sharedUserSetting.signaturesChanged = Boolean.TRUE;
446             sharedUserSetting.signatures.mSigningDetails = reconciledPkg.mSigningDetails;
447         }
448         pkgSetting.setSigningDetails(reconciledPkg.mSigningDetails);
449 
450         final int userId = request.getUserId();
451         // Modify state for the given package setting
452         commitPackageSettings(pkg, pkgSetting, oldPkgSetting, reconciledPkg);
453         if (pkgSetting.getInstantApp(userId)) {
454             mPm.mInstantAppRegistry.addInstantApp(userId, pkgSetting.getAppId());
455         }
456 
457         if (!IncrementalManager.isIncrementalPath(pkgSetting.getPathString())) {
458             pkgSetting.setLoadingProgress(1f);
459         }
460 
461         // TODO: passes the package name as an argument in a message to the handler for V+
462         //  so we don't need to rely on creating lambda objects so frequently.
463         if (UpdateOwnershipHelper.hasValidOwnershipDenyList(pkgSetting)) {
464             mPm.mHandler.post(() -> handleUpdateOwnerDenyList(pkgSetting));
465         }
466         return pkg;
467     }
468 
handleUpdateOwnerDenyList(PackageSetting pkgSetting)469     private void handleUpdateOwnerDenyList(PackageSetting pkgSetting) {
470         ArraySet<String> listItems = mUpdateOwnershipHelper.readUpdateOwnerDenyList(pkgSetting);
471         if (listItems != null && !listItems.isEmpty()) {
472             mUpdateOwnershipHelper.addToUpdateOwnerDenyList(pkgSetting.getPackageName(),
473                     listItems);
474             SystemConfig config = SystemConfig.getInstance();
475             synchronized (mPm.mLock) {
476                 for (String unownedPackage : listItems) {
477                     PackageSetting unownedSetting = mPm.mSettings.getPackageLPr(unownedPackage);
478                     if (unownedSetting != null
479                             && config.getSystemAppUpdateOwnerPackageName(unownedPackage) == null) {
480                         unownedSetting.setUpdateOwnerPackage(null);
481                     }
482                 }
483             }
484         }
485     }
486 
487     /**
488      * Adds a scanned package to the system. When this method is finished, the package will
489      * be available for query, resolution, etc...
490      */
commitPackageSettings(@onNull AndroidPackage pkg, @NonNull PackageSetting pkgSetting, @Nullable PackageSetting oldPkgSetting, ReconciledPackage reconciledPkg)491     private void commitPackageSettings(@NonNull AndroidPackage pkg,
492             @NonNull PackageSetting pkgSetting, @Nullable PackageSetting oldPkgSetting,
493             ReconciledPackage reconciledPkg) {
494         final String pkgName = pkg.getPackageName();
495         final InstallRequest request = reconciledPkg.mInstallRequest;
496         final AndroidPackage oldPkg = request.getScanRequestOldPackage();
497         final int scanFlags = request.getScanFlags();
498         final boolean chatty = (request.getParseFlags() & ParsingPackageUtils.PARSE_CHATTY) != 0;
499         if (mPm.mCustomResolverComponentName != null
500                 && mPm.mCustomResolverComponentName.getPackageName().equals(pkg.getPackageName())) {
501             mPm.setUpCustomResolverActivity(pkg, pkgSetting);
502         }
503 
504         // When upgrading a package, clear the app metadata file path for the new package.
505         if (oldPkgSetting != null
506                 && oldPkgSetting.getLastUpdateTime() < pkgSetting.getLastUpdateTime()) {
507             pkgSetting.setAppMetadataFilePath(null);
508             pkgSetting.setAppMetadataSource(APP_METADATA_SOURCE_UNKNOWN);
509         }
510         // If the app metadata file path is not null then this is a system app with a preloaded app
511         // metadata file on the system image. Do not reset the path and source if this is the
512         // case.
513         if (pkgSetting.getAppMetadataFilePath() == null) {
514             String dir = pkg.getPath();
515             if (pkgSetting.isSystem()) {
516                 dir = Environment.getDataDirectoryPath() + "/app-metadata/" + pkg.getPackageName();
517             }
518             String appMetadataFilePath = dir + "/" + APP_METADATA_FILE_NAME;
519             if (request.hasAppMetadataFile()) {
520                 pkgSetting.setAppMetadataFilePath(appMetadataFilePath);
521                 if (Flags.aslInApkAppMetadataSource()) {
522                     pkgSetting.setAppMetadataSource(APP_METADATA_SOURCE_INSTALLER);
523                 }
524             } else if (Flags.aslInApkAppMetadataSource()) {
525                 Map<String, PackageManager.Property> properties = pkg.getProperties();
526                 if (properties.containsKey(PROPERTY_ANDROID_SAFETY_LABEL)) {
527                     // ASL file extraction is done in post-install
528                     pkgSetting.setAppMetadataFilePath(appMetadataFilePath);
529                     pkgSetting.setAppMetadataSource(APP_METADATA_SOURCE_APK);
530                 }
531             }
532         }
533 
534         if (pkg.getPackageName().equals("android")) {
535             mPm.setPlatformPackage(pkg, pkgSetting);
536         }
537 
538         // writer
539         ArrayList<AndroidPackage> clientLibPkgs =
540                 mSharedLibraries.commitSharedLibraryChanges(pkg, pkgSetting,
541                         reconciledPkg.mAllowedSharedLibraryInfos,
542                         reconciledPkg.getCombinedAvailablePackages(), scanFlags);
543 
544         request.setLibraryConsumers(clientLibPkgs);
545 
546         if ((scanFlags & SCAN_BOOTING) != 0) {
547             // No apps can run during boot scan, so they don't need to be frozen
548         } else if ((scanFlags & SCAN_DONT_KILL_APP) != 0) {
549             // Caller asked to not kill app, so it's probably not frozen
550         } else if ((scanFlags & SCAN_IGNORE_FROZEN) != 0) {
551             // Caller asked us to ignore frozen check for some reason; they
552             // probably didn't know the package name
553         } else {
554             // We're doing major surgery on this package, so it better be frozen
555             // right now to keep it from launching
556             mPm.snapshotComputer().checkPackageFrozen(pkgName);
557         }
558 
559         final boolean isReplace = request.isInstallReplace();
560         // Also need to kill any apps that are dependent on the library, except the case of
561         // installation of new version static shared library.
562         if (clientLibPkgs != null) {
563             if (pkg.getStaticSharedLibraryName() == null || isReplace) {
564                 for (int i = 0; i < clientLibPkgs.size(); i++) {
565                     AndroidPackage clientPkg = clientLibPkgs.get(i);
566                     String packageName = clientPkg.getPackageName();
567                     mPm.killApplication(packageName,
568                             clientPkg.getUid(), "update lib",
569                             ApplicationExitInfo.REASON_DEPENDENCY_DIED);
570                 }
571             }
572         }
573 
574         // writer
575         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings");
576 
577         synchronized (mPm.mLock) {
578             // We don't expect installation to fail beyond this point
579             // Add the new setting to mSettings
580             mPm.mSettings.insertPackageSettingLPw(pkgSetting, pkg);
581             // Add the new setting to mPackages
582             mPm.mPackages.put(pkg.getPackageName(), pkg);
583             if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) {
584                 mApexManager.registerApkInApex(pkg);
585             }
586 
587             if ((mPm.isDeviceUpgrading() && pkgSetting.isSystem()) || isReplace) {
588                 for (int userId : mPm.mUserManager.getUserIds()) {
589                     pkgSetting.restoreComponentSettings(userId);
590                 }
591             }
592 
593             // Don't add keysets for APEX as their package settings are not persisted and will
594             // result in orphaned keysets.
595             if ((scanFlags & SCAN_AS_APEX) == 0) {
596                 // Add the package's KeySets to the global KeySetManagerService
597                 KeySetManagerService ksms = mPm.mSettings.getKeySetManagerService();
598                 ksms.addScannedPackageLPw(pkg);
599             }
600 
601             final Computer snapshot = mPm.snapshotComputer();
602             mPm.mComponentResolver.addAllComponents(pkg, chatty, mPm.mSetupWizardPackage, snapshot);
603             mPm.mAppsFilter.addPackage(snapshot, pkgSetting, isReplace,
604                     (scanFlags & SCAN_DONT_KILL_APP) != 0 /* retainImplicitGrantOnReplace */);
605             mPm.addAllPackageProperties(pkg);
606 
607             // Only verify app links for non-archival installations, otherwise there won't be any
608             // declared app links.
609             if (!request.isArchived()) {
610                 if (oldPkgSetting == null || oldPkgSetting.getPkg() == null) {
611                     mPm.mDomainVerificationManager.addPackage(pkgSetting,
612                             request.getPreVerifiedDomains());
613                 } else {
614                     mPm.mDomainVerificationManager.migrateState(oldPkgSetting, pkgSetting,
615                             request.getPreVerifiedDomains());
616                 }
617             }
618 
619             int collectionSize = ArrayUtils.size(pkg.getInstrumentations());
620             StringBuilder r = null;
621             int i;
622             for (i = 0; i < collectionSize; i++) {
623                 ParsedInstrumentation a = pkg.getInstrumentations().get(i);
624                 ComponentMutateUtils.setPackageName(a, pkg.getPackageName());
625                 mPm.addInstrumentation(a.getComponentName(), a);
626                 if (chatty) {
627                     if (r == null) {
628                         r = new StringBuilder(256);
629                     } else {
630                         r.append(' ');
631                     }
632                     r.append(a.getName());
633                 }
634             }
635             if (r != null) {
636                 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Instrumentation: " + r);
637             }
638 
639             final List<String> protectedBroadcasts = pkg.getProtectedBroadcasts();
640             if (!protectedBroadcasts.isEmpty()) {
641                 synchronized (mPm.mProtectedBroadcasts) {
642                     mPm.mProtectedBroadcasts.addAll(protectedBroadcasts);
643                 }
644             }
645 
646             mPm.mPermissionManager.onPackageAdded(pkgSetting,
647                     (scanFlags & SCAN_AS_INSTANT_APP) != 0, oldPkg);
648         }
649 
650         Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
651     }
652 
installExistingPackageAsUser(@ullable String packageName, @UserIdInt int userId, @PackageManager.InstallFlags int installFlags, @PackageManager.InstallReason int installReason, @Nullable List<String> allowlistedRestrictedPermissions, @Nullable IntentSender intentSender)653     public Pair<Integer, IntentSender> installExistingPackageAsUser(@Nullable String packageName,
654             @UserIdInt int userId, @PackageManager.InstallFlags int installFlags,
655             @PackageManager.InstallReason int installReason,
656             @Nullable List<String> allowlistedRestrictedPermissions,
657             @Nullable IntentSender intentSender) {
658         if (DEBUG_INSTALL) {
659             Log.v(TAG, "installExistingPackageAsUser package=" + packageName + " userId=" + userId
660                     + " installFlags=" + installFlags + " installReason=" + installReason
661                     + " allowlistedRestrictedPermissions=" + allowlistedRestrictedPermissions);
662         }
663 
664         final int callingUid = Binder.getCallingUid();
665         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES)
666                 != PackageManager.PERMISSION_GRANTED
667                 && mContext.checkCallingOrSelfPermission(
668                 android.Manifest.permission.INSTALL_EXISTING_PACKAGES)
669                 != PackageManager.PERMISSION_GRANTED) {
670             throw new SecurityException("Neither user " + callingUid + " nor current process has "
671                     + android.Manifest.permission.INSTALL_PACKAGES + ".");
672         }
673         PackageSetting pkgSetting;
674         final Computer preLockSnapshot = mPm.snapshotComputer();
675         preLockSnapshot.enforceCrossUserPermission(callingUid, userId,
676                 true /* requireFullPermission */, true /* checkShell */,
677                 "installExistingPackage for user " + userId);
678         if (mPm.isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
679             return Pair.create(PackageManager.INSTALL_FAILED_USER_RESTRICTED, intentSender);
680         }
681 
682         final long callingId = Binder.clearCallingIdentity();
683         try {
684             boolean installed = false;
685             final boolean instantApp =
686                     (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
687             final boolean fullApp =
688                     (installFlags & PackageManager.INSTALL_FULL_APP) != 0;
689 
690             // writer
691             synchronized (mPm.mLock) {
692                 final Computer snapshot = mPm.snapshotComputer();
693                 pkgSetting = mPm.mSettings.getPackageLPr(packageName);
694                 if (pkgSetting == null || pkgSetting.getPkg() == null) {
695                     return Pair.create(PackageManager.INSTALL_FAILED_INVALID_URI, intentSender);
696                 }
697                 if (instantApp && (pkgSetting.isSystem() || pkgSetting.isUpdatedSystemApp())) {
698                     return Pair.create(PackageManager.INSTALL_FAILED_INVALID_URI, intentSender);
699                 }
700                 if (!snapshot.canViewInstantApps(callingUid, UserHandle.getUserId(callingUid))) {
701                     // only allow the existing package to be used if it's installed as a full
702                     // application for at least one user
703                     boolean installAllowed = false;
704                     for (int checkUserId : mPm.mUserManager.getUserIds()) {
705                         installAllowed = !pkgSetting.getInstantApp(checkUserId);
706                         if (installAllowed) {
707                             break;
708                         }
709                     }
710                     if (!installAllowed) {
711                         return Pair.create(PackageManager.INSTALL_FAILED_INVALID_URI, intentSender);
712                     }
713                 }
714                 if (!pkgSetting.getInstalled(userId)) {
715                     pkgSetting.setInstalled(true, userId);
716                     pkgSetting.setHidden(false, userId);
717                     pkgSetting.setInstallReason(installReason, userId);
718                     pkgSetting.setUninstallReason(PackageManager.UNINSTALL_REASON_UNKNOWN, userId);
719                     pkgSetting.setFirstInstallTime(System.currentTimeMillis(), userId);
720                     // Clear any existing archive state.
721                     mPm.mInstallerService.mPackageArchiver.clearArchiveState(pkgSetting, userId);
722                     mPm.mSettings.writePackageRestrictionsLPr(userId);
723                     mPm.mSettings.writeKernelMappingLPr(pkgSetting);
724                     installed = true;
725                 } else if (fullApp && pkgSetting.getInstantApp(userId)) {
726                     // upgrade app from instant to full; we don't allow app downgrade
727                     installed = true;
728                 }
729                 ScanPackageUtils.setInstantAppForUser(mPm.mInjector, pkgSetting, userId, instantApp,
730                         fullApp);
731             }
732 
733             if (installed) {
734                 final String updateOwner = pkgSetting.getInstallSource().mUpdateOwnerPackageName;
735                 final var dpmi = mInjector.getLocalService(DevicePolicyManagerInternal.class);
736                 final boolean isFromManagedUserOrProfile =
737                         dpmi != null && dpmi.isUserOrganizationManaged(userId);
738                 // Here we handle the update owner when install existing package, and the rules are:
739                 // -. Retain the update owner when enable a system app in managed user or profile.
740                 // -. Retain the update owner if the installer is the same.
741                 // -. Clear the update owner when update owner changes.
742                 if (!preLockSnapshot.isCallerSameApp(updateOwner, callingUid)
743                         && (!pkgSetting.isSystem() || !isFromManagedUserOrProfile)) {
744                     pkgSetting.setUpdateOwnerPackage(null);
745                 }
746                 if (pkgSetting.getPkg() != null) {
747                     final PermissionManagerServiceInternal.PackageInstalledParams.Builder
748                             permissionParamsBuilder =
749                             new PermissionManagerServiceInternal.PackageInstalledParams.Builder();
750                     if ((installFlags & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS)
751                             != 0) {
752                         permissionParamsBuilder.setAllowlistedRestrictedPermissions(
753                                 new ArrayList<>(pkgSetting.getPkg().getRequestedPermissions()));
754                     }
755                     mPm.mPermissionManager.onPackageInstalled(pkgSetting.getPkg(),
756                             Process.INVALID_UID /* previousAppId */,
757                             permissionParamsBuilder.build(), userId);
758 
759                     try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
760                         // We don't need to freeze for a brand new install
761                         mAppDataHelper.prepareAppDataPostCommitLIF(
762                                 pkgSetting, /* previousAppId= */0, new int[] { userId });
763                     }
764                 }
765                 // TODO(b/278553670) Store archive state for the user.
766                 boolean isArchived = (pkgSetting.getPkg() == null);
767                 mBroadcastHelper.sendPackageAddedForUser(mPm.snapshotComputer(), packageName,
768                         pkgSetting, userId, isArchived, DataLoaderType.NONE,
769                         mPm.mAppPredictionServicePackage);
770                 synchronized (mPm.mLock) {
771                     mPm.updateSequenceNumberLP(pkgSetting, new int[]{ userId });
772                 }
773                 // start async restore with no post-install since we finish install here
774 
775                 final IntentSender onCompleteSender = intentSender;
776                 intentSender = null;
777 
778                 InstallRequest request = new InstallRequest(userId,
779                         PackageManager.INSTALL_SUCCEEDED, pkgSetting.getPkg(), new int[]{ userId },
780                         () -> {
781                             mPm.restorePermissionsAndUpdateRolesForNewUserInstall(packageName,
782                                     userId);
783                             if (onCompleteSender != null) {
784                                 onInstallComplete(PackageManager.INSTALL_SUCCEEDED, mContext,
785                                         onCompleteSender);
786                             }
787                         }, pkgSetting.getAppId(), callingUid, pkgSetting.isSystem());
788                 restoreAndPostInstall(request);
789             }
790         } finally {
791             Binder.restoreCallingIdentity(callingId);
792         }
793 
794         return Pair.create(PackageManager.INSTALL_SUCCEEDED, intentSender);
795     }
796 
onInstallComplete(int returnCode, Context context, IntentSender target)797     static void onInstallComplete(int returnCode, Context context, IntentSender target) {
798         Intent fillIn = new Intent();
799         fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
800                 PackageManager.installStatusToPublicStatus(returnCode));
801         try {
802             final BroadcastOptions options = BroadcastOptions.makeBasic();
803             options.setPendingIntentBackgroundActivityLaunchAllowed(false);
804             target.sendIntent(context, 0, fillIn, null /* onFinished*/, null /* handler */,
805                     null /* requiredPermission */, options.toBundle());
806         } catch (IntentSender.SendIntentException ignored) {
807         }
808     }
809 
restoreAndPostInstall(InstallRequest request)810     public void restoreAndPostInstall(InstallRequest request) {
811         final int userId = request.getUserId();
812         if (DEBUG_INSTALL) {
813             Log.v(TAG,
814                     "restoreAndPostInstall userId=" + userId + " package=" + request.getPkg());
815         }
816 
817         PackageSetting packageSetting = null;
818 
819         final boolean update = request.isUpdate();
820         boolean doRestore = false;
821         if (request.getPkg() != null && !request.isArchived()) {
822             // A restore should be requested at this point:
823             // if the install succeeded and it's not an archived install
824             if (!update) {
825                 // AND the operation is not an update,
826                 doRestore = true;
827             } else {
828                 // OR the package has never been restored.
829                 String packageName = request.getPkg().getPackageName();
830                 synchronized (mPm.mLock) {
831                     packageSetting = mPm.mSettings.getPackageLPr(packageName);
832                     if (packageSetting != null && packageSetting.isPendingRestore()) {
833                         doRestore = true;
834                     }
835                 }
836             }
837         }
838 
839         // Set up the post-install work request bookkeeping.  This will be used
840         // and cleaned up by the post-install event handling regardless of whether
841         // there's a restore pass performed.  Token values are >= 1.
842         int token;
843         if (mPm.mNextInstallToken < 0) mPm.mNextInstallToken = 1;
844         token = mPm.mNextInstallToken++;
845         mPm.mRunningInstalls.put(token, request);
846 
847         if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
848 
849         final boolean succeeded = request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED;
850         if (succeeded && doRestore) {
851             // Pass responsibility to the Backup Manager.  It will perform a
852             // restore if appropriate, then pass responsibility back to the
853             // Package Manager to run the post-install observer callbacks
854             // and broadcasts.
855             request.closeFreezer();
856             doRestore = performBackupManagerRestore(userId, token, request);
857         }
858 
859         // If this is an update to a package that might be potentially downgraded, then we
860         // need to check with the rollback manager whether there's any userdata that might
861         // need to be snapshotted or restored for the package.
862         //
863         // TODO(narayan): Get this working for cases where userId == UserHandle.USER_ALL.
864         if (succeeded && !doRestore && update) {
865             doRestore = performRollbackManagerRestore(userId, token, request);
866         }
867 
868         if (succeeded && doRestore && !request.hasPostInstallRunnable()) {
869             boolean hasNeverBeenRestored =
870                     packageSetting != null && packageSetting.isPendingRestore();
871             request.setPostInstallRunnable(() -> {
872                 // Permissions should be restored on each user that has the app installed for the
873                 // first time, unless it's an unarchive install for an archived app, in which case
874                 // the permissions should be restored on each user that has the app updated.
875                 int[] userIdsToRestorePermissions = hasNeverBeenRestored
876                         ? request.getUpdateBroadcastUserIds()
877                         : request.getFirstTimeBroadcastUserIds();
878                 for (int restorePermissionUserId : userIdsToRestorePermissions) {
879                     mPm.restorePermissionsAndUpdateRolesForNewUserInstall(request.getName(),
880                             restorePermissionUserId);
881                 }
882             });
883         }
884 
885         if (doRestore) {
886             if (packageSetting != null) {
887                 synchronized (mPm.mLock) {
888                     packageSetting.setPendingRestore(false);
889                 }
890             }
891         } else {
892             // No restore possible, or the Backup Manager was mysteriously not
893             // available -- just fire the post-install work request directly.
894             if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
895 
896             Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall", token);
897 
898             Message msg = mPm.mHandler.obtainMessage(POST_INSTALL, token, 0);
899             mPm.mHandler.sendMessage(msg);
900         }
901     }
902 
903     /**
904      * Perform Backup Manager restore for a given {@link InstallRequest}.
905      * Returns whether the restore successfully completed.
906      */
performBackupManagerRestore(int userId, int token, InstallRequest request)907     private boolean performBackupManagerRestore(int userId, int token, InstallRequest request) {
908         if (request.getPkg() == null) {
909             return false;
910         }
911         IBackupManager iBackupManager = mInjector.getIBackupManager();
912         if (iBackupManager != null) {
913             // For backwards compatibility as USER_ALL previously routed directly to USER_SYSTEM
914             // in the BackupManager. USER_ALL is used in compatibility tests.
915             if (userId == UserHandle.USER_ALL) {
916                 userId = UserHandle.USER_SYSTEM;
917             }
918             if (DEBUG_INSTALL) {
919                 Log.v(TAG, "token " + token + " to BM for possible restore for user " + userId);
920             }
921             Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "restore", token);
922             try {
923                 if (iBackupManager.isUserReadyForBackup(userId)) {
924                     iBackupManager.restoreAtInstallForUser(
925                             userId, request.getPkg().getPackageName(), token);
926                 } else {
927                     Slog.w(TAG, "User " + userId + " is not ready. Restore at install "
928                             + "didn't take place.");
929                     return false;
930                 }
931             } catch (RemoteException e) {
932                 // can't happen; the backup manager is local
933             } catch (Exception e) {
934                 Slog.e(TAG, "Exception trying to enqueue restore", e);
935                 return false;
936             }
937         } else {
938             Slog.e(TAG, "Backup Manager not found!");
939             return false;
940         }
941         return true;
942     }
943 
944     /**
945      * Perform Rollback Manager restore for a given {@link InstallRequest}.
946      * Returns whether the restore successfully completed.
947      */
performRollbackManagerRestore(int userId, int token, InstallRequest request)948     private boolean performRollbackManagerRestore(int userId, int token, InstallRequest request) {
949         if (request.getPkg() == null) {
950             return false;
951         }
952         final String packageName = request.getPkg().getPackageName();
953         final int[] allUsers = mPm.mUserManager.getUserIds();
954         final int[] installedUsers;
955 
956         final PackageSetting ps;
957         int appId = -1;
958         long ceDataInode = -1;
959         synchronized (mPm.mLock) {
960             ps = mPm.mSettings.getPackageLPr(packageName);
961             if (ps != null) {
962                 appId = ps.getAppId();
963                 ceDataInode = ps.getCeDataInode(userId);
964                 // NOTE: We ignore the user specified in the InstallParam because we know this is
965                 // an update, and hence need to restore data for all installed users.
966                 installedUsers = ps.queryInstalledUsers(allUsers, true);
967             } else {
968                 installedUsers = new int[0];
969             }
970         }
971 
972         final int installFlags = request.getInstallFlags();
973         boolean doSnapshotOrRestore = ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0
974                 || (installFlags & PackageManager.INSTALL_REQUEST_DOWNGRADE) != 0);
975 
976         if (ps != null && doSnapshotOrRestore) {
977             final String seInfo = ps.getSeInfo();
978             final RollbackManagerInternal rollbackManager =
979                     mInjector.getLocalService(RollbackManagerInternal.class);
980             rollbackManager.snapshotAndRestoreUserData(packageName,
981                     UserHandle.toUserHandles(installedUsers), appId, ceDataInode, seInfo, token);
982             return true;
983         }
984         return false;
985     }
986 
installPackagesTraced(List<InstallRequest> requests)987     void installPackagesTraced(List<InstallRequest> requests) {
988         try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
989             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
990             installPackagesLI(requests);
991         } finally {
992             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
993         }
994     }
995 
996     /**
997      * Installs one or more packages atomically. This operation is broken up into four phases:
998      * <ul>
999      *     <li><b>Prepare</b>
1000      *         <br/>Analyzes any current install state, parses the package and does initial
1001      *         validation on it.</li>
1002      *     <li><b>Scan</b>
1003      *         <br/>Interrogates the parsed packages given the context collected in prepare.</li>
1004      *     <li><b>Reconcile</b>
1005      *         <br/>Validates scanned packages in the context of each other and the current system
1006      *         state to ensure that the install will be successful.
1007      *     <li><b>Commit</b>
1008      *         <br/>Commits all scanned packages and updates system state. This is the only place
1009      *         that system state may be modified in the install flow and all predictable errors
1010      *         must be determined before this phase.</li>
1011      * </ul>
1012      *
1013      * Failure at any phase will result in a full failure to install all packages.
1014      */
1015     @GuardedBy("mPm.mInstallLock")
installPackagesLI(List<InstallRequest> requests)1016     private void installPackagesLI(List<InstallRequest> requests) {
1017         final Set<String> scannedPackages = new ArraySet<>(requests.size());
1018         final Map<String, Settings.VersionInfo> versionInfos = new ArrayMap<>(requests.size());
1019         final Map<String, Boolean> createdAppId = new ArrayMap<>(requests.size());
1020         CriticalEventLog.getInstance().logInstallPackagesStarted();
1021         boolean success = false;
1022         try {
1023             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI");
1024             for (InstallRequest request : requests) {
1025                 try {
1026                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage");
1027                     request.onPrepareStarted();
1028                     preparePackageLI(request);
1029                 } catch (PrepareFailure prepareFailure) {
1030                     request.setError(prepareFailure.error,
1031                             prepareFailure.getMessage());
1032                     request.setOriginPackage(prepareFailure.mConflictingPackage);
1033                     request.setOriginPermission(prepareFailure.mConflictingPermission);
1034                     return;
1035                 } finally {
1036                     request.onPrepareFinished();
1037                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1038                 }
1039 
1040                 final ParsedPackage packageToScan = request.getParsedPackage();
1041                 if (packageToScan == null) {
1042                     request.setError(INSTALL_FAILED_SESSION_INVALID,
1043                             "Failed to obtain package to scan");
1044                     return;
1045                 }
1046                 request.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
1047                 final String packageName = packageToScan.getPackageName();
1048                 try {
1049                     request.onScanStarted();
1050                     final ScanResult scanResult = scanPackageTracedLI(request.getParsedPackage(),
1051                             request.getParseFlags(), request.getScanFlags(),
1052                             System.currentTimeMillis(), request.getUser(),
1053                             request.getAbiOverride());
1054                     request.setScanResult(scanResult);
1055                     request.onScanFinished();
1056                     if (!scannedPackages.add(packageName)) {
1057                         request.setError(
1058                                 PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE,
1059                                 "Duplicate package "
1060                                         + packageName
1061                                         + " in multi-package install request.");
1062                         return;
1063                     }
1064                     if (!checkNoAppStorageIsConsistent(
1065                             request.getScanRequestOldPackage(), packageToScan)) {
1066                         // TODO: INSTALL_FAILED_UPDATE_INCOMPATIBLE is about incomptabible
1067                         //  signatures. Is there a better error code?
1068                         request.setError(
1069                                 INSTALL_FAILED_UPDATE_INCOMPATIBLE,
1070                                 "Update attempted to change value of "
1071                                         + PackageManager.PROPERTY_NO_APP_DATA_STORAGE);
1072                         return;
1073                     }
1074                     final boolean isApex = (request.getScanFlags() & SCAN_AS_APEX) != 0;
1075                     final boolean isSdkLibrary = packageToScan.isSdkLibrary();
1076                     if (isApex || (isSdkLibrary && disallowSdkLibsToBeApps())) {
1077                         request.getScannedPackageSetting().setAppId(Process.INVALID_UID);
1078                     } else {
1079                         createdAppId.put(packageName, optimisticallyRegisterAppId(request));
1080                     }
1081                     versionInfos.put(packageName,
1082                             mPm.getSettingsVersionForPackage(packageToScan));
1083                 } catch (PackageManagerException e) {
1084                     request.setError("Scanning Failed.", e);
1085                     return;
1086                 }
1087                 if (request.isArchived()) {
1088                     final SparseArray<String> responsibleInstallerTitles =
1089                             PackageArchiver.getResponsibleInstallerTitles(mContext,
1090                                     mPm.snapshotComputer(), request.getInstallSource(),
1091                                     request.getUserId(), mPm.mUserManager.getUserIds());
1092                     if (responsibleInstallerTitles == null
1093                             || responsibleInstallerTitles.size() == 0) {
1094                         request.setError(PackageManagerException.ofInternalError(
1095                                 "Failed to obtain the responsible installer info",
1096                                 INTERNAL_ERROR_ARCHIVE_NO_INSTALLER_TITLE));
1097                         return;
1098                     }
1099                     request.setResponsibleInstallerTitles(responsibleInstallerTitles);
1100                 }
1101             }
1102 
1103             List<ReconciledPackage> reconciledPackages;
1104             synchronized (mPm.mLock) {
1105                 try {
1106                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
1107                     reconciledPackages = ReconcilePackageUtils.reconcilePackages(
1108                             requests, Collections.unmodifiableMap(mPm.mPackages),
1109                             versionInfos, mSharedLibraries, mPm.mSettings.getKeySetManagerService(),
1110                             mPm.mSettings, mPm.mInjector.getSystemConfig());
1111                 } catch (ReconcileFailure e) {
1112                     for (InstallRequest request : requests) {
1113                         request.setError("Reconciliation failed...", e);
1114                     }
1115                     return;
1116                 } finally {
1117                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1118                 }
1119                 if (Flags.improveInstallFreeze()) {
1120                     // Postpone freezer until after reconcile
1121                     for (ReconciledPackage reconciledPkg : reconciledPackages) {
1122                         InstallRequest installRequest = reconciledPkg.mInstallRequest;
1123                         String packageName = installRequest.getParsedPackage().getPackageName();
1124                         PackageFreezer freezer = freezePackageForInstall(packageName,
1125                                 UserHandle.USER_ALL, installRequest.getInstallFlags(),
1126                                 "installPackageLI", ApplicationExitInfo.REASON_PACKAGE_UPDATED,
1127                                 installRequest);
1128                         installRequest.setFreezer(freezer);
1129                     }
1130                 }
1131                 try {
1132                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "commitPackages");
1133                     commitPackagesLocked(reconciledPackages, mPm.mUserManager.getUserIds());
1134                     success = true;
1135                 } finally {
1136                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1137                 }
1138             }
1139             executePostCommitStepsLIF(reconciledPackages);
1140         } finally {
1141             if (success) {
1142                 for (InstallRequest request : requests) {
1143                     if (request.getDataLoaderType() != DataLoaderType.INCREMENTAL) {
1144                         continue;
1145                     }
1146                     if (request.getSignatureSchemeVersion() != SIGNING_BLOCK_V4) {
1147                         continue;
1148                     }
1149                     // For incremental installs, we bypass the verifier prior to install. Now
1150                     // that we know the package is valid, send a notice to the verifier with
1151                     // the root hash of the base.apk.
1152                     final String baseCodePath = request.getPkg().getBaseApkPath();
1153                     final String[] splitCodePaths = request.getPkg().getSplitCodePaths();
1154                     final Uri originUri = request.getOriginUri();
1155                     final int verificationId = mPm.mPendingVerificationToken++;
1156                     final String rootHashString = PackageManagerServiceUtils
1157                             .buildVerificationRootHashString(baseCodePath, splitCodePaths);
1158                     VerificationUtils.broadcastPackageVerified(verificationId, originUri,
1159                             PackageManager.VERIFICATION_ALLOW, rootHashString,
1160                             request.getDataLoaderType(), request.getUser(), mContext);
1161                 }
1162             } else {
1163                 for (InstallRequest installRequest : requests) {
1164                     if (installRequest.getParsedPackage() != null && createdAppId.getOrDefault(
1165                             installRequest.getParsedPackage().getPackageName(), false)) {
1166                         cleanUpAppIdCreation(installRequest);
1167                     }
1168                 }
1169                 // TODO(b/194319951): create a more descriptive reason than unknown
1170                 // mark all non-failure installs as UNKNOWN so we do not treat them as success
1171                 for (InstallRequest request : requests) {
1172                     request.closeFreezer();
1173                     if (request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED) {
1174                         request.setReturnCode(PackageManager.INSTALL_UNKNOWN);
1175                     }
1176                 }
1177             }
1178             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1179         }
1180     }
1181 
1182     @GuardedBy("mPm.mInstallLock")
checkNoAppStorageIsConsistent(AndroidPackage oldPkg, AndroidPackage newPkg)1183     private boolean checkNoAppStorageIsConsistent(AndroidPackage oldPkg, AndroidPackage newPkg) {
1184         if (oldPkg == null) {
1185             // New install, nothing to check against.
1186             return true;
1187         }
1188         final PackageManager.Property curProp =
1189                 oldPkg.getProperties().get(PackageManager.PROPERTY_NO_APP_DATA_STORAGE);
1190         final PackageManager.Property newProp =
1191                 newPkg.getProperties().get(PackageManager.PROPERTY_NO_APP_DATA_STORAGE);
1192         if (curProp == null || !curProp.getBoolean()) {
1193             return newProp == null || !newProp.getBoolean();
1194         }
1195         return newProp != null && newProp.getBoolean();
1196     }
1197 
1198     @GuardedBy("mPm.mInstallLock")
preparePackageLI(InstallRequest request)1199     private void preparePackageLI(InstallRequest request) throws PrepareFailure {
1200         final int[] allUsers =  mPm.mUserManager.getUserIds();
1201         final int installFlags = request.getInstallFlags();
1202         final boolean onExternal = request.getVolumeUuid() != null;
1203         final boolean instantApp = ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0);
1204         final boolean fullApp = ((installFlags & PackageManager.INSTALL_FULL_APP) != 0);
1205         final boolean virtualPreload =
1206                 ((installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
1207         final boolean isApex = ((installFlags & PackageManager.INSTALL_APEX) != 0);
1208         final boolean isRollback =
1209                 request.getInstallReason() == PackageManager.INSTALL_REASON_ROLLBACK;
1210         @PackageManagerService.ScanFlags int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
1211         if (request.isInstallMove()) {
1212             // moving a complete application; perform an initial scan on the new install location
1213             scanFlags |= SCAN_INITIAL;
1214         }
1215         if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) {
1216             scanFlags |= SCAN_DONT_KILL_APP;
1217         }
1218         if (instantApp) {
1219             scanFlags |= SCAN_AS_INSTANT_APP;
1220         }
1221         if (fullApp) {
1222             scanFlags |= SCAN_AS_FULL_APP;
1223         }
1224         if (virtualPreload) {
1225             scanFlags |= SCAN_AS_VIRTUAL_PRELOAD;
1226         }
1227         if (isApex) {
1228             scanFlags |= SCAN_AS_APEX;
1229         }
1230 
1231         final File tmpPackageFile = new File(
1232                 isApex ? request.getApexInfo().modulePath : request.getCodePath());
1233         if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile);
1234 
1235         // Validity check
1236         if (instantApp && onExternal) {
1237             Slog.i(TAG, "Incompatible ephemeral install; external=" + onExternal);
1238             throw new PrepareFailure(PackageManager.INSTALL_FAILED_SESSION_INVALID);
1239         }
1240 
1241         // Retrieve PackageSettings and parse package
1242         @ParsingPackageUtils.ParseFlags final int parseFlags =
1243                 mPm.getDefParseFlags() | ParsingPackageUtils.PARSE_CHATTY
1244                         | ParsingPackageUtils.PARSE_ENFORCE_CODE
1245                         | (onExternal ? ParsingPackageUtils.PARSE_EXTERNAL_STORAGE : 0);
1246 
1247         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
1248         final ParsedPackage parsedPackage;
1249         final ArchivedPackageParcel archivedPackage;
1250         try (PackageParser2 pp = mPm.mInjector.getPreparingPackageParser()) {
1251             if (request.getPackageLite() == null || !request.isArchived()) {
1252                 // TODO: pass packageLite from install request instead of reparsing the package
1253                 parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false);
1254                 AndroidPackageUtils.validatePackageDexMetadata(parsedPackage);
1255                 archivedPackage = null;
1256             } else {
1257                 // Archived install mode, no APK.
1258                 parsedPackage = pp.parsePackageFromPackageLite(request.getPackageLite(),
1259                         parseFlags);
1260                 archivedPackage = request.getPackageLite().getArchivedPackage();
1261             }
1262         } catch (PackageParserException e) {
1263             throw new PrepareFailure(e.error,
1264                     ExceptionUtils.getCompleteMessage("Failed parse during installPackageLI", e));
1265         } finally {
1266             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1267         }
1268 
1269         // Block the install of apps using a lower target SDK version than required.
1270         // This helps improve security and privacy as malware can target older SDK versions
1271         // to avoid enforcement of new API behavior.
1272         boolean bypassLowTargetSdkBlock =
1273                 ((installFlags & PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK) != 0);
1274 
1275         // Skip enforcement when the testOnly flag is set
1276         if (!bypassLowTargetSdkBlock && parsedPackage.isTestOnly()) {
1277             bypassLowTargetSdkBlock = true;
1278         }
1279 
1280         // Enforce the low target sdk install block except when
1281         // the --bypass-low-target-sdk-block is set for the install
1282         if (!bypassLowTargetSdkBlock
1283                 && parsedPackage.getTargetSdkVersion() < MIN_INSTALLABLE_TARGET_SDK) {
1284             Slog.w(TAG, "App " + parsedPackage.getPackageName()
1285                     + " targets deprecated sdk version");
1286             throw new PrepareFailure(INSTALL_FAILED_DEPRECATED_SDK_VERSION,
1287                     "App package must target at least SDK version "
1288                             + MIN_INSTALLABLE_TARGET_SDK + ", but found "
1289                             + parsedPackage.getTargetSdkVersion());
1290         }
1291 
1292         // Instant apps have several additional install-time checks.
1293         if (instantApp) {
1294             if (parsedPackage.getTargetSdkVersion() < Build.VERSION_CODES.O) {
1295                 Slog.w(TAG, "Instant app package " + parsedPackage.getPackageName()
1296                         + " does not target at least O");
1297                 throw new PrepareFailure(INSTALL_FAILED_SESSION_INVALID,
1298                         "Instant app package must target at least O");
1299             }
1300             if (parsedPackage.getSharedUserId() != null) {
1301                 Slog.w(TAG, "Instant app package " + parsedPackage.getPackageName()
1302                         + " may not declare sharedUserId.");
1303                 throw new PrepareFailure(INSTALL_FAILED_SESSION_INVALID,
1304                         "Instant app package may not declare a sharedUserId");
1305             }
1306         }
1307 
1308         if (parsedPackage.isStaticSharedLibrary()) {
1309             // Static shared libraries have synthetic package names
1310             PackageManagerService.renameStaticSharedLibraryPackage(parsedPackage);
1311 
1312             // No static shared libs on external storage
1313             if (onExternal) {
1314                 Slog.i(TAG, "Static shared libs can only be installed on internal storage.");
1315                 throw new PrepareFailure(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
1316                         "Static shared libs can only be installed on internal storage.");
1317             }
1318         }
1319 
1320         String pkgName = parsedPackage.getPackageName();
1321         request.setName(pkgName);
1322         if (parsedPackage.isTestOnly()) {
1323             if ((installFlags & PackageManager.INSTALL_ALLOW_TEST) == 0) {
1324                 throw new PrepareFailure(INSTALL_FAILED_TEST_ONLY,
1325                         "Failed to install test-only apk. Did you forget to add -t?");
1326             }
1327         }
1328 
1329         // either use what we've been given or parse directly from the APK
1330         if (request.getSigningDetails() != SigningDetails.UNKNOWN) {
1331             parsedPackage.setSigningDetails(request.getSigningDetails());
1332         } else {
1333             final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
1334             final ParseResult<SigningDetails> result = ParsingPackageUtils.getSigningDetails(
1335                     input, parsedPackage, false /*skipVerify*/);
1336             if (result.isError()) {
1337                 throw new PrepareFailure("Failed collect during installPackageLI",
1338                         result.getException());
1339             }
1340             parsedPackage.setSigningDetails(result.getResult());
1341         }
1342 
1343         if (instantApp && parsedPackage.getSigningDetails().getSignatureSchemeVersion()
1344                 < SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2) {
1345             Slog.w(TAG, "Instant app package " + parsedPackage.getPackageName()
1346                     + " is not signed with at least APK Signature Scheme v2");
1347             throw new PrepareFailure(INSTALL_FAILED_SESSION_INVALID,
1348                     "Instant app package must be signed with APK Signature Scheme v2 or greater");
1349         }
1350 
1351         boolean systemApp = false;
1352         boolean replace = false;
1353         synchronized (mPm.mLock) {
1354             final PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName);
1355             // Check if installing already existing package
1356             if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
1357                 String oldName = mPm.mSettings.getRenamedPackageLPr(pkgName);
1358                 if (parsedPackage.getOriginalPackages().contains(oldName)
1359                         && mPm.mPackages.containsKey(oldName)) {
1360                     // This package is derived from an original package,
1361                     // and this device has been updating from that original
1362                     // name.  We must continue using the original name, so
1363                     // rename the new package here.
1364                     parsedPackage.setPackageName(oldName);
1365                     pkgName = parsedPackage.getPackageName();
1366                     replace = true;
1367                     if (DEBUG_INSTALL) {
1368                         Slog.d(TAG, "Replacing existing renamed package: oldName="
1369                                 + oldName + " pkgName=" + pkgName);
1370                     }
1371                 } else if (ps != null) {
1372                     // This package, under its official name, already exists
1373                     // on the device; we should replace it.
1374                     replace = true;
1375                     if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing package: " + pkgName);
1376                 }
1377                 if (replace) {
1378                     // Prevent apps opting out from runtime permissions
1379                     final int oldTargetSdk = ps.getTargetSdkVersion();
1380                     final int newTargetSdk = parsedPackage.getTargetSdkVersion();
1381                     if (oldTargetSdk > Build.VERSION_CODES.LOLLIPOP_MR1
1382                             && newTargetSdk <= Build.VERSION_CODES.LOLLIPOP_MR1) {
1383                         throw new PrepareFailure(
1384                                 PackageManager.INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE,
1385                                 "Package " + parsedPackage.getPackageName()
1386                                         + " new target SDK " + newTargetSdk
1387                                         + " doesn't support runtime permissions but the old"
1388                                         + " target SDK " + oldTargetSdk + " does.");
1389                     }
1390                     // Prevent persistent apps from being updated
1391                     if (ps.isPersistent()
1392                             && ((installFlags & PackageManager.INSTALL_STAGED) == 0)) {
1393                         throw new PrepareFailure(PackageManager.INSTALL_FAILED_INVALID_APK,
1394                                 "Package " + pkgName + " is a persistent app. "
1395                                         + "Persistent apps are not updateable.");
1396                     }
1397                 }
1398             }
1399 
1400             PackageSetting signatureCheckPs = ps;
1401 
1402             // SDK libs can have other major versions with different package names.
1403             if (signatureCheckPs == null && parsedPackage.isSdkLibrary()) {
1404                 WatchedLongSparseArray<SharedLibraryInfo> libraryInfos =
1405                         mSharedLibraries.getSharedLibraryInfos(
1406                                 parsedPackage.getSdkLibraryName());
1407                 if (libraryInfos != null && libraryInfos.size() > 0) {
1408                     // Any existing version would do.
1409                     SharedLibraryInfo libraryInfo = libraryInfos.valueAt(0);
1410                     signatureCheckPs = mPm.mSettings.getPackageLPr(libraryInfo.getPackageName());
1411                 }
1412             }
1413 
1414             // Static shared libs have same package with different versions where
1415             // we internally use a synthetic package name to allow multiple versions
1416             // of the same package, therefore we need to compare signatures against
1417             // the package setting for the latest library version.
1418             if (parsedPackage.isStaticSharedLibrary()) {
1419                 SharedLibraryInfo libraryInfo =
1420                         mSharedLibraries.getLatestStaticSharedLibraVersion(parsedPackage);
1421                 if (libraryInfo != null) {
1422                     signatureCheckPs = mPm.mSettings.getPackageLPr(libraryInfo.getPackageName());
1423                 }
1424             }
1425 
1426             if (signatureCheckPs != null) {
1427                 if (DEBUG_INSTALL) {
1428                     Slog.d(TAG,
1429                             "Existing package for signature checking: " + signatureCheckPs);
1430                 }
1431 
1432                 // Quick validity check that we're signed correctly if updating;
1433                 // we'll check this again later when scanning, but we want to
1434                 // bail early here before tripping over redefined permissions.
1435                 final KeySetManagerService ksms = mPm.mSettings.getKeySetManagerService();
1436                 final SharedUserSetting signatureCheckSus = mPm.mSettings.getSharedUserSettingLPr(
1437                         signatureCheckPs);
1438                 if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, signatureCheckSus,
1439                         scanFlags)) {
1440                     if (!ksms.checkUpgradeKeySetLocked(signatureCheckPs, parsedPackage)) {
1441                         throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
1442                                 + parsedPackage.getPackageName() + " upgrade keys do not match the "
1443                                 + "previously installed version");
1444                     }
1445                 } else {
1446                     try {
1447                         final boolean compareCompat =
1448                                 ReconcilePackageUtils.isCompatSignatureUpdateNeeded(
1449                                         mPm.getSettingsVersionForPackage(parsedPackage));
1450                         final boolean compareRecover =
1451                                 ReconcilePackageUtils.isRecoverSignatureUpdateNeeded(
1452                                         mPm.getSettingsVersionForPackage(parsedPackage));
1453                         // We don't care about disabledPkgSetting on install for now.
1454                         final boolean compatMatch =
1455                                 PackageManagerServiceUtils.verifySignatures(signatureCheckPs,
1456                                         signatureCheckSus, null,
1457                                 parsedPackage.getSigningDetails(), compareCompat, compareRecover,
1458                                 isRollback);
1459                         // The new KeySets will be re-added later in the scanning process.
1460                         if (compatMatch) {
1461                             synchronized (mPm.mLock) {
1462                                 ksms.removeAppKeySetDataLPw(parsedPackage.getPackageName());
1463                             }
1464                         }
1465                     } catch (PackageManagerException e) {
1466                         throw new PrepareFailure(e.error, e.getMessage());
1467                     }
1468                 }
1469             }
1470 
1471             if (ps != null) {
1472                 if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);
1473 
1474                 systemApp = ps.isSystem();
1475                 request.setOriginUsers(ps.queryUsersInstalledOrHasData(
1476                         allUsers));
1477             }
1478 
1479             final int numGroups = ArrayUtils.size(parsedPackage.getPermissionGroups());
1480             for (int groupNum = 0; groupNum < numGroups; groupNum++) {
1481                 final ParsedPermissionGroup group =
1482                         parsedPackage.getPermissionGroups().get(groupNum);
1483                 final PermissionGroupInfo sourceGroup = mPm.getPermissionGroupInfo(group.getName(),
1484                         0);
1485 
1486                 if (sourceGroup != null && cannotInstallWithBadPermissionGroups(parsedPackage)) {
1487                     final String sourcePackageName = sourceGroup.packageName;
1488 
1489                     if ((replace || !parsedPackage.getPackageName().equals(sourcePackageName))
1490                             && !doesSignatureMatchForPermissions(sourcePackageName, parsedPackage,
1491                             scanFlags)) {
1492                         EventLog.writeEvent(0x534e4554, "146211400", -1,
1493                                 parsedPackage.getPackageName());
1494 
1495                         throw new PrepareFailure(INSTALL_FAILED_DUPLICATE_PERMISSION_GROUP,
1496                                 "Package "
1497                                         + parsedPackage.getPackageName()
1498                                         + " attempting to redeclare permission group "
1499                                         + group.getName() + " already owned by "
1500                                         + sourcePackageName);
1501                     }
1502                 }
1503             }
1504 
1505             // TODO: Move logic for checking permission compatibility into PermissionManagerService
1506             final int n = ArrayUtils.size(parsedPackage.getPermissions());
1507             for (int i = n - 1; i >= 0; i--) {
1508                 final ParsedPermission perm = parsedPackage.getPermissions().get(i);
1509                 final Permission bp = mPm.mPermissionManager.getPermissionTEMP(perm.getName());
1510 
1511                 // Don't allow anyone but the system to define ephemeral permissions.
1512                 if ((perm.getProtectionLevel() & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0
1513                         && !systemApp) {
1514                     Slog.w(TAG, "Non-System package " + parsedPackage.getPackageName()
1515                             + " attempting to delcare ephemeral permission "
1516                             + perm.getName() + "; Removing ephemeral.");
1517                     ComponentMutateUtils.setProtectionLevel(perm,
1518                             perm.getProtectionLevel() & ~PermissionInfo.PROTECTION_FLAG_INSTANT);
1519                 }
1520 
1521                 // Check whether the newly-scanned package wants to define an already-defined perm
1522                 if (bp != null) {
1523                     final String sourcePackageName = bp.getPackageName();
1524 
1525                     if (!doesSignatureMatchForPermissions(sourcePackageName, parsedPackage,
1526                             scanFlags)) {
1527                         // If the owning package is the system itself, we log but allow
1528                         // install to proceed; we fail the install on all other permission
1529                         // redefinitions.
1530                         if (!sourcePackageName.equals("android")) {
1531                             throw new PrepareFailure(INSTALL_FAILED_DUPLICATE_PERMISSION,
1532                                     "Package "
1533                                             + parsedPackage.getPackageName()
1534                                             + " attempting to redeclare permission "
1535                                             + perm.getName() + " already owned by "
1536                                             + sourcePackageName)
1537                                     .conflictsWithExistingPermission(perm.getName(),
1538                                             sourcePackageName);
1539                         } else {
1540                             Slog.w(TAG, "Package " + parsedPackage.getPackageName()
1541                                     + " attempting to redeclare system permission "
1542                                     + perm.getName() + "; ignoring new declaration");
1543                             parsedPackage.removePermission(i);
1544                         }
1545                     } else if (!PLATFORM_PACKAGE_NAME.equals(parsedPackage.getPackageName())) {
1546                         // Prevent apps to change protection level to dangerous from any other
1547                         // type as this would allow a privilege escalation where an app adds a
1548                         // normal/signature permission in other app's group and later redefines
1549                         // it as dangerous leading to the group auto-grant.
1550                         if ((perm.getProtectionLevel() & PermissionInfo.PROTECTION_MASK_BASE)
1551                                 == PermissionInfo.PROTECTION_DANGEROUS) {
1552                             if (!bp.isRuntime()) {
1553                                 Slog.w(TAG, "Package " + parsedPackage.getPackageName()
1554                                         + " trying to change a non-runtime permission "
1555                                         + perm.getName()
1556                                         + " to runtime; keeping old protection level");
1557                                 ComponentMutateUtils.setProtectionLevel(perm,
1558                                         bp.getProtectionLevel());
1559                             }
1560                         }
1561                     }
1562                 }
1563 
1564                 if (perm.getGroup() != null
1565                         && cannotInstallWithBadPermissionGroups(parsedPackage)) {
1566                     boolean isPermGroupDefinedByPackage = false;
1567                     for (int groupNum = 0; groupNum < numGroups; groupNum++) {
1568                         if (parsedPackage.getPermissionGroups().get(groupNum).getName()
1569                                 .equals(perm.getGroup())) {
1570                             isPermGroupDefinedByPackage = true;
1571                             break;
1572                         }
1573                     }
1574 
1575                     if (!isPermGroupDefinedByPackage) {
1576                         final PermissionGroupInfo sourceGroup =
1577                                 mPm.getPermissionGroupInfo(perm.getGroup(), 0);
1578 
1579                         if (sourceGroup == null) {
1580                             EventLog.writeEvent(0x534e4554, "146211400", -1,
1581                                     parsedPackage.getPackageName());
1582 
1583                             throw new PrepareFailure(INSTALL_FAILED_BAD_PERMISSION_GROUP,
1584                                     "Package "
1585                                             + parsedPackage.getPackageName()
1586                                             + " attempting to declare permission "
1587                                             + perm.getName() + " in non-existing group "
1588                                             + perm.getGroup());
1589                         } else {
1590                             String groupSourcePackageName = sourceGroup.packageName;
1591 
1592                             if (!PLATFORM_PACKAGE_NAME.equals(groupSourcePackageName)
1593                                     && !doesSignatureMatchForPermissions(groupSourcePackageName,
1594                                     parsedPackage, scanFlags)) {
1595                                 EventLog.writeEvent(0x534e4554, "146211400", -1,
1596                                         parsedPackage.getPackageName());
1597 
1598                                 throw new PrepareFailure(INSTALL_FAILED_BAD_PERMISSION_GROUP,
1599                                         "Package "
1600                                                 + parsedPackage.getPackageName()
1601                                                 + " attempting to declare permission "
1602                                                 + perm.getName() + " in group "
1603                                                 + perm.getGroup() + " owned by package "
1604                                                 + groupSourcePackageName
1605                                                 + " with incompatible certificate");
1606                             }
1607                         }
1608                     }
1609                 }
1610             }
1611         }
1612 
1613         if (systemApp) {
1614             if (onExternal) {
1615                 // Abort update; system app can't be replaced with app on sdcard
1616                 throw new PrepareFailure(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
1617                         "Cannot install updates to system apps on sdcard");
1618             } else if (instantApp) {
1619                 // Abort update; system app can't be replaced with an instant app
1620                 throw new PrepareFailure(INSTALL_FAILED_SESSION_INVALID,
1621                         "Cannot update a system app with an instant app");
1622             }
1623         }
1624 
1625         if (request.isInstallMove()) {
1626             // We did an in-place move, so dex is ready to roll
1627             scanFlags |= SCAN_NO_DEX;
1628             scanFlags |= SCAN_MOVE;
1629 
1630             synchronized (mPm.mLock) {
1631                 final PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName);
1632                 if (ps == null) {
1633                     request.setError(PackageManagerException.ofInternalError(
1634                             "Missing settings for moved package " + pkgName,
1635                             PackageManagerException.INTERNAL_ERROR_MISSING_SETTING_FOR_MOVE));
1636                 }
1637 
1638                 // We moved the entire application as-is, so bring over the
1639                 // previously derived ABI information.
1640                 parsedPackage.setPrimaryCpuAbi(ps.getPrimaryCpuAbiLegacy())
1641                         .setSecondaryCpuAbi(ps.getSecondaryCpuAbiLegacy());
1642             }
1643 
1644         } else {
1645             // Enable SCAN_NO_DEX flag to skip dexopt at a later stage
1646             scanFlags |= SCAN_NO_DEX;
1647             // The native libs of Apex is located in apex_payload.img, don't need to parse it from
1648             // the original apex file
1649             if (!isApex) {
1650                 try {
1651                     PackageSetting pkgSetting;
1652                     synchronized (mPm.mLock) {
1653                         pkgSetting = mPm.mSettings.getPackageLPr(pkgName);
1654                     }
1655                     boolean isUpdatedSystemAppFromExistingSetting = pkgSetting != null
1656                             && pkgSetting.isUpdatedSystemApp();
1657                     final String abiOverride = deriveAbiOverride(request.getAbiOverride());
1658 
1659                     // TODO: Are these system flags actually set properly at this stage?
1660                     boolean isUpdatedSystemAppInferred =
1661                             pkgSetting != null && pkgSetting.isSystem();
1662                     // derivePackageAbi works OK for archived packages despite logging some errors.
1663                     final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths>
1664                             derivedAbi = mPackageAbiHelper.derivePackageAbi(parsedPackage,
1665                             systemApp, (isUpdatedSystemAppFromExistingSetting
1666                                     || isUpdatedSystemAppInferred), abiOverride,
1667                             ScanPackageUtils.getAppLib32InstallDir());
1668                     derivedAbi.first.applyTo(parsedPackage);
1669                     derivedAbi.second.applyTo(parsedPackage);
1670                 } catch (PackageManagerException pme) {
1671                     Slog.e(TAG, "Error deriving application ABI", pme);
1672                     throw PrepareFailure.ofInternalError(
1673                             "Error deriving application ABI: " + pme.getMessage(),
1674                             PackageManagerException.INTERNAL_ERROR_DERIVING_ABI);
1675                 }
1676             }
1677         }
1678 
1679         if (!isApex) {
1680             doRenameLI(request, parsedPackage);
1681 
1682             try {
1683                 setUpFsVerity(parsedPackage);
1684             } catch (Installer.InstallerException | IOException | DigestException
1685                     | NoSuchAlgorithmException e) {
1686                 throw PrepareFailure.ofInternalError(
1687                         "Failed to set up verity: " + e,
1688                         PackageManagerException.INTERNAL_ERROR_VERITY_SETUP);
1689             }
1690         } else {
1691             // Use the path returned by apexd
1692             parsedPackage.setPath(request.getApexInfo().modulePath);
1693             parsedPackage.setBaseApkPath(request.getApexInfo().modulePath);
1694         }
1695 
1696         PackageFreezer freezer = null;
1697         if (!Flags.improveInstallFreeze()) {
1698             freezer = freezePackageForInstall(pkgName, UserHandle.USER_ALL, installFlags,
1699                     "installPackageLI", ApplicationExitInfo.REASON_PACKAGE_UPDATED, request);
1700         }
1701 
1702 
1703         boolean shouldCloseFreezerBeforeReturn = true;
1704         try {
1705             final PackageSetting oldPackageState;
1706             final AndroidPackage oldPackage;
1707             String renamedPackage;
1708             boolean sysPkg = false;
1709             int targetScanFlags = scanFlags;
1710             int targetParseFlags = parseFlags;
1711             final PackageSetting ps;
1712             final PackageSetting disabledPs;
1713             final SharedUserSetting sharedUserSetting;
1714             if (replace) {
1715                 final String pkgName11 = parsedPackage.getPackageName();
1716                 synchronized (mPm.mLock) {
1717                     oldPackageState = mPm.mSettings.getPackageLPr(pkgName11);
1718                 }
1719                 oldPackage = oldPackageState.getAndroidPackage();
1720                 if (parsedPackage.isStaticSharedLibrary()) {
1721                     // Static libs have a synthetic package name containing the version
1722                     // and cannot be updated as an update would get a new package name,
1723                     // unless this is installed from adb which is useful for development.
1724                     if (oldPackage != null
1725                             && (installFlags & PackageManager.INSTALL_FROM_ADB) == 0) {
1726                         throw new PrepareFailure(INSTALL_FAILED_DUPLICATE_PACKAGE,
1727                                 "Packages declaring "
1728                                         + "static-shared libs cannot be updated");
1729                     }
1730                 }
1731 
1732                 final boolean isInstantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;
1733 
1734                 final int[] installedUsers;
1735                 final int[] uninstalledUsers;
1736 
1737                 synchronized (mPm.mLock) {
1738                     if (DEBUG_INSTALL) {
1739                         Slog.d(TAG,
1740                                 "replacePackageLI: new=" + parsedPackage
1741                                         + ", old=" + oldPackageState.getName());
1742                     }
1743 
1744                     ps = mPm.mSettings.getPackageLPr(pkgName11);
1745                     disabledPs = mPm.mSettings.getDisabledSystemPkgLPr(ps);
1746                     sharedUserSetting = mPm.mSettings.getSharedUserSettingLPr(ps);
1747 
1748                     // verify signatures are valid
1749                     final KeySetManagerService ksms = mPm.mSettings.getKeySetManagerService();
1750                     if (ksms.shouldCheckUpgradeKeySetLocked(ps, sharedUserSetting, scanFlags)) {
1751                         if (!ksms.checkUpgradeKeySetLocked(ps, parsedPackage)) {
1752                             throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
1753                                     "New package not signed by keys specified by upgrade-keysets: "
1754                                             + pkgName11);
1755                         }
1756                     } else {
1757                         SigningDetails parsedPkgSigningDetails = parsedPackage.getSigningDetails();
1758                         SigningDetails oldPkgSigningDetails = oldPackageState.getSigningDetails();
1759                         // default to original signature matching
1760                         if (!parsedPkgSigningDetails.checkCapability(oldPkgSigningDetails,
1761                                 SigningDetails.CertCapabilities.INSTALLED_DATA)
1762                                 && !oldPkgSigningDetails.checkCapability(parsedPkgSigningDetails,
1763                                 SigningDetails.CertCapabilities.ROLLBACK)) {
1764                             // Allow the update to proceed if this is a rollback and the parsed
1765                             // package's current signing key is the current signer or in the lineage
1766                             // of the old package; this allows a rollback to a previously installed
1767                             // version after an app's signing key has been rotated without requiring
1768                             // the rollback capability on the previous signing key.
1769                             if (!isRollback || !oldPkgSigningDetails.hasAncestorOrSelf(
1770                                     parsedPkgSigningDetails)) {
1771                                 throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
1772                                         "New package has a different signature: " + pkgName11);
1773                             }
1774                         }
1775                     }
1776 
1777                     // don't allow a system upgrade unless the upgrade hash matches
1778                     if (oldPackageState.getRestrictUpdateHash() != null
1779                             && oldPackageState.isSystem()) {
1780                         final byte[] digestBytes;
1781                         try {
1782                             final MessageDigest digest = MessageDigest.getInstance("SHA-512");
1783                             updateDigest(digest, new File(parsedPackage.getBaseApkPath()));
1784                             if (!ArrayUtils.isEmpty(parsedPackage.getSplitCodePaths())) {
1785                                 for (String path : parsedPackage.getSplitCodePaths()) {
1786                                     updateDigest(digest, new File(path));
1787                                 }
1788                             }
1789                             digestBytes = digest.digest();
1790                         } catch (NoSuchAlgorithmException | IOException e) {
1791                             throw new PrepareFailure(INSTALL_FAILED_INVALID_APK,
1792                                     "Could not compute hash: " + pkgName11);
1793                         }
1794                         if (!Arrays.equals(oldPackageState.getRestrictUpdateHash(), digestBytes)) {
1795                             throw new PrepareFailure(INSTALL_FAILED_INVALID_APK,
1796                                     "New package fails restrict-update check: " + pkgName11);
1797                         }
1798                         // retain upgrade restriction
1799                         parsedPackage.setRestrictUpdateHash(
1800                                 oldPackageState.getRestrictUpdateHash());
1801                     }
1802 
1803                     if (oldPackage != null) {
1804                         // APK should not change its sharedUserId declarations
1805                         final var oldSharedUid = oldPackage.getSharedUserId() != null
1806                                 ? oldPackage.getSharedUserId() : "<nothing>";
1807                         final var newSharedUid = parsedPackage.getSharedUserId() != null
1808                                 ? parsedPackage.getSharedUserId() : "<nothing>";
1809                         if (!oldSharedUid.equals(newSharedUid)) {
1810                             throw new PrepareFailure(INSTALL_FAILED_UID_CHANGED,
1811                                     "Package " + parsedPackage.getPackageName()
1812                                             + " shared user changed from "
1813                                             + oldSharedUid + " to " + newSharedUid);
1814                         }
1815 
1816                         // APK should not re-join shared UID
1817                         if (oldPackage.isLeavingSharedUser()
1818                                 && !parsedPackage.isLeavingSharedUser()) {
1819                             throw new PrepareFailure(INSTALL_FAILED_UID_CHANGED,
1820                                     "Package " + parsedPackage.getPackageName()
1821                                             + " attempting to rejoin " + newSharedUid);
1822                         }
1823                     }
1824 
1825                     // In case of rollback, remember per-user/profile install state
1826                     installedUsers = ps.queryInstalledUsers(allUsers, true);
1827                     uninstalledUsers = ps.queryInstalledUsers(allUsers, false);
1828 
1829                     // don't allow an upgrade from full to ephemeral
1830                     if (isInstantApp) {
1831                         if (request.getUserId() == UserHandle.USER_ALL) {
1832                             for (int currentUser : allUsers) {
1833                                 if (!ps.getInstantApp(currentUser)) {
1834                                     // can't downgrade from full to instant
1835                                     Slog.w(TAG,
1836                                             "Can't replace full app with instant app: " + pkgName11
1837                                                     + " for user: " + currentUser);
1838                                     throw new PrepareFailure(
1839                                             PackageManager.INSTALL_FAILED_SESSION_INVALID);
1840                                 }
1841                             }
1842                         } else if (!ps.getInstantApp(request.getUserId())) {
1843                             // can't downgrade from full to instant
1844                             Slog.w(TAG, "Can't replace full app with instant app: " + pkgName11
1845                                     + " for user: " + request.getUserId());
1846                             throw new PrepareFailure(
1847                                     PackageManager.INSTALL_FAILED_SESSION_INVALID);
1848                         }
1849                     }
1850                 }
1851 
1852                 // Update what is removed
1853                 PackageRemovedInfo removedInfo = new PackageRemovedInfo();
1854                 removedInfo.mUid = ps.getAppId();
1855                 removedInfo.mRemovedPackage = ps.getPackageName();
1856                 removedInfo.mInstallerPackageName =
1857                         ps.getInstallSource().mInstallerPackageName;
1858                 removedInfo.mIsStaticSharedLib =
1859                         parsedPackage.getStaticSharedLibraryName() != null;
1860                 removedInfo.mIsUpdate = true;
1861                 removedInfo.mOrigUsers = installedUsers;
1862                 removedInfo.mInstallReasons = new SparseIntArray(installedUsers.length);
1863                 for (int i = 0; i < installedUsers.length; i++) {
1864                     final int userId = installedUsers[i];
1865                     removedInfo.mInstallReasons.put(userId,
1866                             ps.getInstallReason(userId));
1867                 }
1868                 removedInfo.mUninstallReasons = new SparseIntArray(uninstalledUsers.length);
1869                 for (int i = 0; i < uninstalledUsers.length; i++) {
1870                     final int userId = uninstalledUsers[i];
1871                     removedInfo.mUninstallReasons.put(userId,
1872                             ps.getUninstallReason(userId));
1873                 }
1874                 removedInfo.mIsExternal = oldPackageState.isExternalStorage();
1875                 removedInfo.mRemovedPackageVersionCode = oldPackageState.getVersionCode();
1876                 request.setRemovedInfo(removedInfo);
1877 
1878                 sysPkg = oldPackageState.isSystem();
1879                 if (sysPkg) {
1880                     // Set the system/privileged/oem/vendor/product flags as needed
1881                     final boolean privileged = oldPackageState.isPrivileged();
1882                     final boolean oem = oldPackageState.isOem();
1883                     final boolean vendor = oldPackageState.isVendor();
1884                     final boolean product = oldPackageState.isProduct();
1885                     final boolean odm = oldPackageState.isOdm();
1886                     final boolean systemExt = oldPackageState.isSystemExt();
1887                     final @ParsingPackageUtils.ParseFlags int systemParseFlags = parseFlags;
1888                     final @PackageManagerService.ScanFlags int systemScanFlags = scanFlags
1889                             | SCAN_AS_SYSTEM
1890                             | (privileged ? SCAN_AS_PRIVILEGED : 0)
1891                             | (oem ? SCAN_AS_OEM : 0)
1892                             | (vendor ? SCAN_AS_VENDOR : 0)
1893                             | (product ? SCAN_AS_PRODUCT : 0)
1894                             | (odm ? SCAN_AS_ODM : 0)
1895                             | (systemExt ? SCAN_AS_SYSTEM_EXT : 0);
1896 
1897                     if (DEBUG_INSTALL) {
1898                         Slog.d(TAG, "replaceSystemPackageLI: new=" + parsedPackage
1899                                 + ", old=" + oldPackageState.getName());
1900                     }
1901                     request.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
1902                     request.setApexModuleName(oldPackageState.getApexModuleName());
1903                     targetParseFlags = systemParseFlags;
1904                     targetScanFlags = systemScanFlags;
1905                 } else { // non system replace
1906                     if (DEBUG_INSTALL) {
1907                         Slog.d(TAG,
1908                                 "replaceNonSystemPackageLI: new=" + parsedPackage + ", old="
1909                                         + oldPackageState.getName());
1910                     }
1911                 }
1912             } else { // new package install
1913                 ps = null;
1914                 disabledPs = null;
1915                 oldPackageState = null;
1916                 // Remember this for later, in case we need to rollback this install
1917                 String pkgName1 = parsedPackage.getPackageName();
1918 
1919                 if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + parsedPackage);
1920 
1921                 // TODO(b/194319951): MOVE TO RECONCILE
1922                 synchronized (mPm.mLock) {
1923                     renamedPackage = mPm.mSettings.getRenamedPackageLPr(pkgName1);
1924                     if (renamedPackage != null) {
1925                         // A package with the same name is already installed, though
1926                         // it has been renamed to an older name.  The package we
1927                         // are trying to install should be installed as an update to
1928                         // the existing one, but that has not been requested, so bail.
1929                         throw new PrepareFailure(INSTALL_FAILED_ALREADY_EXISTS,
1930                                 "Attempt to re-install " + pkgName1
1931                                         + " without first uninstalling package running as "
1932                                         + renamedPackage);
1933                     }
1934                     if (mPm.mPackages.containsKey(pkgName1)) {
1935                         // Don't allow installation over an existing package with the same name.
1936                         throw new PrepareFailure(INSTALL_FAILED_ALREADY_EXISTS,
1937                                 "Attempt to re-install " + pkgName1
1938                                         + " without first uninstalling.");
1939                     }
1940                 }
1941             }
1942             // we're passing the freezer back to be closed in a later phase of install
1943             shouldCloseFreezerBeforeReturn = false;
1944 
1945             request.setPrepareResult(replace, targetScanFlags, targetParseFlags,
1946                     oldPackageState, parsedPackage, archivedPackage,
1947                     replace /* clearCodeCache */, sysPkg, ps, disabledPs);
1948         } finally {
1949             if (freezer != null) {
1950                 request.setFreezer(freezer);
1951                 if (shouldCloseFreezerBeforeReturn) {
1952                     freezer.close();
1953                 }
1954             }
1955         }
1956     }
1957 
1958     /**
1959      * Rename package into final resting place. All paths on the given
1960      * scanned package should be updated to reflect the rename.
1961      */
1962     @GuardedBy("mPm.mInstallLock")
doRenameLI(InstallRequest request, ParsedPackage parsedPackage)1963     private void doRenameLI(InstallRequest request,
1964             ParsedPackage parsedPackage) throws PrepareFailure {
1965         final int status = request.getReturnCode();
1966         final String statusMsg = request.getReturnMsg();
1967         if (request.isInstallMove()) {
1968             if (status != PackageManager.INSTALL_SUCCEEDED) {
1969                 mRemovePackageHelper.cleanUpForMoveInstall(request.getMoveToUuid(),
1970                         request.getMovePackageName(), request.getMoveFromCodePath());
1971                 throw new PrepareFailure(status, statusMsg);
1972             }
1973             return;
1974         }
1975         // For file installations
1976         if (status != PackageManager.INSTALL_SUCCEEDED) {
1977             mRemovePackageHelper.removeCodePath(request.getCodeFile());
1978             throw new PrepareFailure(status, statusMsg);
1979         }
1980 
1981         final File targetDir = resolveTargetDir(request.getInstallFlags(), request.getCodeFile());
1982         final File beforeCodeFile = request.getCodeFile();
1983         final File afterCodeFile = PackageManagerServiceUtils.getNextCodePath(targetDir,
1984                 parsedPackage.getPackageName());
1985 
1986         if (DEBUG_INSTALL) Slog.d(TAG, "Renaming " + beforeCodeFile + " to " + afterCodeFile);
1987         final boolean onIncremental = mPm.mIncrementalManager != null
1988                 && isIncrementalPath(beforeCodeFile.getAbsolutePath());
1989         try {
1990             makeDirRecursive(afterCodeFile.getParentFile(), 0771);
1991             if (onIncremental) {
1992                 // Just link files here. The stage dir will be removed when the installation
1993                 // session is completed.
1994                 mPm.mIncrementalManager.linkCodePath(beforeCodeFile, afterCodeFile);
1995             } else {
1996                 Os.rename(beforeCodeFile.getAbsolutePath(), afterCodeFile.getAbsolutePath());
1997             }
1998         } catch (IOException | ErrnoException e) {
1999             Slog.w(TAG, "Failed to rename", e);
2000             throw new PrepareFailure(PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE,
2001                     "Failed to rename");
2002         }
2003 
2004         if (!onIncremental && !SELinux.restoreconRecursive(afterCodeFile)) {
2005             Slog.w(TAG, "Failed to restorecon");
2006             throw new PrepareFailure(PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE,
2007                     "Failed to restorecon");
2008         }
2009 
2010         // Reflect the rename internally
2011         request.setCodeFile(afterCodeFile);
2012 
2013         // Reflect the rename in scanned details
2014         try {
2015             parsedPackage.setPath(afterCodeFile.getCanonicalPath());
2016         } catch (IOException e) {
2017             Slog.e(TAG, "Failed to get path: " + afterCodeFile, e);
2018             throw new PrepareFailure(PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE,
2019                     "Failed to get path: " + afterCodeFile);
2020         }
2021         parsedPackage.setBaseApkPath(FileUtils.rewriteAfterRename(beforeCodeFile,
2022                 afterCodeFile, parsedPackage.getBaseApkPath()));
2023         parsedPackage.setSplitCodePaths(FileUtils.rewriteAfterRename(beforeCodeFile,
2024                 afterCodeFile, parsedPackage.getSplitCodePaths()));
2025     }
2026 
2027     // TODO(b/168126411): Once staged install flow starts using the same folder as non-staged
2028     //  flow, we won't need this method anymore.
resolveTargetDir(int installFlags, File codeFile)2029     private File resolveTargetDir(int installFlags, File codeFile) {
2030         boolean isStagedInstall = (installFlags & INSTALL_STAGED) != 0;
2031         if (isStagedInstall) {
2032             return Environment.getDataAppDirectory(null);
2033         } else {
2034             return codeFile.getParentFile();
2035         }
2036     }
2037 
2038     /*
2039      * Cannot properly check CANNOT_INSTALL_WITH_BAD_PERMISSION_GROUPS using CompatChanges
2040      * as this only works for packages that are installed
2041      *
2042      * TODO: Move logic for permission group compatibility into PermissionManagerService
2043      */
2044     @SuppressWarnings("AndroidFrameworkCompatChange")
cannotInstallWithBadPermissionGroups(ParsedPackage parsedPackage)2045     private static boolean cannotInstallWithBadPermissionGroups(ParsedPackage parsedPackage) {
2046         return parsedPackage.getTargetSdkVersion() >= Build.VERSION_CODES.S;
2047     }
2048 
doesSignatureMatchForPermissions(@onNull String sourcePackageName, @NonNull ParsedPackage parsedPackage, int scanFlags)2049     private boolean doesSignatureMatchForPermissions(@NonNull String sourcePackageName,
2050             @NonNull ParsedPackage parsedPackage, int scanFlags) {
2051         // If the defining package is signed with our cert, it's okay.  This
2052         // also includes the "updating the same package" case, of course.
2053         // "updating same package" could also involve key-rotation.
2054 
2055         final PackageSetting sourcePackageSetting;
2056         final KeySetManagerService ksms;
2057         final SharedUserSetting sharedUserSetting;
2058         synchronized (mPm.mLock) {
2059             sourcePackageSetting = mPm.mSettings.getPackageLPr(sourcePackageName);
2060             ksms = mPm.mSettings.getKeySetManagerService();
2061             sharedUserSetting = mPm.mSettings.getSharedUserSettingLPr(sourcePackageSetting);
2062         }
2063 
2064         final SigningDetails sourceSigningDetails = (sourcePackageSetting == null
2065                 ? SigningDetails.UNKNOWN : sourcePackageSetting.getSigningDetails());
2066         if (sourcePackageName.equals(parsedPackage.getPackageName())
2067                 && (ksms.shouldCheckUpgradeKeySetLocked(
2068                         sourcePackageSetting, sharedUserSetting, scanFlags))) {
2069             return ksms.checkUpgradeKeySetLocked(sourcePackageSetting, parsedPackage);
2070         } else {
2071 
2072             // in the event of signing certificate rotation, we need to see if the
2073             // package's certificate has rotated from the current one, or if it is an
2074             // older certificate with which the current is ok with sharing permissions
2075             if (sourceSigningDetails.checkCapability(
2076                     parsedPackage.getSigningDetails(),
2077                     SigningDetails.CertCapabilities.PERMISSION)) {
2078                 return true;
2079             } else if (parsedPackage.getSigningDetails().checkCapability(
2080                     sourceSigningDetails,
2081                     SigningDetails.CertCapabilities.PERMISSION)) {
2082                 // the scanned package checks out, has signing certificate rotation
2083                 // history, and is newer; bring it over
2084                 synchronized (mPm.mLock) {
2085                     sourcePackageSetting.setSigningDetails(parsedPackage.getSigningDetails());
2086                 }
2087                 return true;
2088             } else {
2089                 return false;
2090             }
2091         }
2092     }
2093 
2094     /**
2095      * Set up fs-verity for the given package. For older devices that do not support fs-verity,
2096      * this is a no-op.
2097      */
setUpFsVerity(AndroidPackage pkg)2098     private void setUpFsVerity(AndroidPackage pkg) throws Installer.InstallerException,
2099             PrepareFailure, IOException, DigestException, NoSuchAlgorithmException {
2100         if (!PackageManagerServiceUtils.isApkVerityEnabled()) {
2101             return;
2102         }
2103 
2104         if (isIncrementalPath(pkg.getPath()) && IncrementalManager.getVersion()
2105                 < IncrementalManager.MIN_VERSION_TO_SUPPORT_FSVERITY) {
2106             return;
2107         }
2108 
2109         // Collect files we care for fs-verity setup.
2110         ArrayMap<String, String> fsverityCandidates = new ArrayMap<>();
2111         fsverityCandidates.put(pkg.getBaseApkPath(),
2112                 VerityUtils.getFsveritySignatureFilePath(pkg.getBaseApkPath()));
2113 
2114         final String dmPath = DexMetadataHelper.buildDexMetadataPathForApk(
2115                 pkg.getBaseApkPath());
2116         if (new File(dmPath).exists()) {
2117             fsverityCandidates.put(dmPath, VerityUtils.getFsveritySignatureFilePath(dmPath));
2118         }
2119 
2120         for (String path : pkg.getSplitCodePaths()) {
2121             fsverityCandidates.put(path, VerityUtils.getFsveritySignatureFilePath(path));
2122 
2123             final String splitDmPath = DexMetadataHelper.buildDexMetadataPathForApk(path);
2124             if (new File(splitDmPath).exists()) {
2125                 fsverityCandidates.put(splitDmPath,
2126                         VerityUtils.getFsveritySignatureFilePath(splitDmPath));
2127             }
2128         }
2129 
2130         var fis = FileIntegrityService.getService();
2131         for (Map.Entry<String, String> entry : fsverityCandidates.entrySet()) {
2132             try {
2133                 final String filePath = entry.getKey();
2134                 if (VerityUtils.hasFsverity(filePath)) {
2135                     continue;
2136                 }
2137 
2138                 final String signaturePath = entry.getValue();
2139                 if (new File(signaturePath).exists()) {
2140                     // If signature is provided, enable fs-verity first so that the file can be
2141                     // measured for signature check below.
2142                     VerityUtils.setUpFsverity(filePath);
2143 
2144                     if (!fis.verifyPkcs7DetachedSignature(signaturePath, filePath)) {
2145                         throw new PrepareFailure(PackageManager.INSTALL_FAILED_BAD_SIGNATURE,
2146                                 "fs-verity signature does not verify against a known key");
2147                     }
2148                 }
2149             } catch (IOException e) {
2150                 throw new PrepareFailure(PackageManager.INSTALL_FAILED_BAD_SIGNATURE,
2151                         "Failed to enable fs-verity: " + e);
2152             }
2153         }
2154     }
2155 
freezePackageForInstall(String packageName, int userId, int installFlags, String killReason, int exitInfoReason, InstallRequest request)2156     private PackageFreezer freezePackageForInstall(String packageName, int userId, int installFlags,
2157             String killReason, int exitInfoReason, InstallRequest request) {
2158         if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) {
2159             return new PackageFreezer(mPm, request);
2160         } else {
2161             return mPm.freezePackage(packageName, userId, killReason, exitInfoReason, request);
2162         }
2163     }
2164 
updateDigest(MessageDigest digest, File file)2165     private static void updateDigest(MessageDigest digest, File file) throws IOException {
2166         try (DigestInputStream digestStream =
2167                      new DigestInputStream(new FileInputStream(file), digest)) {
2168             int length, total = 0;
2169             while ((length = digestStream.read()) != -1) {
2170                 total += length;
2171             } // just plow through the file
2172         }
2173     }
2174 
2175     @GuardedBy("mPm.mLock")
commitPackagesLocked(List<ReconciledPackage> reconciledPackages, @NonNull int[] allUsers)2176     private void commitPackagesLocked(List<ReconciledPackage> reconciledPackages,
2177             @NonNull int[] allUsers) {
2178         // TODO: remove any expected failures from this method; this should only be able to fail due
2179         //       to unavoidable errors (I/O, etc.)
2180         for (ReconciledPackage reconciledPkg : reconciledPackages) {
2181             final InstallRequest installRequest = reconciledPkg.mInstallRequest;
2182             final ParsedPackage parsedPackage = installRequest.getParsedPackage();
2183             final String packageName = parsedPackage.getPackageName();
2184 
2185             installRequest.onCommitStarted();
2186             if (installRequest.isInstallReplace()) {
2187                 AndroidPackage oldPackage = mPm.mPackages.get(packageName);
2188 
2189                 // Set the update and install times
2190                 PackageStateInternal deletedPkgSetting = mPm.snapshotComputer()
2191                         .getPackageStateInternal(packageName);
2192                 // TODO(b/225756739): For rebootless APEX, consider using lastUpdateMillis provided
2193                 //  by apexd to be more accurate.
2194                 installRequest.setScannedPackageSettingFirstInstallTimeFromReplaced(
2195                         deletedPkgSetting, allUsers);
2196                 installRequest.setScannedPackageSettingLastUpdateTime(
2197                         System.currentTimeMillis());
2198 
2199                 installRequest.getRemovedInfo().mBroadcastAllowList =
2200                         mPm.mAppsFilter.getVisibilityAllowList(mPm.snapshotComputer(),
2201                                 installRequest.getScannedPackageSetting(),
2202                                 allUsers, mPm.mSettings.getPackagesLocked());
2203                 if (installRequest.isInstallSystem()) {
2204                     // Remove existing system package
2205                     mRemovePackageHelper.removePackage(oldPackage, true);
2206                     if (!disableSystemPackageLPw(oldPackage)) {
2207                         // We didn't need to disable the .apk as a current system package,
2208                         // which means we are replacing another update that is already
2209                         // installed.  We need to make sure to delete the older one's .apk.
2210                         installRequest.getRemovedInfo().mArgs = new CleanUpArgs(
2211                                 packageName,
2212                                 oldPackage.getPath(),
2213                                 getAppDexInstructionSets(
2214                                         deletedPkgSetting.getPrimaryCpuAbi(),
2215                                         deletedPkgSetting.getSecondaryCpuAbi()));
2216                     } else {
2217                         installRequest.getRemovedInfo().mArgs = null;
2218                     }
2219                 } else {
2220                     try {
2221                         // Settings will be written during the call to updateSettingsLI().
2222                         mDeletePackageHelper.executeDeletePackage(
2223                                 reconciledPkg.mDeletePackageAction, packageName,
2224                                 true, allUsers, false);
2225                     } catch (SystemDeleteException e) {
2226                         if (mPm.mIsEngBuild) {
2227                             throw new RuntimeException("Unexpected failure", e);
2228                             // ignore; not possible for non-system app
2229                         }
2230                     }
2231 
2232                     if (installRequest.getReturnCode() == PackageManager.INSTALL_SUCCEEDED) {
2233                         PackageSetting ps2 = mPm.mSettings.getPackageLPr(
2234                                 parsedPackage.getPackageName());
2235                         if (ps2 != null) {
2236                             installRequest.getRemovedInfo().mRemovedForAllUsers =
2237                                     mPm.mPackages.get(ps2.getPackageName()) == null;
2238                         }
2239                     }
2240                 }
2241             }
2242 
2243             AndroidPackage pkg = commitReconciledScanResultLocked(reconciledPkg, allUsers);
2244             updateSettingsLI(pkg, allUsers, installRequest);
2245 
2246             final PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
2247             if (ps != null) {
2248                 installRequest.setNewUsers(
2249                         ps.queryInstalledUsers(allUsers, true));
2250                 ps.setUpdateAvailable(false /*updateAvailable*/);
2251             }
2252             if (installRequest.getReturnCode() == PackageManager.INSTALL_SUCCEEDED) {
2253                 // If this is an archival installation then we'll initialize the archive status,
2254                 // while also marking package as not installed.
2255                 // Doing this at the very end of the install as we are using ps.getInstalled
2256                 // to figure out which users were changed.
2257                 mPm.markPackageAsArchivedIfNeeded(ps,
2258                         installRequest.getArchivedPackage(),
2259                         installRequest.getResponsibleInstallerTitles(),
2260                         installRequest.getNewUsers());
2261                 mPm.updateSequenceNumberLP(ps, installRequest.getNewUsers());
2262                 mPm.updateInstantAppInstallerLocked(packageName);
2263             }
2264             installRequest.onCommitFinished();
2265         }
2266         ApplicationPackageManager.invalidateGetPackagesForUidCache();
2267     }
2268 
2269     @GuardedBy("mPm.mLock")
disableSystemPackageLPw(AndroidPackage oldPkg)2270     private boolean disableSystemPackageLPw(AndroidPackage oldPkg) {
2271         return mPm.mSettings.disableSystemPackageLPw(oldPkg.getPackageName(), true);
2272     }
2273 
updateSettingsLI(AndroidPackage newPackage, int[] allUsers, InstallRequest installRequest)2274     private void updateSettingsLI(AndroidPackage newPackage,
2275             int[] allUsers, InstallRequest installRequest) {
2276         updateSettingsInternalLI(newPackage, allUsers, installRequest);
2277     }
2278 
updateSettingsInternalLI(AndroidPackage pkg, int[] allUsers, InstallRequest installRequest)2279     private void updateSettingsInternalLI(AndroidPackage pkg,
2280             int[] allUsers, InstallRequest installRequest) {
2281         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettingsInternal");
2282 
2283         final String pkgName = pkg.getPackageName();
2284         final int[] installedForUsers = installRequest.getOriginUsers();
2285         final int installReason = installRequest.getInstallReason();
2286         final String installerPackageName = installRequest.getInstallerPackageName();
2287 
2288         if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.getPath());
2289         final int userId = installRequest.getUserId();
2290         if (userId != UserHandle.USER_ALL && userId != UserHandle.USER_CURRENT
2291                 && !mPm.mUserManager.exists(userId)) {
2292             installRequest.setError(PackageManagerException.ofInternalError(
2293                     "User " + userId + " doesn't exist or has been removed",
2294                     PackageManagerException.INTERNAL_ERROR_MISSING_USER));
2295             return;
2296         }
2297         synchronized (mPm.mLock) {
2298             // For system-bundled packages, we assume that installing an upgraded version
2299             // of the package implies that the user actually wants to run that new code,
2300             // so we enable the package.
2301             final PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName);
2302             if (ps != null) {
2303                 if (ps.isSystem()) {
2304                     if (DEBUG_INSTALL) {
2305                         Slog.d(TAG, "Implicitly enabling system package on upgrade: " + pkgName);
2306                     }
2307                     // Enable system package for requested users
2308                     if (installedForUsers != null
2309                             && !installRequest.isApplicationEnabledSettingPersistent()) {
2310                         for (int origUserId : installedForUsers) {
2311                             if (userId == UserHandle.USER_ALL || userId == origUserId) {
2312                                 ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT,
2313                                         origUserId, installerPackageName);
2314                             }
2315                         }
2316                     }
2317                     // Also convey the prior install/uninstall state
2318                     if (allUsers != null && installedForUsers != null) {
2319                         for (int currentUserId : allUsers) {
2320                             final boolean installed = ArrayUtils.contains(
2321                                     installedForUsers, currentUserId);
2322                             if (DEBUG_INSTALL) {
2323                                 Slog.d(TAG, "    user " + currentUserId + " => " + installed);
2324                             }
2325                             ps.setInstalled(installed, currentUserId);
2326                         }
2327                         // these install state changes will be persisted in the
2328                         // upcoming call to mSettings.writeLPr().
2329                     }
2330 
2331                     if (allUsers != null) {
2332                         for (int currentUserId : allUsers) {
2333                             ps.resetOverrideComponentLabelIcon(currentUserId);
2334                         }
2335                     }
2336                 }
2337 
2338                 // Retrieve the overlays for shared libraries of the package.
2339                 if (!ps.getPkgState().getUsesLibraryInfos().isEmpty()) {
2340                     for (SharedLibraryWrapper sharedLib : ps.getPkgState().getUsesLibraryInfos()) {
2341                         for (int currentUserId : allUsers) {
2342                             if (sharedLib.getType() != SharedLibraryInfo.TYPE_DYNAMIC) {
2343                                 // TODO(146804378): Support overlaying static shared libraries
2344                                 continue;
2345                             }
2346                             final PackageSetting libPs = mPm.mSettings.getPackageLPr(
2347                                     sharedLib.getPackageName());
2348                             if (libPs == null) {
2349                                 continue;
2350                             }
2351                             ps.setOverlayPathsForLibrary(sharedLib.getName(),
2352                                     libPs.getOverlayPaths(currentUserId), currentUserId);
2353                         }
2354                     }
2355                 }
2356 
2357                 if (userId != UserHandle.USER_ALL) {
2358                     // It's implied that when a user requests installation, they want the app to
2359                     // be installed and enabled. The caller, however, can explicitly specify to
2360                     // keep the existing enabled state.
2361                     ps.setInstalled(true, userId);
2362                     if (!installRequest.isApplicationEnabledSettingPersistent()) {
2363                         ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userId,
2364                                 installerPackageName);
2365                     }
2366                     // Clear any existing archive state.
2367                     mPm.mInstallerService.mPackageArchiver.clearArchiveState(ps, userId);
2368                 } else if (allUsers != null) {
2369                     // The caller explicitly specified INSTALL_ALL_USERS flag.
2370                     // Thus, updating the settings to install the app for all users.
2371                     for (int currentUserId : allUsers) {
2372                         // If the app is already installed for the currentUser,
2373                         // keep it as installed as we might be updating the app at this place.
2374                         // If not currently installed, check if the currentUser is restricted by
2375                         // DISALLOW_INSTALL_APPS or DISALLOW_DEBUGGING_FEATURES device policy.
2376                         // Install / update the app if the user isn't restricted. Skip otherwise.
2377                         final boolean installedForCurrentUser = ArrayUtils.contains(
2378                                 installedForUsers, currentUserId);
2379                         final boolean restrictedByPolicy =
2380                                 mPm.isUserRestricted(currentUserId,
2381                                         UserManager.DISALLOW_INSTALL_APPS)
2382                                 || mPm.isUserRestricted(currentUserId,
2383                                         UserManager.DISALLOW_DEBUGGING_FEATURES);
2384                         if (installedForCurrentUser || !restrictedByPolicy) {
2385                             ps.setInstalled(true, currentUserId);
2386                             if (!installRequest.isApplicationEnabledSettingPersistent()) {
2387                                 ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, currentUserId,
2388                                         installerPackageName);
2389                             }
2390                             // Clear any existing archive state.
2391                             mPm.mInstallerService.mPackageArchiver.clearArchiveState(ps,
2392                                     currentUserId);
2393                         } else {
2394                             ps.setInstalled(false, currentUserId);
2395                         }
2396                     }
2397                 }
2398 
2399                 mPm.mSettings.addInstallerPackageNames(ps.getInstallSource());
2400 
2401                 // When replacing an existing package, preserve the original install reason for all
2402                 // users that had the package installed before. Similarly for uninstall reasons.
2403                 final Set<Integer> previousUserIds = new ArraySet<>();
2404                 if (installRequest.getRemovedInfo() != null
2405                         && installRequest.getRemovedInfo().mInstallReasons != null) {
2406                     final int installReasonCount =
2407                             installRequest.getRemovedInfo().mInstallReasons.size();
2408                     for (int i = 0; i < installReasonCount; i++) {
2409                         final int previousUserId =
2410                                 installRequest.getRemovedInfo().mInstallReasons.keyAt(i);
2411                         final int previousInstallReason =
2412                                 installRequest.getRemovedInfo().mInstallReasons.valueAt(i);
2413                         ps.setInstallReason(previousInstallReason, previousUserId);
2414                         previousUserIds.add(previousUserId);
2415                     }
2416                 }
2417                 if (installRequest.getRemovedInfo() != null
2418                         && installRequest.getRemovedInfo().mUninstallReasons != null) {
2419                     for (int i = 0; i < installRequest.getRemovedInfo().mUninstallReasons.size();
2420                             i++) {
2421                         final int previousUserId =
2422                                 installRequest.getRemovedInfo().mUninstallReasons.keyAt(i);
2423                         final int previousReason =
2424                                 installRequest.getRemovedInfo().mUninstallReasons.valueAt(i);
2425                         ps.setUninstallReason(previousReason, previousUserId);
2426                     }
2427                 }
2428 
2429                 // Set install reason for users that are having the package newly installed.
2430                 if (userId == UserHandle.USER_ALL) {
2431                     for (int currentUserId : allUsers) {
2432                         if (!previousUserIds.contains(currentUserId)
2433                                 && ps.getInstalled(currentUserId)) {
2434                             ps.setInstallReason(installReason, currentUserId);
2435                         }
2436                     }
2437                 } else if (!previousUserIds.contains(userId)) {
2438                     ps.setInstallReason(installReason, userId);
2439                 }
2440 
2441                 // TODO(b/169721400): generalize Incremental States and create a Callback object
2442                 // that can be used for all the packages.
2443                 final String codePath = ps.getPathString();
2444                 if (IncrementalManager.isIncrementalPath(codePath)
2445                         && mIncrementalManager != null) {
2446                     mIncrementalManager.registerLoadingProgressCallback(codePath,
2447                             new IncrementalProgressListener(ps.getPackageName(), mPm));
2448                 }
2449 
2450                 // Ensure that the uninstall reason is UNKNOWN for users with the package installed.
2451                 for (int currentUserId : allUsers) {
2452                     if (ps.getInstalled(currentUserId)) {
2453                         ps.setUninstallReason(UNINSTALL_REASON_UNKNOWN, currentUserId);
2454                     }
2455                 }
2456 
2457                 mPm.mSettings.writeKernelMappingLPr(ps);
2458 
2459                 final PermissionManagerServiceInternal.PackageInstalledParams.Builder
2460                         permissionParamsBuilder =
2461                         new PermissionManagerServiceInternal.PackageInstalledParams.Builder();
2462                 final boolean grantRequestedPermissions = (installRequest.getInstallFlags()
2463                         & PackageManager.INSTALL_GRANT_ALL_REQUESTED_PERMISSIONS) != 0;
2464                 if (grantRequestedPermissions) {
2465                     var permissionStates = new ArrayMap<String, Integer>();
2466                     for (var permissionName : pkg.getRequestedPermissions()) {
2467                         permissionStates.put(permissionName,
2468                                 PackageInstaller.SessionParams.PERMISSION_STATE_GRANTED);
2469                     }
2470                     permissionParamsBuilder.setPermissionStates(permissionStates);
2471                 } else {
2472                     var permissionStates = installRequest.getPermissionStates();
2473                     if (permissionStates != null) {
2474                         permissionParamsBuilder
2475                                 .setPermissionStates(permissionStates);
2476                     }
2477                 }
2478                 final boolean allowlistAllRestrictedPermissions =
2479                         (installRequest.getInstallFlags()
2480                                 & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) != 0;
2481                 final List<String> allowlistedRestrictedPermissions =
2482                         allowlistAllRestrictedPermissions
2483                                 ? new ArrayList<>(pkg.getRequestedPermissions())
2484                                 : installRequest.getAllowlistedRestrictedPermissions();
2485                 if (allowlistedRestrictedPermissions != null) {
2486                     permissionParamsBuilder.setAllowlistedRestrictedPermissions(
2487                             allowlistedRestrictedPermissions);
2488                 }
2489                 final int autoRevokePermissionsMode = installRequest.getAutoRevokePermissionsMode();
2490                 permissionParamsBuilder.setAutoRevokePermissionsMode(autoRevokePermissionsMode);
2491                 mPm.mPermissionManager.onPackageInstalled(pkg, installRequest.getPreviousAppId(),
2492                         permissionParamsBuilder.build(), userId);
2493             }
2494             installRequest.setName(pkgName);
2495             installRequest.setAppId(pkg.getUid());
2496             installRequest.setPkg(pkg);
2497             installRequest.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
2498             //to update install status
2499             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "writeSettings");
2500             mPm.writeSettingsLPrTEMP();
2501             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
2502         }
2503 
2504         Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
2505     }
2506 
setAccessRestrictedSettingsMode(String pkgName, int appId, int userId, int mode)2507     private void setAccessRestrictedSettingsMode(String pkgName, int appId, int userId, int mode) {
2508         final AppOpsManager appOpsManager = mPm.mContext.getSystemService(AppOpsManager.class);
2509         final int uid = UserHandle.getUid(userId, appId);
2510         appOpsManager.setMode(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
2511                 uid,
2512                 pkgName,
2513                 mode);
2514     }
2515 
2516     /**
2517      * On successful install, executes remaining steps after commit completes and the package lock
2518      * is released. These are typically more expensive or require calls to installd, which often
2519      * locks on {@link com.android.server.pm.PackageManagerService.mLock}.
2520      */
2521     @GuardedBy("mPm.mInstallLock")
executePostCommitStepsLIF(List<ReconciledPackage> reconciledPackages)2522     private void executePostCommitStepsLIF(List<ReconciledPackage> reconciledPackages) {
2523         final ArraySet<IncrementalStorage> incrementalStorages = new ArraySet<>();
2524         for (ReconciledPackage reconciledPkg : reconciledPackages) {
2525             final InstallRequest installRequest = reconciledPkg.mInstallRequest;
2526             final PackageSetting ps = installRequest.getScannedPackageSetting();
2527             final String packageName = ps.getPackageName();
2528             final String codePath = ps.getPathString();
2529             final AndroidPackage pkg = ps.getPkg();
2530             final boolean onIncremental = mIncrementalManager != null
2531                     && isIncrementalPath(codePath);
2532             if (onIncremental) {
2533                 IncrementalStorage storage = mIncrementalManager.openStorage(codePath);
2534                 if (storage == null) {
2535                     throw new IllegalArgumentException(
2536                             "Install: null storage for incremental package " + packageName);
2537                 }
2538                 incrementalStorages.add(storage);
2539             }
2540 
2541             // Hardcode previousAppId to 0 to disable any data migration (http://b/221088088)
2542             mAppDataHelper.prepareAppDataPostCommitLIF(ps, 0, installRequest.getNewUsers());
2543             if (installRequest.isClearCodeCache()) {
2544                 mAppDataHelper.clearAppDataLIF(ps.getPkg(), UserHandle.USER_ALL,
2545                         FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
2546                                 | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
2547             }
2548             if (installRequest.isInstallReplace() && pkg != null) {
2549                 mDexManager.notifyPackageUpdated(packageName,
2550                         pkg.getBaseApkPath(), pkg.getSplitCodePaths());
2551             }
2552 
2553             // Construct the DexoptOptions early to see if we should skip running dexopt.
2554             //
2555             // Do not run PackageDexOptimizer through the local performDexOpt
2556             // method because `pkg` may not be in `mPackages` yet.
2557             //
2558             // Also, don't fail application installs if the dexopt step fails.
2559             DexoptOptions dexoptOptions = DexOptHelper.getDexoptOptionsByInstallRequest(
2560                     installRequest, mDexManager);
2561             // Check whether we need to dexopt the app.
2562             //
2563             // NOTE: it is IMPORTANT to call dexopt:
2564             //   - after doRename which will sync the package data from AndroidPackage and
2565             //     its corresponding ApplicationInfo.
2566             //   - after installNewPackageLIF or replacePackageLIF which will update result with the
2567             //     uid of the application (pkg.applicationInfo.uid).
2568             //     This update happens in place!
2569             //
2570             // We only need to dexopt if the package meets ALL of the following conditions:
2571             //   1) it is not an instant app or if it is then dexopt is enabled via gservices.
2572             //   2) it is not debuggable.
2573             //   3) it is not on Incremental File System.
2574             //
2575             // Note that we do not dexopt instant apps by default. dexopt can take some time to
2576             // complete, so we skip this step during installation. Instead, we'll take extra time
2577             // the first time the instant app starts. It's preferred to do it this way to provide
2578             // continuous progress to the useur instead of mysteriously blocking somewhere in the
2579             // middle of running an instant app. The default behaviour can be overridden
2580             // via gservices.
2581             //
2582             // Furthermore, dexopt may be skipped, depending on the install scenario and current
2583             // state of the device.
2584             //
2585             // TODO(b/174695087): instantApp and onIncremental should be removed and their install
2586             //       path moved to SCENARIO_FAST.
2587 
2588             final boolean performDexopt = DexOptHelper.shouldPerformDexopt(installRequest,
2589                     dexoptOptions, mContext);
2590             if (performDexopt) {
2591                 // dexopt can take long, and ArtService doesn't require installd, so we release
2592                 // the lock here and re-acquire the lock after dexopt is finished.
2593                 PackageManagerTracedLock.RawLock installLock = mPm.mInstallLock.getRawLock();
2594                 installLock.unlock();
2595                 try {
2596                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
2597 
2598                     // This mirrors logic from commitReconciledScanResultLocked, where the library
2599                     // files needed for dexopt are assigned.
2600                     PackageSetting realPkgSetting = installRequest.getRealPackageSetting();
2601 
2602                     // Unfortunately, the updated system app flag is only tracked on this
2603                     // PackageSetting
2604                     boolean isUpdatedSystemApp =
2605                             installRequest.getScannedPackageSetting().isUpdatedSystemApp();
2606 
2607                     realPkgSetting.getPkgState().setUpdatedSystemApp(isUpdatedSystemApp);
2608 
2609                     DexoptResult dexOptResult = DexOptHelper.dexoptPackageUsingArtService(
2610                             installRequest, dexoptOptions);
2611                     installRequest.onDexoptFinished(dexOptResult);
2612                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
2613                 } finally {
2614                     installLock.lock();
2615                 }
2616             }
2617         }
2618         PackageManagerServiceUtils.waitForNativeBinariesExtractionForIncremental(
2619                 incrementalStorages);
2620     }
2621 
verifyReplacingVersionCode(PackageInfoLite pkgLite, long requiredInstalledVersionCode, int installFlags)2622     Pair<Integer, String> verifyReplacingVersionCode(PackageInfoLite pkgLite,
2623             long requiredInstalledVersionCode, int installFlags) {
2624         if ((installFlags & PackageManager.INSTALL_APEX) != 0) {
2625             return verifyReplacingVersionCodeForApex(
2626                     pkgLite, requiredInstalledVersionCode, installFlags);
2627         }
2628 
2629         String packageName = pkgLite.packageName;
2630         synchronized (mPm.mLock) {
2631             // Package which currently owns the data that the new package will own if installed.
2632             // If an app is uninstalled while keeping data (e.g. adb uninstall -k), installedPkg
2633             // will be null whereas dataOwnerPkg will contain information about the package
2634             // which was uninstalled while keeping its data.
2635             AndroidPackage dataOwnerPkg = mPm.mPackages.get(packageName);
2636             PackageSetting dataOwnerPs = mPm.mSettings.getPackageLPr(packageName);
2637             if (dataOwnerPkg  == null) {
2638                 if (dataOwnerPs != null) {
2639                     dataOwnerPkg = dataOwnerPs.getPkg();
2640                 }
2641             }
2642 
2643             if (requiredInstalledVersionCode != PackageManager.VERSION_CODE_HIGHEST) {
2644                 if (dataOwnerPkg == null) {
2645                     String errorMsg = "Required installed version code was "
2646                             + requiredInstalledVersionCode
2647                             + " but package is not installed";
2648                     Slog.w(TAG, errorMsg);
2649                     return Pair.create(
2650                             PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION, errorMsg);
2651                 }
2652 
2653                 if (dataOwnerPkg.getLongVersionCode() != requiredInstalledVersionCode) {
2654                     String errorMsg = "Required installed version code was "
2655                             + requiredInstalledVersionCode
2656                             + " but actual installed version is "
2657                             + dataOwnerPkg.getLongVersionCode();
2658                     Slog.w(TAG, errorMsg);
2659                     return Pair.create(
2660                             PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION, errorMsg);
2661                 }
2662             }
2663 
2664             if (dataOwnerPkg != null && !dataOwnerPkg.isSdkLibrary()) {
2665                 if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags,
2666                         dataOwnerPkg.isDebuggable())) {
2667                     // Downgrade is not permitted; a lower version of the app will not be allowed
2668                     try {
2669                         PackageManagerServiceUtils.checkDowngrade(dataOwnerPkg, pkgLite);
2670                     } catch (PackageManagerException e) {
2671                         String errorMsg = "Downgrade detected: " + e.getMessage();
2672                         Slog.w(TAG, errorMsg);
2673                         return Pair.create(
2674                                 PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg);
2675                     }
2676                 } else if (dataOwnerPs.isSystem()) {
2677                     // Downgrade is permitted, but system apps can't be downgraded below
2678                     // the version preloaded onto the system image
2679                     final PackageSetting disabledPs = mPm.mSettings.getDisabledSystemPkgLPr(
2680                             dataOwnerPs);
2681                     if (disabledPs != null) {
2682                         dataOwnerPkg = disabledPs.getPkg();
2683                     }
2684                     if (!Build.IS_DEBUGGABLE && !dataOwnerPkg.isDebuggable()) {
2685                         // Only restrict non-debuggable builds and non-debuggable version of the app
2686                         try {
2687                             PackageManagerServiceUtils.checkDowngrade(dataOwnerPkg, pkgLite);
2688                         } catch (PackageManagerException e) {
2689                             String errorMsg =
2690                                     "System app: " + packageName + " cannot be downgraded to"
2691                                             + " older than its preloaded version on the system"
2692                                             + " image. " + e.getMessage();
2693                             Slog.w(TAG, errorMsg);
2694                             return Pair.create(
2695                                     PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg);
2696                         }
2697                     }
2698                 }
2699             }
2700         }
2701         return Pair.create(PackageManager.INSTALL_SUCCEEDED, null);
2702     }
2703 
verifyReplacingVersionCodeForApex(PackageInfoLite pkgLite, long requiredInstalledVersionCode, int installFlags)2704     private Pair<Integer, String> verifyReplacingVersionCodeForApex(PackageInfoLite pkgLite,
2705             long requiredInstalledVersionCode, int installFlags) {
2706         String packageName = pkgLite.packageName;
2707 
2708         final PackageInfo activePackage = mPm.snapshotComputer().getPackageInfo(
2709                 packageName, PackageManager.MATCH_APEX, UserHandle.USER_SYSTEM);
2710         if (activePackage == null) {
2711             String errorMsg = "Attempting to install new APEX package " + packageName;
2712             Slog.w(TAG, errorMsg);
2713             return Pair.create(PackageManager.INSTALL_FAILED_PACKAGE_CHANGED, errorMsg);
2714         }
2715 
2716         final long activeVersion = activePackage.getLongVersionCode();
2717         if (requiredInstalledVersionCode != PackageManager.VERSION_CODE_HIGHEST
2718                 && activeVersion != requiredInstalledVersionCode) {
2719             String errorMsg = "Installed version of APEX package " + packageName
2720                     + " does not match required. Active version: " + activeVersion
2721                     + " required: " + requiredInstalledVersionCode;
2722             Slog.w(TAG, errorMsg);
2723             return Pair.create(PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION, errorMsg);
2724         }
2725 
2726         final boolean isAppDebuggable = (activePackage.applicationInfo.flags
2727                 & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
2728         final long newVersionCode = pkgLite.getLongVersionCode();
2729         if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags, isAppDebuggable)
2730                 && newVersionCode < activeVersion) {
2731             String errorMsg = "Downgrade of APEX package " + packageName
2732                     + " is not allowed. Active version: " + activeVersion
2733                     + " attempted: " + newVersionCode;
2734             Slog.w(TAG, errorMsg);
2735             return Pair.create(PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg);
2736         }
2737 
2738         return Pair.create(PackageManager.INSTALL_SUCCEEDED, null);
2739     }
2740 
getUidForVerifier(VerifierInfo verifierInfo)2741     int getUidForVerifier(VerifierInfo verifierInfo) {
2742         synchronized (mPm.mLock) {
2743             final AndroidPackage pkg = mPm.mPackages.get(verifierInfo.packageName);
2744             if (pkg == null) {
2745                 return -1;
2746             } else if (pkg.getSigningDetails().getSignatures().length != 1) {
2747                 Slog.i(TAG, "Verifier package " + verifierInfo.packageName
2748                         + " has more than one signature; ignoring");
2749                 return -1;
2750             }
2751 
2752             /*
2753              * If the public key of the package's signature does not match
2754              * our expected public key, then this is a different package and
2755              * we should skip.
2756              */
2757 
2758             final byte[] expectedPublicKey;
2759             try {
2760                 final Signature verifierSig = pkg.getSigningDetails().getSignatures()[0];
2761                 final PublicKey publicKey = verifierSig.getPublicKey();
2762                 expectedPublicKey = publicKey.getEncoded();
2763             } catch (CertificateException e) {
2764                 return -1;
2765             }
2766 
2767             final byte[] actualPublicKey = verifierInfo.publicKey.getEncoded();
2768 
2769             if (!Arrays.equals(actualPublicKey, expectedPublicKey)) {
2770                 Slog.i(TAG, "Verifier package " + verifierInfo.packageName
2771                         + " does not have the expected public key; ignoring");
2772                 return -1;
2773             }
2774 
2775             return pkg.getUid();
2776         }
2777     }
2778 
sendPendingBroadcasts()2779     public void sendPendingBroadcasts() {
2780         String[] packages;
2781         ArrayList<String>[] components;
2782         int numBroadcasts = 0, numUsers;
2783         int[] uids;
2784 
2785         synchronized (mPm.mLock) {
2786             final SparseArray<ArrayMap<String, ArrayList<String>>> userIdToPackagesToComponents =
2787                     mPm.mPendingBroadcasts.copiedMap();
2788             numUsers = userIdToPackagesToComponents.size();
2789             for (int n = 0; n < numUsers; n++) {
2790                 numBroadcasts += userIdToPackagesToComponents.valueAt(n).size();
2791             }
2792             if (numBroadcasts == 0) {
2793                 // Nothing to be done. Just return
2794                 return;
2795             }
2796             packages = new String[numBroadcasts];
2797             components = new ArrayList[numBroadcasts];
2798             uids = new int[numBroadcasts];
2799             int i = 0;  // filling out the above arrays
2800 
2801             for (int n = 0; n < numUsers; n++) {
2802                 final int packageUserId = userIdToPackagesToComponents.keyAt(n);
2803                 final ArrayMap<String, ArrayList<String>> componentsToBroadcast =
2804                         userIdToPackagesToComponents.valueAt(n);
2805                 final int numComponents = CollectionUtils.size(componentsToBroadcast);
2806                 for (int index = 0; index < numComponents; index++) {
2807                     packages[i] = componentsToBroadcast.keyAt(index);
2808                     components[i] = componentsToBroadcast.valueAt(index);
2809                     final PackageSetting ps = mPm.mSettings.getPackageLPr(packages[i]);
2810                     uids[i] = (ps != null)
2811                             ? UserHandle.getUid(packageUserId, ps.getAppId())
2812                             : -1;
2813                     i++;
2814                 }
2815             }
2816             numBroadcasts = i;
2817             mPm.mPendingBroadcasts.clear();
2818         }
2819         final Computer snapshot = mPm.snapshotComputer();
2820         // Send broadcasts
2821         for (int i = 0; i < numBroadcasts; i++) {
2822             mBroadcastHelper.sendPackageChangedBroadcast(snapshot, packages[i],
2823                     true /* dontKillApp */, components[i], uids[i], null /* reason */);
2824         }
2825     }
2826 
handlePackagePostInstall(InstallRequest request, boolean launchedForRestore)2827     void handlePackagePostInstall(InstallRequest request, boolean launchedForRestore) {
2828         final boolean killApp =
2829                 (request.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) == 0;
2830         final boolean succeeded = request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED;
2831         final boolean update = request.isUpdate();
2832         final boolean archived = request.isArchived();
2833         final String packageName = request.getName();
2834         final Computer snapshot = mPm.snapshotComputer();
2835         final PackageStateInternal pkgSetting =
2836                 succeeded ? snapshot.getPackageStateInternal(packageName) : null;
2837         final boolean removedBeforeUpdate = (pkgSetting == null)
2838                 || (pkgSetting.isSystem() && !pkgSetting.getPath().getPath().equals(
2839                 request.getPkg().getPath()));
2840         if (succeeded && removedBeforeUpdate) {
2841             Slog.e(TAG, packageName + " was removed before handlePackagePostInstall "
2842                     + "could be executed");
2843             request.setReturnCode(INSTALL_FAILED_PACKAGE_CHANGED);
2844             request.setReturnMessage("Package was removed before install could complete.");
2845 
2846             // Remove the update failed package's older resources safely now
2847             mRemovePackageHelper.cleanUpResources(packageName, request.getOldCodeFile(),
2848                     request.getOldInstructionSet());
2849             mPm.notifyInstallObserver(request);
2850             return;
2851         }
2852 
2853         if (succeeded) {
2854             if (Flags.aslInApkAppMetadataSource()
2855                     && pkgSetting.getAppMetadataSource() == APP_METADATA_SOURCE_APK) {
2856                 if (!extractAppMetadataFromApk(request.getPkg(),
2857                         pkgSetting.getAppMetadataFilePath(), pkgSetting.isSystem())) {
2858                     synchronized (mPm.mLock) {
2859                         PackageSetting setting = mPm.mSettings.getPackageLPr(packageName);
2860                         if (setting != null) {
2861                             setting.setAppMetadataFilePath(null)
2862                                     .setAppMetadataSource(APP_METADATA_SOURCE_UNKNOWN);
2863                         }
2864                     }
2865                 }
2866             }
2867 
2868             // Clear the uid cache after we installed a new package.
2869             mPm.mPerUidReadTimeoutsCache = null;
2870 
2871             mPm.notifyInstantAppPackageInstalled(request.getPkg().getPackageName(),
2872                     request.getNewUsers());
2873 
2874             final int[] firstUserIds = request.getFirstTimeBroadcastUserIds();
2875 
2876             if (request.getPkg().getStaticSharedLibraryName() == null) {
2877                 mPm.mProcessLoggingHandler.invalidateBaseApkHash(request.getPkg().getBaseApkPath());
2878             }
2879 
2880             mBroadcastHelper.sendPostInstallBroadcasts(mPm.snapshotComputer(), request, packageName,
2881                     mPm.mRequiredPermissionControllerPackage, mPm.mRequiredVerifierPackages,
2882                     mPm.mRequiredInstallerPackage,
2883                     /* packageSender= */ mPm, launchedForRestore, killApp, update, archived);
2884 
2885             if (request.isAllNewUsers() && !update) {
2886                 mPm.notifyPackageAdded(packageName, request.getAppId());
2887             } else {
2888                 mPm.notifyPackageChanged(packageName, request.getAppId());
2889             }
2890 
2891             // Set the OP_ACCESS_RESTRICTED_SETTINGS op, which is used by ECM (see {@link
2892             // EnhancedConfirmationManager}) as a persistent state denoting whether an app is
2893             // currently guarded by ECM, not guarded by ECM, or (in Android V+) that this should
2894             // be decided later.
2895             if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()
2896                     && android.security.Flags.extendEcmToAllSettings()) {
2897                 final int appId = request.getAppId();
2898                 mPm.mHandler.post(() -> {
2899                     for (int userId : firstUserIds) {
2900                         // MODE_DEFAULT means that the app's guardedness will be decided lazily
2901                         setAccessRestrictedSettingsMode(packageName, appId, userId,
2902                                 AppOpsManager.MODE_DEFAULT);
2903                     }
2904                 });
2905             } else {
2906                 // Apply restricted settings on potentially dangerous packages. Needs to happen
2907                 // after appOpsManager is notified of the new package
2908                 if (request.getPackageSource() == PackageInstaller.PACKAGE_SOURCE_LOCAL_FILE
2909                         || request.getPackageSource()
2910                         == PackageInstaller.PACKAGE_SOURCE_DOWNLOADED_FILE) {
2911                     final int appId = request.getAppId();
2912                     mPm.mHandler.post(() -> {
2913                         for (int userId : firstUserIds) {
2914                             // MODE_ERRORED means that the app is explicitly guarded
2915                             setAccessRestrictedSettingsMode(packageName, appId, userId,
2916                                     AppOpsManager.MODE_ERRORED);
2917                         }
2918                     });
2919                 }
2920             }
2921 
2922             // Log current value of "unknown sources" setting
2923             EventLog.writeEvent(EventLogTags.UNKNOWN_SOURCES_ENABLED,
2924                     getUnknownSourcesSettings());
2925 
2926             // Remove the replaced package's older resources safely now
2927             CleanUpArgs args = request.getRemovedInfo() != null
2928                     ? request.getRemovedInfo().mArgs : null;
2929             if (args != null) {
2930                 if (!killApp) {
2931                     // If we didn't kill the app, defer the deletion of code/resource files,
2932                     // since the old code/resource files may still be in use by the running
2933                     // application. This mitigates problems and cases where resources or
2934                     // code is loaded by a new Activity before ApplicationInfo changes have
2935                     // propagated to all application threads.
2936                     mPm.scheduleDeferredNoKillPostDelete(args);
2937                     if (Flags.improveInstallDontKill()) {
2938                         try (var installLock = mPm.mInstallLock.acquireLock()) {
2939                             PackageManagerServiceUtils.linkFilesToOldDirs(mPm.mInstaller,
2940                                     packageName, pkgSetting.getPath(), pkgSetting.getOldPaths());
2941                         }
2942                     }
2943                 } else {
2944                     mRemovePackageHelper.cleanUpResources(packageName, args.getCodeFile(),
2945                             args.getInstructionSets());
2946                 }
2947             } else {
2948                 // Force a gc to clear up things. Ask for a background one, it's fine to go on
2949                 // and not block here.
2950                 VMRuntime.getRuntime().requestConcurrentGC();
2951             }
2952 
2953             if (!archived) {
2954                 // Notify DexManager that the package was installed for new users.
2955                 // The updated users should already be indexed and the package code paths
2956                 // should not change.
2957                 // Don't notify the manager for ephemeral apps as they are not expected to
2958                 // survive long enough to benefit of background optimizations.
2959                 for (int userId : firstUserIds) {
2960                     PackageInfo info = snapshot.getPackageInfo(packageName, /*flags*/ 0, userId);
2961                     // There's a race currently where some install events may interleave with an
2962                     // uninstall. This can lead to package info being null (b/36642664).
2963                     if (info != null) {
2964                         mDexManager.notifyPackageInstalled(info, userId);
2965                     }
2966                 }
2967             } else {
2968                 // Now send PACKAGE_REMOVED + EXTRA_REPLACING broadcast.
2969                 final PackageRemovedInfo info = new PackageRemovedInfo();
2970                 info.mRemovedPackage = packageName;
2971                 info.mInstallerPackageName = request.getInstallerPackageName();
2972                 info.mRemovedUsers = firstUserIds;
2973                 info.mBroadcastUsers = firstUserIds;
2974                 info.mUid = request.getAppId();
2975                 info.mRemovedPackageVersionCode = request.getPkg().getLongVersionCode();
2976                 info.mRemovedForAllUsers = true;
2977 
2978                 mBroadcastHelper.sendPackageRemovedBroadcasts(info, mPm,
2979                         false /*killApp*/, false /*removedBySystem*/, true /*isArchived*/);
2980             }
2981         }
2982 
2983         final boolean deferInstallObserver = succeeded && update;
2984         if (deferInstallObserver) {
2985             if (killApp) {
2986                 mPm.scheduleDeferredPendingKillInstallObserver(request);
2987             } else {
2988                 mPm.scheduleDeferredNoKillInstallObserver(request);
2989             }
2990         } else {
2991             mPm.notifyInstallObserver(request);
2992         }
2993 
2994         // Prune unused static shared libraries which have been cached a period of time
2995         mPm.schedulePruneUnusedStaticSharedLibraries(true /* delay */);
2996 
2997         // Log tracing if needed
2998         if (request.getTraceMethod() != null) {
2999             Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, request.getTraceMethod(),
3000                     request.getTraceCookie());
3001         }
3002     }
3003 
3004     /**
3005      * Get the "allow unknown sources" setting.
3006      *
3007      * @return the current "allow unknown sources" setting
3008      */
getUnknownSourcesSettings()3009     private int getUnknownSourcesSettings() {
3010         return android.provider.Settings.Secure.getIntForUser(mContext.getContentResolver(),
3011                 android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS,
3012                 -1, UserHandle.USER_SYSTEM);
3013     }
3014 
3015     /**
3016      * Uncompress and install stub applications.
3017      * <p>In order to save space on the system partition, some applications are shipped in a
3018      * compressed form. In addition the compressed bits for the full application, the
3019      * system image contains a tiny stub comprised of only the Android manifest.
3020      * <p>During the first boot, attempt to uncompress and install the full application. If
3021      * the application can't be installed for any reason, disable the stub and prevent
3022      * uncompressing the full application during future boots.
3023      * <p>In order to forcefully attempt an installation of a full application, go to app
3024      * settings and enable the application.
3025      */
3026     @GuardedBy({"mPm.mLock", "mPm.mInstallLock"})
installSystemStubPackages(@onNull List<String> systemStubPackageNames, @PackageManagerService.ScanFlags int scanFlags)3027     void installSystemStubPackages(@NonNull List<String> systemStubPackageNames,
3028             @PackageManagerService.ScanFlags int scanFlags) {
3029         for (int i = systemStubPackageNames.size() - 1; i >= 0; --i) {
3030             final String packageName = systemStubPackageNames.get(i);
3031             // skip if the system package is already disabled
3032             if (mPm.mSettings.isDisabledSystemPackageLPr(packageName)) {
3033                 systemStubPackageNames.remove(i);
3034                 continue;
3035             }
3036             // skip if the package isn't installed (?!); this should never happen
3037             final AndroidPackage pkg = mPm.mPackages.get(packageName);
3038             if (pkg == null) {
3039                 systemStubPackageNames.remove(i);
3040                 continue;
3041             }
3042             // skip if the package has been disabled by the user
3043             final PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
3044             if (ps != null) {
3045                 final int enabledState = ps.getEnabled(UserHandle.USER_SYSTEM);
3046                 if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
3047                     systemStubPackageNames.remove(i);
3048                     continue;
3049                 }
3050             }
3051 
3052             // install the package to replace the stub on /system
3053             try {
3054                 installStubPackageLI(pkg, 0, scanFlags);
3055                 ps.setEnabled(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
3056                         UserHandle.USER_SYSTEM, "android");
3057                 systemStubPackageNames.remove(i);
3058             } catch (PackageManagerException e) {
3059                 Slog.e(TAG, "Failed to parse uncompressed system package: " + e.getMessage());
3060             }
3061 
3062             // any failed attempt to install the package will be cleaned up later
3063         }
3064 
3065         // disable any stub still left; these failed to install the full application
3066         for (int i = systemStubPackageNames.size() - 1; i >= 0; --i) {
3067             final String pkgName = systemStubPackageNames.get(i);
3068             final PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName);
3069             ps.setEnabled(PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
3070                     UserHandle.USER_SYSTEM, "android");
3071             logCriticalInfo(Log.ERROR, "Stub disabled; pkg: " + pkgName);
3072         }
3073     }
3074 
3075     /**
3076      * Extract, install and enable a stub package.
3077      * <p>If the compressed file can not be extracted / installed for any reason, the stub
3078      * APK will be installed and the package will be disabled. To recover from this situation,
3079      * the user will need to go into system settings and re-enable the package.
3080      */
enableCompressedPackage(AndroidPackage stubPkg, @NonNull PackageSetting stubPkgSetting)3081     boolean enableCompressedPackage(AndroidPackage stubPkg,
3082             @NonNull PackageSetting stubPkgSetting) {
3083         final int parseFlags = mPm.getDefParseFlags() | ParsingPackageUtils.PARSE_CHATTY
3084                 | ParsingPackageUtils.PARSE_ENFORCE_CODE;
3085         try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
3086             final AndroidPackage pkg;
3087             try (PackageFreezer freezer =
3088                          mPm.freezePackage(stubPkg.getPackageName(), UserHandle.USER_ALL,
3089                                  "setEnabledSetting",
3090                                  ApplicationExitInfo.REASON_PACKAGE_UPDATED, null /* request */)) {
3091                 pkg = installStubPackageLI(stubPkg, parseFlags, 0 /*scanFlags*/);
3092                 mAppDataHelper.prepareAppDataAfterInstallLIF(pkg);
3093                 synchronized (mPm.mLock) {
3094                     try {
3095                         mSharedLibraries.updateSharedLibraries(
3096                                 pkg, stubPkgSetting, null, null,
3097                                 Collections.unmodifiableMap(mPm.mPackages));
3098                     } catch (PackageManagerException e) {
3099                         Slog.w(TAG, "updateAllSharedLibrariesLPw failed: ", e);
3100                     }
3101                     mPm.mPermissionManager.onPackageInstalled(pkg,
3102                             Process.INVALID_UID /* previousAppId */,
3103                             PermissionManagerServiceInternal.PackageInstalledParams.DEFAULT,
3104                             UserHandle.USER_ALL);
3105                     mPm.writeSettingsLPrTEMP();
3106                     // Since compressed package can be system app only, we do not need to
3107                     // set restricted settings on it.
3108                 }
3109             } catch (PackageManagerException e) {
3110                 // Whoops! Something went very wrong; roll back to the stub and disable the package
3111                 try (PackageFreezer freezer =
3112                              mPm.freezePackage(stubPkg.getPackageName(), UserHandle.USER_ALL,
3113                                      "setEnabledSetting",
3114                                      ApplicationExitInfo.REASON_PACKAGE_UPDATED,
3115                                      null /* request */)) {
3116                     synchronized (mPm.mLock) {
3117                         // NOTE: Ensure the system package is enabled; even for a compressed stub.
3118                         // If we don't, installing the system package fails during scan
3119                         mPm.mSettings.enableSystemPackageLPw(stubPkg.getPackageName());
3120                     }
3121                     installPackageFromSystemLIF(stubPkg.getPath(),
3122                             mPm.mUserManager.getUserIds() /*allUserHandles*/,
3123                             null /*origUserHandles*/,
3124                             true /*writeSettings*/);
3125                 } catch (PackageManagerException pme) {
3126                     // Serious WTF; we have to be able to install the stub
3127                     Slog.wtf(TAG, "Failed to restore system package:" + stubPkg.getPackageName(),
3128                             pme);
3129                 } finally {
3130                     // Disable the package; the stub by itself is not runnable
3131                     synchronized (mPm.mLock) {
3132                         final PackageSetting stubPs = mPm.mSettings.getPackageLPr(
3133                                 stubPkg.getPackageName());
3134                         if (stubPs != null) {
3135                             stubPs.setEnabled(COMPONENT_ENABLED_STATE_DISABLED,
3136                                     UserHandle.USER_SYSTEM, "android");
3137                         }
3138                         mPm.writeSettingsLPrTEMP();
3139                     }
3140                 }
3141                 return false;
3142             }
3143             mAppDataHelper.clearAppDataLIF(pkg, UserHandle.USER_ALL,
3144                     FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
3145                             | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
3146             mDexManager.notifyPackageUpdated(pkg.getPackageName(),
3147                     pkg.getBaseApkPath(), pkg.getSplitCodePaths());
3148         }
3149         return true;
3150     }
3151 
3152     @GuardedBy("mPm.mInstallLock")
installStubPackageLI(AndroidPackage stubPkg, @ParsingPackageUtils.ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags)3153     private AndroidPackage installStubPackageLI(AndroidPackage stubPkg,
3154             @ParsingPackageUtils.ParseFlags int parseFlags,
3155             @PackageManagerService.ScanFlags int scanFlags)
3156             throws PackageManagerException {
3157         if (DEBUG_COMPRESSION) {
3158             Slog.i(TAG, "Uncompressing system stub; pkg: " + stubPkg.getPackageName());
3159         }
3160         // uncompress the binary to its eventual destination on /data
3161         final File scanFile = decompressPackage(stubPkg.getPackageName(), stubPkg.getPath());
3162         if (scanFile == null) {
3163             throw PackageManagerException.ofInternalError(
3164                     "Unable to decompress stub at " + stubPkg.getPath(),
3165                     PackageManagerException.INTERNAL_ERROR_DECOMPRESS_STUB);
3166         }
3167         synchronized (mPm.mLock) {
3168             mPm.mSettings.disableSystemPackageLPw(stubPkg.getPackageName(), true /*replaced*/);
3169         }
3170         mRemovePackageHelper.removePackage(stubPkg, true /*chatty*/);
3171         try {
3172             return initPackageTracedLI(scanFile, parseFlags, scanFlags);
3173         } catch (PackageManagerException e) {
3174             Slog.w(TAG, "Failed to install compressed system package:" + stubPkg.getPackageName(),
3175                     e);
3176             // Remove the failed install
3177             mRemovePackageHelper.removeCodePath(scanFile);
3178             throw e;
3179         }
3180     }
3181 
3182     /**
3183      * Decompresses the given package on the system image onto
3184      * the /data partition.
3185      * @return The directory the package was decompressed into. Otherwise, {@code null}.
3186      */
3187     @GuardedBy("mPm.mInstallLock")
decompressPackage(String packageName, String codePath)3188     private File decompressPackage(String packageName, String codePath) {
3189         if (!compressedFileExists(codePath)) {
3190             if (DEBUG_COMPRESSION) {
3191                 Slog.i(TAG, "No files to decompress at: " + codePath);
3192             }
3193             return null;
3194         }
3195         final File dstCodePath =
3196                 PackageManagerServiceUtils.getNextCodePath(Environment.getDataAppDirectory(null),
3197                         packageName);
3198         int ret = PackageManagerServiceUtils.decompressFiles(codePath, dstCodePath, packageName);
3199         if (ret == PackageManager.INSTALL_SUCCEEDED) {
3200             ret = PackageManagerServiceUtils.extractNativeBinaries(dstCodePath, packageName);
3201         }
3202         if (ret == PackageManager.INSTALL_SUCCEEDED) {
3203             // NOTE: During boot, we have to delay releasing cblocks for no other reason than
3204             // we cannot retrieve the setting {@link Secure#RELEASE_COMPRESS_BLOCKS_ON_INSTALL}.
3205             // When we no longer need to read that setting, cblock release can occur always
3206             // occur here directly
3207             if (!mPm.isSystemReady()) {
3208                 if (mPm.mReleaseOnSystemReady == null) {
3209                     mPm.mReleaseOnSystemReady = new ArrayList<>();
3210                 }
3211                 mPm.mReleaseOnSystemReady.add(dstCodePath);
3212             } else {
3213                 final ContentResolver resolver = mContext.getContentResolver();
3214                 F2fsUtils.releaseCompressedBlocks(resolver, dstCodePath);
3215             }
3216         } else {
3217             if (!dstCodePath.exists()) {
3218                 return null;
3219             }
3220             mRemovePackageHelper.removeCodePath(dstCodePath);
3221             return null;
3222         }
3223 
3224         return dstCodePath;
3225     }
3226 
3227     /**
3228      * Tries to restore the disabled system package after an update has been deleted.
3229      */
restoreDisabledSystemPackageLIF(DeletePackageAction action, @NonNull int[] allUserHandles, boolean writeSettings)3230     public void restoreDisabledSystemPackageLIF(DeletePackageAction action,
3231             @NonNull int[] allUserHandles, boolean writeSettings) throws SystemDeleteException {
3232         final PackageSetting deletedPs = action.mDeletingPs;
3233         final PackageRemovedInfo outInfo = action.mRemovedInfo;
3234         final PackageSetting disabledPs = action.mDisabledPs;
3235 
3236         synchronized (mPm.mLock) {
3237             // NOTE: The system package always needs to be enabled; even if it's for
3238             // a compressed stub. If we don't, installing the system package fails
3239             // during scan [scanning checks the disabled packages]. We will reverse
3240             // this later, after we've "installed" the stub.
3241             // Reinstate the old system package
3242             mPm.mSettings.enableSystemPackageLPw(disabledPs.getPkg().getPackageName());
3243             // Remove any native libraries from the upgraded package.
3244             PackageManagerServiceUtils.removeNativeBinariesLI(deletedPs);
3245         }
3246         // Install the system package
3247         if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs);
3248         try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
3249             final int[] origUsers = outInfo == null ? null : outInfo.mOrigUsers;
3250             installPackageFromSystemLIF(disabledPs.getPathString(), allUserHandles,
3251                     origUsers, writeSettings);
3252         } catch (PackageManagerException e) {
3253             Slog.w(TAG, "Failed to restore system package:" + deletedPs.getPackageName() + ": "
3254                     + e.getMessage());
3255             // TODO(b/194319951): can we avoid this; throw would come from scan...
3256             throw new SystemDeleteException(e);
3257         } finally {
3258             if (disabledPs.getPkg().isStub()) {
3259                 // We've re-installed the stub; make sure it's disabled here. If package was
3260                 // originally enabled, we'll install the compressed version of the application
3261                 // and re-enable it afterward.
3262                 synchronized (mPm.mLock) {
3263                     disableStubPackage(action, deletedPs, allUserHandles);
3264                 }
3265             }
3266         }
3267     }
3268 
3269     @GuardedBy("mPm.mLock")
disableStubPackage(DeletePackageAction action, PackageSetting deletedPs, @NonNull int[] allUserHandles)3270     private void disableStubPackage(DeletePackageAction action, PackageSetting deletedPs,
3271             @NonNull int[] allUserHandles) {
3272         final PackageSetting stubPs = mPm.mSettings.getPackageLPr(
3273                 deletedPs.getPackageName());
3274         if (stubPs != null) {
3275             int userId = action.mUser == null
3276                     ? UserHandle.USER_ALL : action.mUser.getIdentifier();
3277             if (userId == UserHandle.USER_ALL) {
3278                 for (int aUserId : allUserHandles) {
3279                     stubPs.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, aUserId, "android");
3280                 }
3281             } else if (userId >= UserHandle.USER_SYSTEM) {
3282                 stubPs.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, userId, "android");
3283             }
3284         }
3285     }
3286 
3287     /**
3288      * Installs a package that's already on the system partition.
3289      */
3290     @GuardedBy("mPm.mInstallLock")
installPackageFromSystemLIF(@onNull String codePathString, @NonNull int[] allUserHandles, @Nullable int[] origUserHandles, boolean writeSettings)3291     private void installPackageFromSystemLIF(@NonNull String codePathString,
3292             @NonNull int[] allUserHandles, @Nullable int[] origUserHandles,
3293             boolean writeSettings)
3294             throws PackageManagerException {
3295         final File codePath = new File(codePathString);
3296         @ParsingPackageUtils.ParseFlags int parseFlags =
3297                 mPm.getDefParseFlags()
3298                         | ParsingPackageUtils.PARSE_MUST_BE_APK
3299                         | ParsingPackageUtils.PARSE_IS_SYSTEM_DIR;
3300         @PackageManagerService.ScanFlags int scanFlags = mPm.getSystemPackageScanFlags(codePath);
3301         final AndroidPackage pkg = initPackageTracedLI(codePath, parseFlags, scanFlags);
3302 
3303         synchronized (mPm.mLock) {
3304             PackageSetting pkgSetting = mPm.mSettings.getPackageLPr(pkg.getPackageName());
3305             try {
3306                 // update shared libraries for the newly re-installed system package
3307                 mSharedLibraries.updateSharedLibraries(pkg, pkgSetting, null, null,
3308                         Collections.unmodifiableMap(mPm.mPackages));
3309             } catch (PackageManagerException e) {
3310                 Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
3311             }
3312         }
3313         setPackageInstalledForSystemPackage(pkg, allUserHandles, origUserHandles, writeSettings);
3314 
3315         mAppDataHelper.prepareAppDataAfterInstallLIF(pkg);
3316     }
3317 
setPackageInstalledForSystemPackage(@onNull AndroidPackage pkg, @NonNull int[] allUserHandles, @Nullable int[] origUserHandles, boolean writeSettings)3318     private void setPackageInstalledForSystemPackage(@NonNull AndroidPackage pkg,
3319             @NonNull int[] allUserHandles, @Nullable int[] origUserHandles,
3320             boolean writeSettings) {
3321         // writer
3322         synchronized (mPm.mLock) {
3323             PackageSetting ps = mPm.mSettings.getPackageLPr(pkg.getPackageName());
3324 
3325             final boolean applyUserRestrictions = origUserHandles != null;
3326             if (applyUserRestrictions) {
3327                 boolean installedStateChanged = false;
3328                 if (DEBUG_REMOVE) {
3329                     Slog.d(TAG, "Propagating install state across reinstall");
3330                 }
3331                 for (int userId : allUserHandles) {
3332                     final boolean installed = ArrayUtils.contains(origUserHandles, userId);
3333                     if (DEBUG_REMOVE) {
3334                         Slog.d(TAG, "    user " + userId + " => " + installed);
3335                     }
3336                     if (installed != ps.getInstalled(userId)) {
3337                         installedStateChanged = true;
3338                     }
3339                     ps.setInstalled(installed, userId);
3340                     if (installed) {
3341                         ps.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userId);
3342                     }
3343                 }
3344                 // Regardless of writeSettings we need to ensure that this restriction
3345                 // state propagation is persisted
3346                 mPm.mSettings.writeAllUsersPackageRestrictionsLPr();
3347                 if (installedStateChanged) {
3348                     mPm.mSettings.writeKernelMappingLPr(ps);
3349                 }
3350             }
3351 
3352             // The method below will take care of removing obsolete permissions and granting
3353             // install permissions.
3354             mPm.mPermissionManager.onPackageInstalled(pkg, Process.INVALID_UID,
3355                     PermissionManagerServiceInternal.PackageInstalledParams.DEFAULT,
3356                     UserHandle.USER_ALL);
3357             for (final int userId : allUserHandles) {
3358                 if (applyUserRestrictions) {
3359                     mPm.mSettings.writePermissionStateForUserLPr(userId, false);
3360                 }
3361             }
3362 
3363             // can downgrade to reader here
3364             if (writeSettings) {
3365                 mPm.writeSettingsLPrTEMP();
3366             }
3367         }
3368     }
3369 
3370     @GuardedBy("mPm.mLock")
prepareSystemPackageCleanUp( WatchedArrayMap<String, PackageSetting> packageSettings, List<String> possiblyDeletedUpdatedSystemApps, ArrayMap<String, File> expectingBetter, int[] userIds)3371     public void prepareSystemPackageCleanUp(
3372             WatchedArrayMap<String, PackageSetting> packageSettings,
3373             List<String> possiblyDeletedUpdatedSystemApps,
3374             ArrayMap<String, File> expectingBetter, int[] userIds) {
3375         // Iterates PackageSettings in reversed order because the item could be removed
3376         // during the iteration.
3377         for (int index = packageSettings.size() - 1; index >= 0; index--) {
3378             final PackageSetting ps = packageSettings.valueAt(index);
3379             final String packageName = ps.getPackageName();
3380             /*
3381              * If this is not a system app, it can't be a
3382              * disable system app.
3383              */
3384             if (!ps.isSystem()) {
3385                 continue;
3386             }
3387 
3388             /*
3389              * If the package is scanned, it's not erased.
3390              */
3391             final AndroidPackage scannedPkg = mPm.mPackages.get(packageName);
3392             final PackageSetting disabledPs =
3393                     mPm.mSettings.getDisabledSystemPkgLPr(packageName);
3394             if (scannedPkg != null) {
3395                 if (scannedPkg.isApex()) {
3396                     // APEX on /data has been scanned. No need to expect better.
3397                     continue;
3398                 }
3399                 /*
3400                  * If the system app is both scanned and in the
3401                  * disabled packages list, then it must have been
3402                  * added via OTA. Remove it from the currently
3403                  * scanned package so the previously user-installed
3404                  * application can be scanned.
3405                  */
3406                 if (disabledPs != null) {
3407                     logCriticalInfo(Log.WARN,
3408                             "Expecting better updated system app for "
3409                                     + packageName
3410                                     + "; removing system app.  Last known"
3411                                     + " codePath=" + ps.getPathString()
3412                                     + ", versionCode=" + ps.getVersionCode()
3413                                     + "; scanned versionCode="
3414                                     + scannedPkg.getLongVersionCode());
3415                     mRemovePackageHelper.removePackage(scannedPkg, true);
3416                     expectingBetter.put(ps.getPackageName(), ps.getPath());
3417                 }
3418 
3419                 continue;
3420             }
3421 
3422             if (disabledPs == null) {
3423                 logCriticalInfo(Log.WARN, "System package " + packageName
3424                         + " no longer exists; its data will be wiped");
3425                 mRemovePackageHelper.removePackageData(ps, userIds);
3426             } else {
3427                 // we still have a disabled system package, but, it still might have
3428                 // been removed. check the code path still exists and check there's
3429                 // still a package. the latter can happen if an OTA keeps the same
3430                 // code path, but, changes the package name.
3431                 if (disabledPs.getPath() == null || !disabledPs.getPath().exists()
3432                         || disabledPs.getPkg() == null) {
3433                     possiblyDeletedUpdatedSystemApps.add(packageName);
3434                 } else {
3435                     // We're expecting that the system app should remain disabled, but add
3436                     // it to expecting better to recover in case the data version cannot
3437                     // be scanned.
3438                     expectingBetter.put(disabledPs.getPackageName(), disabledPs.getPath());
3439                 }
3440             }
3441         }
3442     }
3443 
3444     @GuardedBy("mPm.mLock")
3445     // Remove disable package settings for updated system apps that were
3446     // removed via an OTA. If the update is no longer present, remove the
3447     // app completely. Otherwise, revoke their system privileges.
cleanupDisabledPackageSettings(List<String> possiblyDeletedUpdatedSystemApps, int[] userIds, int scanFlags)3448     public void cleanupDisabledPackageSettings(List<String> possiblyDeletedUpdatedSystemApps,
3449             int[] userIds, int scanFlags) {
3450         for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) {
3451             final String packageName = possiblyDeletedUpdatedSystemApps.get(i);
3452             final AndroidPackage pkg = mPm.mPackages.get(packageName);
3453             final String msg;
3454 
3455             // remove from the disabled system list; do this first so any future
3456             // scans of this package are performed without this state
3457             mPm.mSettings.removeDisabledSystemPackageLPw(packageName);
3458 
3459             if (pkg == null) {
3460                 // should have found an update, but, we didn't; remove everything
3461                 msg = "Updated system package " + packageName
3462                         + " no longer exists; removing its data";
3463                 // Actual deletion of code and data will be handled by later
3464                 // reconciliation step
3465             } else {
3466                 // found an update; revoke system privileges
3467                 msg = "Updated system package " + packageName
3468                         + " no longer exists; rescanning package on data";
3469 
3470                 // NOTE: We don't do anything special if a stub is removed from the
3471                 // system image. But, if we were [like removing the uncompressed
3472                 // version from the /data partition], this is where it'd be done.
3473 
3474                 // remove the package from the system and re-scan it without any
3475                 // special privileges
3476                 mRemovePackageHelper.removePackage(pkg, true);
3477                 PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
3478                 if (ps != null) {
3479                     ps.getPkgState().setUpdatedSystemApp(false);
3480                 }
3481                 final File codePath = new File(pkg.getPath());
3482                 try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
3483                     initPackageTracedLI(codePath, 0, scanFlags);
3484                 } catch (PackageManagerException e) {
3485                     Slog.e(TAG, "Failed to parse updated, ex-system package: "
3486                             + e.getMessage());
3487                 }
3488             }
3489 
3490             // one final check. if we still have a package setting [ie. it was
3491             // previously scanned and known to the system], but, we don't have
3492             // a package [ie. there was an error scanning it from the /data
3493             // partition], completely remove the package data.
3494             final PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
3495             if (ps != null && mPm.mPackages.get(packageName) == null) {
3496                 mRemovePackageHelper.removePackageData(ps, userIds);
3497             }
3498             logCriticalInfo(Log.WARN, msg);
3499         }
3500     }
3501 
3502     /**
3503      * Scans APEX packages and registers them with the system.
3504      *
3505      * apexd has its own policy to decide which APEX to activate and which not. The policy might
3506      * conflicts that of PMS. The APEX package info stored in PMS is a mirror of that managed by
3507      * apexd. To keep things simple and keep activation status in sync for both apexd and PMS, we
3508      * don't persist APEX in settings and always scan APEX from scratch during boot. However, some
3509      * data like lastUpdateTime will be lost if PackageSetting is not persisted for APEX.
3510      *
3511      * TODO(b/225756739): Read lastUpdateTime from ApexInfoList to populate PackageSetting correctly
3512      */
3513     @GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
scanApexPackages(ApexInfo[] allPackages, int parseFlags, int scanFlags, PackageParser2 packageParser, ExecutorService executorService)3514     public List<ApexManager.ScanResult> scanApexPackages(ApexInfo[] allPackages, int parseFlags,
3515             int scanFlags, PackageParser2 packageParser, ExecutorService executorService) {
3516         if (allPackages == null) {
3517             return Collections.EMPTY_LIST;
3518         }
3519 
3520         ParallelPackageParser parallelPackageParser =
3521                 new ParallelPackageParser(packageParser, executorService);
3522 
3523         // Submit files for parsing in parallel
3524         ArrayMap<File, ApexInfo> parsingApexInfo = new ArrayMap<>();
3525         for (ApexInfo ai : allPackages) {
3526             File apexFile = new File(ai.modulePath);
3527             parallelPackageParser.submit(apexFile, parseFlags);
3528             parsingApexInfo.put(apexFile, ai);
3529         }
3530 
3531         List<ParallelPackageParser.ParseResult> parseResults =
3532                 new ArrayList<>(parsingApexInfo.size());
3533         for (int i = 0; i < parsingApexInfo.size(); i++) {
3534             ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
3535             parseResults.add(parseResult);
3536         }
3537         // Sort the list to ensure we always process factory packages first
3538         Collections.sort(parseResults, (a, b) -> {
3539             ApexInfo i1 = parsingApexInfo.get(a.scanFile);
3540             ApexInfo i2 = parsingApexInfo.get(b.scanFile);
3541             return Boolean.compare(i2.isFactory, i1.isFactory);
3542         });
3543 
3544 
3545         // Process results one by one
3546         List<ApexManager.ScanResult> results = new ArrayList<>(parsingApexInfo.size());
3547         for (int i = 0; i < parseResults.size(); i++) {
3548             ParallelPackageParser.ParseResult parseResult = parseResults.get(i);
3549             Throwable throwable = parseResult.throwable;
3550             ApexInfo ai = parsingApexInfo.get(parseResult.scanFile);
3551             int newParseFlags = parseFlags;
3552             int newScanFlags = scanFlags | SCAN_AS_APEX
3553                     | mPm.getSystemPackageScanFlags(parseResult.scanFile);
3554             if (!ai.isFactory) {
3555                 newParseFlags &= ~ParsingPackageUtils.PARSE_IS_SYSTEM_DIR;
3556                 newScanFlags |= SCAN_NEW_INSTALL;
3557             }
3558 
3559             if (throwable == null) {
3560                 try {
3561                     addForInitLI(parseResult.parsedPackage, newParseFlags, newScanFlags, null,
3562                             new ApexManager.ActiveApexInfo(ai));
3563                     AndroidPackage pkg = parseResult.parsedPackage.hideAsFinal();
3564                     if (ai.isFactory && !ai.isActive) {
3565                         disableSystemPackageLPw(pkg);
3566                     }
3567                     results.add(new ApexManager.ScanResult(ai, pkg, pkg.getPackageName()));
3568                 } catch (PackageManagerException e) {
3569                     throw new IllegalStateException("Failed to scan: " + ai.modulePath, e);
3570                 }
3571             } else if (throwable instanceof PackageManagerException) {
3572                 throw new IllegalStateException("Unable to parse: " + ai.modulePath, throwable);
3573             } else {
3574                 throw new IllegalStateException("Unexpected exception occurred while parsing "
3575                         + ai.modulePath, throwable);
3576             }
3577         }
3578 
3579         return results;
3580     }
3581 
3582     @GuardedBy({"mPm.mInstallLock", "mPm.mLock"})
installPackagesFromDir(File scanDir, int parseFlags, int scanFlags, PackageParser2 packageParser, ExecutorService executorService, @Nullable ApexManager.ActiveApexInfo apexInfo)3583     public void installPackagesFromDir(File scanDir, int parseFlags,
3584             int scanFlags, PackageParser2 packageParser, ExecutorService executorService,
3585             @Nullable ApexManager.ActiveApexInfo apexInfo) {
3586         final File[] files = scanDir.listFiles();
3587         if (ArrayUtils.isEmpty(files)) {
3588             Log.d(TAG, "No files in app dir " + scanDir);
3589             return;
3590         }
3591 
3592         if (DEBUG_PACKAGE_SCANNING) {
3593             Log.d(TAG, "Scanning app dir " + scanDir + " scanFlags=" + scanFlags
3594                     + " flags=0x" + Integer.toHexString(parseFlags));
3595         }
3596         ParallelPackageParser parallelPackageParser =
3597                 new ParallelPackageParser(packageParser, executorService);
3598 
3599         // Submit files for parsing in parallel
3600         int fileCount = 0;
3601         for (File file : files) {
3602             final boolean isPackage = (isApkFile(file) || file.isDirectory())
3603                     && !PackageInstallerService.isStageName(file.getName());
3604             if (!isPackage) {
3605                 // Ignore entries which are not packages
3606                 continue;
3607             }
3608             if ((scanFlags & SCAN_DROP_CACHE) != 0) {
3609                 final PackageCacher cacher = new PackageCacher(mPm.getCacheDir(),
3610                         mPm.mPackageParserCallback);
3611                 Log.w(TAG, "Dropping cache of " + file.getAbsolutePath());
3612                 cacher.cleanCachedResult(file);
3613             }
3614             parallelPackageParser.submit(file, parseFlags);
3615             fileCount++;
3616         }
3617 
3618         // Process results one by one
3619         for (; fileCount > 0; fileCount--) {
3620             ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
3621             Throwable throwable = parseResult.throwable;
3622             int errorCode = PackageManager.INSTALL_SUCCEEDED;
3623             String errorMsg = null;
3624 
3625             if (throwable == null) {
3626                 try {
3627                     Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "addForInitLI");
3628                     addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags,
3629                             new UserHandle(UserHandle.USER_SYSTEM), apexInfo);
3630                 } catch (PackageManagerException e) {
3631                     errorCode = e.error;
3632                     errorMsg = "Failed to scan " + parseResult.scanFile + ": " + e.getMessage();
3633                     Slog.w(TAG, errorMsg);
3634                 } finally {
3635                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
3636                 }
3637             } else if (throwable instanceof PackageManagerException) {
3638                 PackageManagerException e = (PackageManagerException) throwable;
3639                 errorCode = e.error;
3640                 errorMsg = "Failed to parse " + parseResult.scanFile + ": " + e.getMessage();
3641                 Slog.w(TAG, errorMsg);
3642             } else {
3643                 throw new IllegalStateException("Unexpected exception occurred while parsing "
3644                         + parseResult.scanFile, throwable);
3645             }
3646 
3647             if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0 && errorCode != INSTALL_SUCCEEDED) {
3648                 mApexManager.reportErrorWithApkInApex(scanDir.getAbsolutePath(), errorMsg);
3649             }
3650 
3651             // Delete invalid userdata apps
3652             if ((scanFlags & SCAN_AS_SYSTEM) == 0
3653                     && errorCode != PackageManager.INSTALL_SUCCEEDED) {
3654                 logCriticalInfo(Log.WARN,
3655                         "Deleting invalid package at " + parseResult.scanFile);
3656                 mRemovePackageHelper.removeCodePath(parseResult.scanFile);
3657             }
3658         }
3659     }
3660 
3661     /**
3662      * Make sure all system apps that we expected to appear on
3663      * the userdata partition actually showed up. If they never
3664      * appeared, crawl back and revive the system version.
3665      */
3666     @GuardedBy("mPm.mLock")
checkExistingBetterPackages(ArrayMap<String, File> expectingBetterPackages, List<String> stubSystemApps, int systemScanFlags, int systemParseFlags)3667     public void checkExistingBetterPackages(ArrayMap<String, File> expectingBetterPackages,
3668             List<String> stubSystemApps, int systemScanFlags, int systemParseFlags) {
3669         for (int i = 0; i < expectingBetterPackages.size(); i++) {
3670             final String packageName = expectingBetterPackages.keyAt(i);
3671             if (mPm.mPackages.containsKey(packageName)) {
3672                 continue;
3673             }
3674             final File scanFile = expectingBetterPackages.valueAt(i);
3675 
3676             logCriticalInfo(Log.WARN, "Expected better " + packageName
3677                     + " but never showed up; reverting to system");
3678 
3679             final Pair<Integer, Integer> rescanAndReparseFlags =
3680                     mPm.getSystemPackageRescanFlagsAndReparseFlags(scanFile,
3681                             systemScanFlags, systemParseFlags);
3682             @PackageManagerService.ScanFlags int rescanFlags = rescanAndReparseFlags.first;
3683             @ParsingPackageUtils.ParseFlags int reparseFlags = rescanAndReparseFlags.second;
3684 
3685             if (rescanFlags == 0) {
3686                 Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
3687                 continue;
3688             }
3689             mPm.mSettings.enableSystemPackageLPw(packageName);
3690 
3691             try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
3692                 final AndroidPackage newPkg = initPackageTracedLI(
3693                          scanFile, reparseFlags, rescanFlags);
3694                  // We rescanned a stub, add it to the list of stubbed system packages
3695                 if (newPkg.isStub()) {
3696                     stubSystemApps.add(packageName);
3697                 }
3698             } catch (PackageManagerException e) {
3699                 Slog.e(TAG, "Failed to parse original system package: "
3700                         + e.getMessage());
3701             }
3702         }
3703     }
3704 
3705     /**
3706      *  Traces a package scan and registers it with the system.
3707      *  @see #initPackageLI(File, int, int)
3708      */
3709     @GuardedBy("mPm.mInstallLock")
initPackageTracedLI(File scanFile, final int parseFlags, int scanFlags)3710     public AndroidPackage initPackageTracedLI(File scanFile, final int parseFlags, int scanFlags)
3711             throws PackageManagerException {
3712         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage [" + scanFile.toString() + "]");
3713         try {
3714             return initPackageLI(scanFile, parseFlags, scanFlags);
3715         } finally {
3716             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
3717         }
3718     }
3719 
3720     /**
3721      *  Scans a package, registers it with the system and returns the newly parsed package.
3722      *  Returns {@code null} in case of errors and the error code is stored in mLastScanError
3723      */
3724     @GuardedBy("mPm.mInstallLock")
initPackageLI(File scanFile, int parseFlags, int scanFlags)3725     private AndroidPackage initPackageLI(File scanFile, int parseFlags, int scanFlags)
3726             throws PackageManagerException {
3727         if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
3728 
3729         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
3730         final ParsedPackage parsedPackage;
3731         try (PackageParser2 pp = mPm.mInjector.getScanningPackageParser()) {
3732             parsedPackage = pp.parsePackage(scanFile, parseFlags, false);
3733         } catch (PackageParserException e) {
3734             throw new PackageManagerException(e.error, e.getMessage(), e);
3735         } finally {
3736             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
3737         }
3738 
3739         return addForInitLI(parsedPackage, parseFlags, scanFlags,
3740                 new UserHandle(UserHandle.USER_SYSTEM), null);
3741     }
3742 
3743     /**
3744      * Adds a new package to the internal data structures during platform initialization.
3745      * <p>After adding, the package is known to the system and available for querying.
3746      * <p>For packages located on the device ROM [eg. packages located in /system, /vendor,
3747      * etc...], additional checks are performed. Basic verification [such as ensuring
3748      * matching signatures, checking version codes, etc...] occurs if the package is
3749      * identical to a previously known package. If the package fails a signature check,
3750      * the version installed on /data will be removed. If the version of the new package
3751      * is less than or equal than the version on /data, it will be ignored.
3752      * <p>Regardless of the package location, the results are applied to the internal
3753      * structures and the package is made available to the rest of the system.
3754      * <p>NOTE: The return value should be removed. It's the passed in package object.
3755      */
3756     @GuardedBy("mPm.mInstallLock")
addForInitLI(ParsedPackage parsedPackage, @ParsingPackageUtils.ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags, @Nullable UserHandle user, @Nullable ApexManager.ActiveApexInfo activeApexInfo)3757     private AndroidPackage addForInitLI(ParsedPackage parsedPackage,
3758             @ParsingPackageUtils.ParseFlags int parseFlags,
3759             @PackageManagerService.ScanFlags int scanFlags,
3760             @Nullable UserHandle user, @Nullable ApexManager.ActiveApexInfo activeApexInfo)
3761             throws PackageManagerException {
3762         PackageSetting disabledPkgSetting;
3763         synchronized (mPm.mLock) {
3764             // Static shared libraries have synthetic package names
3765             if (activeApexInfo == null && parsedPackage.isStaticSharedLibrary()) {
3766                 PackageManagerService.renameStaticSharedLibraryPackage(parsedPackage);
3767             }
3768             disabledPkgSetting =
3769                     mPm.mSettings.getDisabledSystemPkgLPr(parsedPackage.getPackageName());
3770             if (activeApexInfo != null && disabledPkgSetting != null) {
3771                 // When a disabled system package is scanned, its final PackageSetting is actually
3772                 // skipped and not added to any data structures, instead relying on the disabled
3773                 // setting read from the persisted Settings XML file. This persistence does not
3774                 // include the APEX module name, so here, re-set it from the active APEX info.
3775                 //
3776                 // This also has the (beneficial) side effect where if a package disappears from an
3777                 // APEX, leaving only a /data copy, it will lose its apexModuleName.
3778                 //
3779                 // This must be done before scanSystemPackageLI as that will throw in the case of a
3780                 // system -> data package.
3781                 disabledPkgSetting.setApexModuleName(activeApexInfo.apexModuleName);
3782             }
3783         }
3784 
3785         final Pair<ScanResult, Boolean> scanResultPair = scanSystemPackageLI(
3786                 parsedPackage, parseFlags, scanFlags, user);
3787         final ScanResult scanResult = scanResultPair.first;
3788         boolean shouldHideSystemApp = scanResultPair.second;
3789         final InstallRequest installRequest = new InstallRequest(
3790                 parsedPackage, parseFlags, scanFlags, user, scanResult, disabledPkgSetting);
3791 
3792         String existingApexModuleName = null;
3793         synchronized (mPm.mLock) {
3794             var existingPkgSetting = mPm.mSettings.getPackageLPr(parsedPackage.getPackageName());
3795             if (existingPkgSetting != null) {
3796                 existingApexModuleName = existingPkgSetting.getApexModuleName();
3797             }
3798         }
3799 
3800         if (activeApexInfo != null) {
3801             installRequest.setApexModuleName(activeApexInfo.apexModuleName);
3802         } else {
3803             if (disabledPkgSetting != null) {
3804                 installRequest.setApexModuleName(disabledPkgSetting.getApexModuleName());
3805             } else if (existingApexModuleName != null) {
3806                 installRequest.setApexModuleName(existingApexModuleName);
3807             }
3808         }
3809 
3810         synchronized (mPm.mLock) {
3811             boolean appIdCreated = false;
3812             try {
3813                 final String pkgName = scanResult.mPkgSetting.getPackageName();
3814                 final List<ReconciledPackage> reconcileResult =
3815                         ReconcilePackageUtils.reconcilePackages(
3816                                 Collections.singletonList(installRequest),
3817                                 mPm.mPackages, Collections.singletonMap(pkgName,
3818                                         mPm.getSettingsVersionForPackage(parsedPackage)),
3819                                 mSharedLibraries, mPm.mSettings.getKeySetManagerService(),
3820                                 mPm.mSettings, mPm.mInjector.getSystemConfig());
3821                 if ((scanFlags & SCAN_AS_APEX) == 0) {
3822                     appIdCreated = optimisticallyRegisterAppId(installRequest);
3823                 } else {
3824                     installRequest.setScannedPackageSettingAppId(Process.INVALID_UID);
3825                 }
3826                 commitReconciledScanResultLocked(reconcileResult.get(0),
3827                         mPm.mUserManager.getUserIds());
3828             } catch (PackageManagerException e) {
3829                 if (appIdCreated) {
3830                     cleanUpAppIdCreation(installRequest);
3831                 }
3832                 throw e;
3833             }
3834         }
3835 
3836         if (shouldHideSystemApp) {
3837             synchronized (mPm.mLock) {
3838                 mPm.mSettings.disableSystemPackageLPw(parsedPackage.getPackageName(), true);
3839             }
3840         }
3841 
3842         if (mIncrementalManager != null && isIncrementalPath(parsedPackage.getPath())) {
3843             if (scanResult.mPkgSetting != null && scanResult.mPkgSetting.isLoading()) {
3844                 // Continue monitoring loading progress of active incremental packages
3845                 mIncrementalManager.registerLoadingProgressCallback(parsedPackage.getPath(),
3846                         new IncrementalProgressListener(parsedPackage.getPackageName(), mPm));
3847             }
3848         }
3849 
3850         if (Flags.aslInApkAppMetadataSource()
3851                 && scanResult.mPkgSetting.getAppMetadataSource() == APP_METADATA_SOURCE_APK) {
3852             if (!extractAppMetadataFromApk(parsedPackage,
3853                     scanResult.mPkgSetting.getAppMetadataFilePath(),
3854                     scanResult.mPkgSetting.isSystem())) {
3855                 synchronized (mPm.mLock) {
3856                     scanResult.mPkgSetting.setAppMetadataFilePath(null)
3857                             .setAppMetadataSource(APP_METADATA_SOURCE_UNKNOWN);
3858                 }
3859             }
3860         }
3861         return scanResult.mPkgSetting.getPkg();
3862     }
3863 
3864     /**
3865      * Prepares the system to commit a {@link ScanResult} in a way that will not fail by registering
3866      * the app ID required for reconcile.
3867      * @return {@code true} if a new app ID was registered and will need to be cleaned up on
3868      *         failure.
3869      */
optimisticallyRegisterAppId(@onNull InstallRequest installRequest)3870     private boolean optimisticallyRegisterAppId(@NonNull InstallRequest installRequest)
3871             throws PackageManagerException {
3872         if (!installRequest.isExistingSettingCopied() || installRequest.needsNewAppId()) {
3873             synchronized (mPm.mLock) {
3874                 // THROWS: when we can't allocate a user id. add call to check if there's
3875                 // enough space to ensure we won't throw; otherwise, don't modify state
3876                 return mPm.mSettings.registerAppIdLPw(installRequest.getScannedPackageSetting(),
3877                         installRequest.needsNewAppId());
3878             }
3879         }
3880         return false;
3881     }
3882 
3883     /**
3884      * Reverts any app ID creation that were made by
3885      * {@link #optimisticallyRegisterAppId(InstallRequest)}. Note: this is only necessary if the
3886      * referenced method returned true.
3887      */
cleanUpAppIdCreation(@onNull InstallRequest installRequest)3888     private void cleanUpAppIdCreation(@NonNull InstallRequest installRequest) {
3889         // iff we've acquired an app ID for a new package setting, remove it so that it can be
3890         // acquired by another request.
3891         if (installRequest.getScannedPackageSetting() != null
3892                 && installRequest.getScannedPackageSetting().getAppId() > 0) {
3893             synchronized (mPm.mLock) {
3894                 mPm.mSettings.removeAppIdLPw(installRequest.getScannedPackageSetting().getAppId());
3895             }
3896         }
3897     }
3898 
3899     @GuardedBy("mPm.mInstallLock")
scanPackageTracedLI(ParsedPackage parsedPackage, final @ParsingPackageUtils.ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags, long currentTime, @Nullable UserHandle user, String cpuAbiOverride)3900     private ScanResult scanPackageTracedLI(ParsedPackage parsedPackage,
3901             final @ParsingPackageUtils.ParseFlags int parseFlags,
3902             @PackageManagerService.ScanFlags int scanFlags, long currentTime,
3903             @Nullable UserHandle user, String cpuAbiOverride) throws PackageManagerException {
3904         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage");
3905         try {
3906             return scanPackageNewLI(parsedPackage, parseFlags, scanFlags, currentTime, user,
3907                     cpuAbiOverride);
3908         } finally {
3909             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
3910         }
3911     }
3912 
prepareInitialScanRequest(@onNull ParsedPackage parsedPackage, @ParsingPackageUtils.ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags, @Nullable UserHandle user, String cpuAbiOverride)3913     private ScanRequest prepareInitialScanRequest(@NonNull ParsedPackage parsedPackage,
3914             @ParsingPackageUtils.ParseFlags int parseFlags,
3915             @PackageManagerService.ScanFlags int scanFlags,
3916             @Nullable UserHandle user, String cpuAbiOverride)
3917             throws PackageManagerException {
3918         final AndroidPackage platformPackage;
3919         final String realPkgName;
3920         final PackageSetting disabledPkgSetting;
3921         final PackageSetting installedPkgSetting;
3922         final PackageSetting originalPkgSetting;
3923         final SharedUserSetting sharedUserSetting;
3924         SharedUserSetting oldSharedUserSetting = null;
3925 
3926         synchronized (mPm.mLock) {
3927             platformPackage = mPm.getPlatformPackage();
3928             var isSystemApp = AndroidPackageLegacyUtils.isSystem(parsedPackage);
3929             final String renamedPkgName = mPm.mSettings.getRenamedPackageLPr(
3930                     AndroidPackageUtils.getRealPackageOrNull(parsedPackage, isSystemApp));
3931             realPkgName = ScanPackageUtils.getRealPackageName(parsedPackage, renamedPkgName,
3932                     isSystemApp);
3933             if (realPkgName != null) {
3934                 ScanPackageUtils.ensurePackageRenamed(parsedPackage, renamedPkgName);
3935             }
3936             originalPkgSetting = getOriginalPackageLocked(parsedPackage, renamedPkgName);
3937             installedPkgSetting = mPm.mSettings.getPackageLPr(parsedPackage.getPackageName());
3938             if (mPm.mTransferredPackages.contains(parsedPackage.getPackageName())) {
3939                 Slog.w(TAG, "Package " + parsedPackage.getPackageName()
3940                         + " was transferred to another, but its .apk remains");
3941             }
3942             disabledPkgSetting = mPm.mSettings.getDisabledSystemPkgLPr(
3943                     parsedPackage.getPackageName());
3944 
3945             boolean ignoreSharedUserId = false;
3946             if (installedPkgSetting == null || !installedPkgSetting.hasSharedUser()) {
3947                 // Directly ignore sharedUserSetting for new installs, or if the app has
3948                 // already left shared UID
3949                 ignoreSharedUserId = parsedPackage.isLeavingSharedUser();
3950             }
3951 
3952             if (!ignoreSharedUserId && parsedPackage.getSharedUserId() != null) {
3953                 sharedUserSetting = mPm.mSettings.getSharedUserLPw(
3954                         parsedPackage.getSharedUserId(),
3955                         0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, true /*create*/);
3956             } else {
3957                 sharedUserSetting = null;
3958             }
3959             if (DEBUG_PACKAGE_SCANNING
3960                     && (parseFlags & ParsingPackageUtils.PARSE_CHATTY) != 0
3961                     && sharedUserSetting != null) {
3962                 Log.d(TAG, "Shared UserID " + parsedPackage.getSharedUserId()
3963                         + " (uid=" + sharedUserSetting.mAppId + "):"
3964                         + " packages=" + sharedUserSetting.getPackageStates());
3965             }
3966             if (installedPkgSetting != null) {
3967                 oldSharedUserSetting = mPm.mSettings.getSharedUserSettingLPr(installedPkgSetting);
3968             }
3969         }
3970 
3971         final boolean isPlatformPackage = platformPackage != null
3972                 && platformPackage.getPackageName().equals(parsedPackage.getPackageName());
3973 
3974         return new ScanRequest(parsedPackage, oldSharedUserSetting,
3975                 installedPkgSetting == null ? null : installedPkgSetting.getPkg() /* oldPkg */,
3976                 installedPkgSetting /* packageSetting */,
3977                 sharedUserSetting,
3978                 disabledPkgSetting /* disabledPackageSetting */,
3979                 originalPkgSetting  /* originalPkgSetting */,
3980                 realPkgName, parseFlags, scanFlags, isPlatformPackage, user, cpuAbiOverride);
3981     }
3982 
3983     @GuardedBy("mPm.mInstallLock")
scanPackageNewLI(@onNull ParsedPackage parsedPackage, final @ParsingPackageUtils.ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags, long currentTime, @Nullable UserHandle user, String cpuAbiOverride)3984     private ScanResult scanPackageNewLI(@NonNull ParsedPackage parsedPackage,
3985             final @ParsingPackageUtils.ParseFlags int parseFlags,
3986             @PackageManagerService.ScanFlags int scanFlags, long currentTime,
3987             @Nullable UserHandle user, String cpuAbiOverride)
3988             throws PackageManagerException {
3989         final ScanRequest initialScanRequest = prepareInitialScanRequest(parsedPackage, parseFlags,
3990                 scanFlags, user, cpuAbiOverride);
3991         final PackageSetting installedPkgSetting = initialScanRequest.mPkgSetting;
3992         final PackageSetting disabledPkgSetting = initialScanRequest.mDisabledPkgSetting;
3993 
3994         boolean isUpdatedSystemApp;
3995         if (installedPkgSetting != null) {
3996             isUpdatedSystemApp = installedPkgSetting.isUpdatedSystemApp();
3997         } else {
3998             isUpdatedSystemApp = disabledPkgSetting != null;
3999         }
4000 
4001         final int newScanFlags = adjustScanFlags(scanFlags, installedPkgSetting, disabledPkgSetting,
4002                 user, parsedPackage);
4003         ScanPackageUtils.applyPolicy(parsedPackage, newScanFlags,
4004                 mPm.getPlatformPackage(), isUpdatedSystemApp);
4005 
4006         synchronized (mPm.mLock) {
4007             assertPackageIsValid(parsedPackage, parseFlags, newScanFlags);
4008             final ScanRequest request = new ScanRequest(parsedPackage,
4009                     initialScanRequest.mOldSharedUserSetting,
4010                     initialScanRequest.mOldPkg, installedPkgSetting,
4011                     initialScanRequest.mSharedUserSetting, disabledPkgSetting,
4012                     initialScanRequest.mOriginalPkgSetting, initialScanRequest.mRealPkgName,
4013                     parseFlags, scanFlags, initialScanRequest.mIsPlatformPackage, user,
4014                     cpuAbiOverride);
4015             return ScanPackageUtils.scanPackageOnlyLI(request, mPm.mInjector, mPm.mFactoryTest,
4016                     currentTime);
4017         }
4018     }
4019 
scanSystemPackageLI(ParsedPackage parsedPackage, @ParsingPackageUtils.ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags, @Nullable UserHandle user)4020     private Pair<ScanResult, Boolean> scanSystemPackageLI(ParsedPackage parsedPackage,
4021             @ParsingPackageUtils.ParseFlags int parseFlags,
4022             @PackageManagerService.ScanFlags int scanFlags,
4023             @Nullable UserHandle user) throws PackageManagerException {
4024         final boolean scanSystemPartition =
4025                 (parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) != 0;
4026         final ScanRequest initialScanRequest = prepareInitialScanRequest(parsedPackage, parseFlags,
4027                 scanFlags, user, null);
4028         final PackageSetting installedPkgSetting = initialScanRequest.mPkgSetting;
4029         final PackageSetting originalPkgSetting = initialScanRequest.mOriginalPkgSetting;
4030         final PackageSetting pkgSetting =
4031                 originalPkgSetting == null ? installedPkgSetting : originalPkgSetting;
4032         final boolean pkgAlreadyExists = pkgSetting != null;
4033         final String disabledPkgName = pkgAlreadyExists
4034                 ? pkgSetting.getPackageName() : parsedPackage.getPackageName();
4035         final boolean isSystemPkgUpdated;
4036         final PackageSetting disabledPkgSetting;
4037         final boolean isUpgrade;
4038         synchronized (mPm.mLock) {
4039             isUpgrade = mPm.isDeviceUpgrading();
4040             if (scanSystemPartition && !pkgAlreadyExists
4041                     && mPm.mSettings.getDisabledSystemPkgLPr(disabledPkgName) != null) {
4042                 // The updated-package data for /system apk remains inconsistently
4043                 // after the package data for /data apk is lost accidentally.
4044                 // To recover it, enable /system apk and install it as non-updated system app.
4045                 Slog.w(TAG, "Inconsistent package setting of updated system app for "
4046                         + disabledPkgName + ". To recover it, enable the system app "
4047                         + "and install it as non-updated system app.");
4048                 mPm.mSettings.removeDisabledSystemPackageLPw(disabledPkgName);
4049             }
4050             disabledPkgSetting = mPm.mSettings.getDisabledSystemPkgLPr(disabledPkgName);
4051             isSystemPkgUpdated = disabledPkgSetting != null;
4052 
4053             if (DEBUG_INSTALL && isSystemPkgUpdated) {
4054                 Slog.d(TAG, "updatedPkg = " + disabledPkgSetting);
4055             }
4056 
4057             if (scanSystemPartition && isSystemPkgUpdated) {
4058                 // we're updating the disabled package, so, scan it as the package setting
4059                 final ScanRequest request = new ScanRequest(parsedPackage,
4060                         mPm.mSettings.getSharedUserSettingLPr(disabledPkgSetting),
4061                         null, disabledPkgSetting /* pkgSetting */,
4062                         initialScanRequest.mSharedUserSetting,
4063                         null /* disabledPkgSetting */, null /* originalPkgSetting */,
4064                         null, parseFlags, scanFlags,
4065                         initialScanRequest.mIsPlatformPackage, user, null);
4066                 ScanPackageUtils.applyPolicy(parsedPackage, scanFlags,
4067                         mPm.getPlatformPackage(), true);
4068                 final ScanResult scanResult =
4069                         ScanPackageUtils.scanPackageOnlyLI(request, mPm.mInjector,
4070                                 mPm.mFactoryTest, -1L);
4071                 if (scanResult.mExistingSettingCopied
4072                         && scanResult.mRequest.mPkgSetting != null) {
4073                     scanResult.mRequest.mPkgSetting.updateFrom(scanResult.mPkgSetting);
4074                 }
4075             }
4076         } // End of mLock
4077 
4078         final boolean newPkgChangedPaths = pkgAlreadyExists
4079                 && !pkgSetting.getPathString().equals(parsedPackage.getPath());
4080         final boolean newPkgVersionGreater = pkgAlreadyExists
4081                 && parsedPackage.getLongVersionCode() > pkgSetting.getVersionCode();
4082         final boolean newSharedUserSetting = pkgAlreadyExists
4083                 && (initialScanRequest.mOldSharedUserSetting
4084                 != initialScanRequest.mSharedUserSetting);
4085         final boolean isSystemPkgBetter = scanSystemPartition && isSystemPkgUpdated
4086                 && newPkgChangedPaths && (newPkgVersionGreater || newSharedUserSetting);
4087         if (isSystemPkgBetter) {
4088             // The version of the application on /system is greater than the version on
4089             // /data. Switch back to the application on /system.
4090             // It's safe to assume the application on /system will correctly scan. If not,
4091             // there won't be a working copy of the application.
4092             // Also, if the sharedUserSetting of the application on /system is different
4093             // from the sharedUserSetting on /data, switch back to the application on /system.
4094             // We should trust the sharedUserSetting on /system, even if the application
4095             // version on /system is smaller than the version on /data.
4096             synchronized (mPm.mLock) {
4097                 // just remove the loaded entries from package lists
4098                 mPm.mPackages.remove(pkgSetting.getPackageName());
4099             }
4100 
4101             logCriticalInfo(Log.WARN,
4102                     "System package updated;"
4103                             + " name: " + pkgSetting.getPackageName()
4104                             + "; " + pkgSetting.getVersionCode() + " --> "
4105                             + parsedPackage.getLongVersionCode()
4106                             + "; " + pkgSetting.getPathString()
4107                             + " --> " + parsedPackage.getPath());
4108 
4109             mRemovePackageHelper.cleanUpResources(pkgSetting.getPackageName(),
4110                     new File(pkgSetting.getPathString()),
4111                     getAppDexInstructionSets(pkgSetting.getPrimaryCpuAbiLegacy(),
4112                             pkgSetting.getSecondaryCpuAbiLegacy()));
4113             synchronized (mPm.mLock) {
4114                 mPm.mSettings.enableSystemPackageLPw(pkgSetting.getPackageName());
4115             }
4116         }
4117 
4118         // The version of the application on the /system partition is less than or
4119         // equal to the version on the /data partition. Throw an exception and use
4120         // the application already installed on the /data partition.
4121         if (scanSystemPartition && isSystemPkgUpdated && !isSystemPkgBetter) {
4122             // For some updated system packages, during addForInit we want to ensure the
4123             // PackageSetting has the correct SigningDetails compares to the original version on
4124             // the system partition. For the check to happen later during the /data scan, update
4125             // the disabled package setting per the original APK on a system partition so that it
4126             // can be trusted during reconcile.
4127             if (needSignatureMatchToSystem(parsedPackage.getPackageName())) {
4128                 final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
4129                 final ParseResult<SigningDetails> result =
4130                         ParsingPackageUtils.getSigningDetails(input, parsedPackage,
4131                                 false /*skipVerify*/);
4132                 if (result.isError()) {
4133                     throw new PrepareFailure("Failed collect during scanSystemPackageLI",
4134                             result.getException());
4135                 }
4136                 disabledPkgSetting.setSigningDetails(result.getResult());
4137             }
4138 
4139             // In the case of a skipped package, commitReconciledScanResultLocked is not called to
4140             // add the object to the "live" data structures, so this is the final mutation step
4141             // for the package. Which means it needs to be finalized here to cache derived fields.
4142             // This is relevant for cases where the disabled system package is used for flags or
4143             // other metadata.
4144             parsedPackage.hideAsFinal();
4145             throw PackageManagerException.ofInternalError(
4146                     "Package " + parsedPackage.getPackageName()
4147                     + " at " + parsedPackage.getPath() + " ignored: updated version "
4148                     + (pkgAlreadyExists ? String.valueOf(pkgSetting.getVersionCode()) : "unknown")
4149                     + " better than this " + parsedPackage.getLongVersionCode(),
4150                     PackageManagerException.INTERNAL_ERROR_UPDATED_VERSION_BETTER_THAN_SYSTEM);
4151         }
4152 
4153         // Verify certificates against what was last scanned. Force re-collecting certificate in two
4154         // special cases:
4155         // 1) when scanning system, force re-collect only if system is upgrading.
4156         // 2) when scanning /data, force re-collect only if the package name is allowlisted.
4157         final boolean forceCollect = scanSystemPartition ? isUpgrade
4158                 : pkgAlreadyExists && needSignatureMatchToSystem(pkgSetting.getPackageName());
4159         if (DEBUG_VERIFY && forceCollect) {
4160             Slog.d(TAG, "Force collect certificate of " + parsedPackage.getPackageName());
4161         }
4162 
4163         // APK verification can be skipped during certificate collection, only if the file is in a
4164         // verified partition.
4165         final boolean skipVerify = scanSystemPartition;
4166         ScanPackageUtils.collectCertificatesLI(pkgSetting, parsedPackage,
4167                 mPm.getSettingsVersionForPackage(parsedPackage), forceCollect, skipVerify,
4168                 mPm.isPreNMR1Upgrade());
4169 
4170         // Reset profile if the application version is changed
4171         maybeClearProfilesForUpgradesLI(pkgSetting, parsedPackage);
4172 
4173         /*
4174          * A new system app appeared, but we already had a non-system one of the
4175          * same name installed earlier.
4176          */
4177         boolean shouldHideSystemApp = false;
4178         // A new application appeared on /system, but, we already have a copy of
4179         // the application installed on /data.
4180         if (scanSystemPartition && !isSystemPkgUpdated && pkgAlreadyExists
4181                 && !pkgSetting.isSystem()) {
4182 
4183             if (!parsedPackage.getSigningDetails()
4184                     .checkCapability(pkgSetting.getSigningDetails(),
4185                             SigningDetails.CertCapabilities.INSTALLED_DATA)
4186                     && !pkgSetting.getSigningDetails().checkCapability(
4187                     parsedPackage.getSigningDetails(),
4188                     SigningDetails.CertCapabilities.ROLLBACK)) {
4189                 logCriticalInfo(Log.WARN,
4190                         "System package signature mismatch;"
4191                                 + " name: " + pkgSetting.getPackageName());
4192                 try (@SuppressWarnings("unused") PackageFreezer freezer = mPm.freezePackage(
4193                         parsedPackage.getPackageName(), UserHandle.USER_ALL,
4194                         "scanPackageInternalLI", ApplicationExitInfo.REASON_OTHER,
4195                         null /* request */)) {
4196                     mDeletePackageHelper.deletePackageLIF(
4197                             parsedPackage.getPackageName(), null, true,
4198                             mPm.mUserManager.getUserIds(), 0, new PackageRemovedInfo(), false);
4199                 }
4200             } else if (newPkgVersionGreater || newSharedUserSetting) {
4201                 // The application on /system is newer than the application on /data.
4202                 // Simply remove the application on /data [keeping application data]
4203                 // and replace it with the version on /system.
4204                 // Also, if the sharedUserSetting of the application on /system is different
4205                 // from the sharedUserSetting on data, we should trust the sharedUserSetting
4206                 // on /system, even if the application version on /system is smaller than
4207                 // the version on /data.
4208                 logCriticalInfo(Log.WARN,
4209                         "System package enabled;"
4210                                 + " name: " + pkgSetting.getPackageName()
4211                                 + "; " + pkgSetting.getVersionCode() + " --> "
4212                                 + parsedPackage.getLongVersionCode()
4213                                 + "; " + pkgSetting.getPathString() + " --> "
4214                                 + parsedPackage.getPath());
4215                 mRemovePackageHelper.cleanUpResources(pkgSetting.getPackageName(),
4216                         new File(pkgSetting.getPathString()),
4217                         getAppDexInstructionSets(
4218                                 pkgSetting.getPrimaryCpuAbiLegacy(), pkgSetting.getSecondaryCpuAbiLegacy()));
4219             } else {
4220                 // The application on /system is older than the application on /data. Hide
4221                 // the application on /system and the version on /data will be scanned later
4222                 // and re-added like an update.
4223                 shouldHideSystemApp = true;
4224                 logCriticalInfo(Log.INFO,
4225                         "System package disabled;"
4226                                 + " name: " + pkgSetting.getPackageName()
4227                                 + "; old: " + pkgSetting.getPathString() + " @ "
4228                                 + pkgSetting.getVersionCode()
4229                                 + "; new: " + parsedPackage.getPath() + " @ "
4230                                 + parsedPackage.getLongVersionCode());
4231             }
4232         }
4233 
4234         // A new application appeared on /system, and we are seeing it for the first time.
4235         // Its also not updated as we don't have a copy of it on /data. So, scan it in a
4236         // STOPPED state.
4237         // We'll skip this step under the following conditions:
4238         //   - It's "android"
4239         //   - It's an APEX or overlay package since stopped state does not affect them.
4240         //   - It is enumerated with a <initial-package-state> tag having the stopped attribute
4241         //     set to false
4242         //   - It doesn't have an enabled and exported launcher activity, which means the user
4243         //     wouldn't have a way to un-stop it
4244         final boolean isApexPkg = (scanFlags & SCAN_AS_APEX) != 0;
4245         if (mPm.mShouldStopSystemPackagesByDefault
4246                 && scanSystemPartition
4247                 && !pkgAlreadyExists
4248                 && !isApexPkg
4249                 && !parsedPackage.isOverlayIsStatic()
4250         ) {
4251             String packageName = parsedPackage.getPackageName();
4252             if (!"android".contentEquals(packageName)
4253                     && !mPm.mInitialNonStoppedSystemPackages.contains(packageName)
4254                     && hasLauncherEntry(parsedPackage)) {
4255                 scanFlags |= SCAN_AS_STOPPED_SYSTEM_APP;
4256             }
4257         }
4258 
4259         final long firstInstallTime = Flags.fixSystemAppsFirstInstallTime()
4260                 ? System.currentTimeMillis() : 0;
4261         final ScanResult scanResult = scanPackageNewLI(parsedPackage, parseFlags,
4262                 scanFlags | SCAN_UPDATE_SIGNATURE, firstInstallTime, user, null);
4263         return new Pair<>(scanResult, shouldHideSystemApp);
4264     }
4265 
hasLauncherEntry(ParsedPackage parsedPackage)4266     private static boolean hasLauncherEntry(ParsedPackage parsedPackage) {
4267         final HashSet<String> categories = new HashSet<>();
4268         categories.add(Intent.CATEGORY_LAUNCHER);
4269         final List<ParsedActivity> activities = parsedPackage.getActivities();
4270         for (int indexActivity = 0; indexActivity < activities.size(); indexActivity++) {
4271             final ParsedActivity activity = activities.get(indexActivity);
4272             if (!activity.isEnabled() || !activity.isExported()) {
4273                 continue;
4274             }
4275             final List<ParsedIntentInfo> intents = activity.getIntents();
4276             for (int indexIntent = 0; indexIntent < intents.size(); indexIntent++) {
4277                 final IntentFilter intentFilter = intents.get(indexIntent).getIntentFilter();
4278                 if (intentFilter != null && intentFilter.matchCategories(categories) == null) {
4279                     return true;
4280                 }
4281             }
4282         }
4283         return false;
4284     }
4285 
4286     /**
4287      * Returns whether the package needs a signature verification against the pre-installed version
4288      * at boot.
4289      */
needSignatureMatchToSystem(String packageName)4290     private boolean needSignatureMatchToSystem(String packageName) {
4291         if (!android.security.Flags.extendVbChainToUpdatedApk()) {
4292             return false;
4293         }
4294         return mPm.mInjector.getSystemConfig().getPreinstallPackagesWithStrictSignatureCheck()
4295             .contains(packageName);
4296     }
4297 
4298     /**
4299      * Clear the package profile if this was an upgrade and the package
4300      * version was updated.
4301      */
maybeClearProfilesForUpgradesLI( @ullable PackageSetting originalPkgSetting, @NonNull AndroidPackage pkg)4302     private void maybeClearProfilesForUpgradesLI(
4303             @Nullable PackageSetting originalPkgSetting,
4304             @NonNull AndroidPackage pkg) {
4305         if (originalPkgSetting == null || !mPm.isDeviceUpgrading()) {
4306             return;
4307         }
4308         if (originalPkgSetting.getVersionCode() == pkg.getLongVersionCode()) {
4309             return;
4310         }
4311 
4312         mAppDataHelper.clearAppProfilesLIF(pkg);
4313         if (DEBUG_INSTALL) {
4314             Slog.d(TAG, originalPkgSetting.getPackageName()
4315                     + " clear profile due to version change "
4316                     + originalPkgSetting.getVersionCode() + " != "
4317                     + pkg.getLongVersionCode());
4318         }
4319     }
4320 
4321     /**
4322      * Returns the original package setting.
4323      * <p>A package can migrate its name during an update. In this scenario, a package
4324      * designates a set of names that it considers as one of its original names.
4325      * <p>An original package must be signed identically and it must have the same
4326      * shared user [if any].
4327      */
4328     @GuardedBy("mPm.mLock")
4329     @Nullable
getOriginalPackageLocked(@onNull AndroidPackage pkg, @Nullable String renamedPkgName)4330     private PackageSetting getOriginalPackageLocked(@NonNull AndroidPackage pkg,
4331             @Nullable String renamedPkgName) {
4332         if (ScanPackageUtils.isPackageRenamed(pkg, renamedPkgName)) {
4333             return null;
4334         }
4335         for (int i = ArrayUtils.size(pkg.getOriginalPackages()) - 1; i >= 0; --i) {
4336             final PackageSetting originalPs =
4337                     mPm.mSettings.getPackageLPr(pkg.getOriginalPackages().get(i));
4338             if (originalPs != null) {
4339                 // the package is already installed under its original name...
4340                 // but, should we use it?
4341                 if (!verifyPackageUpdateLPr(originalPs, pkg)) {
4342                     // the new package is incompatible with the original
4343                     continue;
4344                 } else if (mPm.mSettings.getSharedUserSettingLPr(originalPs) != null) {
4345                     final String sharedUserSettingsName =
4346                             mPm.mSettings.getSharedUserSettingLPr(originalPs).name;
4347                     if (!sharedUserSettingsName.equals(pkg.getSharedUserId())) {
4348                         // the shared user id is incompatible with the original
4349                         Slog.w(TAG, "Unable to migrate data from " + originalPs.getPackageName()
4350                                 + " to " + pkg.getPackageName() + ": old shared user settings name "
4351                                 + sharedUserSettingsName
4352                                 + " differs from " + pkg.getSharedUserId());
4353                         continue;
4354                     }
4355                     // TODO: Add case when shared user id is added [b/28144775]
4356                 } else {
4357                     if (DEBUG_UPGRADE) {
4358                         Log.v(TAG, "Renaming new package "
4359                                 + pkg.getPackageName() + " to old name "
4360                                 + originalPs.getPackageName());
4361                     }
4362                 }
4363                 return originalPs;
4364             }
4365         }
4366         return null;
4367     }
4368 
4369     @GuardedBy("mPm.mLock")
verifyPackageUpdateLPr(PackageSetting oldPkg, AndroidPackage newPkg)4370     private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, AndroidPackage newPkg) {
4371         if ((oldPkg.getFlags() & ApplicationInfo.FLAG_SYSTEM) == 0) {
4372             Slog.w(TAG, "Unable to update from " + oldPkg.getPackageName()
4373                     + " to " + newPkg.getPackageName()
4374                     + ": old package not in system partition");
4375             return false;
4376         } else if (mPm.mPackages.get(oldPkg.getPackageName()) != null) {
4377             Slog.w(TAG, "Unable to update from " + oldPkg.getPackageName()
4378                     + " to " + newPkg.getPackageName()
4379                     + ": old package still exists");
4380             return false;
4381         }
4382         return true;
4383     }
4384 
4385     /**
4386      * Asserts the parsed package is valid according to the given policy. If the
4387      * package is invalid, for whatever reason, throws {@link PackageManagerException}.
4388      * <p>
4389      * Implementation detail: This method must NOT have any side effects. It would
4390      * ideally be static, but, it requires locks to read system state.
4391      *
4392      * @throws PackageManagerException If the package fails any of the validation checks
4393      */
assertPackageIsValid(AndroidPackage pkg, final @ParsingPackageUtils.ParseFlags int parseFlags, final @PackageManagerService.ScanFlags int scanFlags)4394     private void assertPackageIsValid(AndroidPackage pkg,
4395             final @ParsingPackageUtils.ParseFlags int parseFlags,
4396             final @PackageManagerService.ScanFlags int scanFlags)
4397             throws PackageManagerException {
4398         if ((parseFlags & ParsingPackageUtils.PARSE_ENFORCE_CODE) != 0) {
4399             ScanPackageUtils.assertCodePolicy(pkg);
4400         }
4401 
4402         if (pkg.getPath() == null) {
4403             // Bail out. The resource and code paths haven't been set.
4404             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
4405                     "Code and resource paths haven't been set correctly");
4406         }
4407 
4408         // Check that there is an APEX package with the same name only during install/first boot
4409         // after OTA.
4410         final boolean isUserInstall = (scanFlags & SCAN_BOOTING) == 0;
4411         final boolean isFirstBootOrUpgrade = (scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0;
4412         // It is allowed to install a new APEX with the same name. But there shouldn't be
4413         // conflicting names between APK and APEX.
4414         final boolean installApex = (scanFlags & SCAN_AS_APEX) != 0;
4415         if ((isUserInstall || isFirstBootOrUpgrade)
4416                 && mPm.snapshotComputer().isApexPackage(pkg.getPackageName())
4417                 && !installApex) {
4418             throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
4419                     pkg.getPackageName()
4420                             + " is an APEX package and can't be installed as an APK.");
4421         }
4422 
4423         // Make sure we're not adding any bogus keyset info
4424         final KeySetManagerService ksms = mPm.mSettings.getKeySetManagerService();
4425         ksms.assertScannedPackageValid(pkg);
4426 
4427         synchronized (mPm.mLock) {
4428             // The special "android" package can only be defined once
4429             if (pkg.getPackageName().equals("android")) {
4430                 if (mPm.getCoreAndroidApplication() != null) {
4431                     Slog.w(TAG, "*************************************************");
4432                     Slog.w(TAG, "Core android package being redefined.  Skipping.");
4433                     Slog.w(TAG, " codePath=" + pkg.getPath());
4434                     Slog.w(TAG, "*************************************************");
4435                     throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
4436                             "Core android package being redefined.  Skipping.");
4437                 }
4438             }
4439 
4440             // A package name must be unique; don't allow duplicates
4441             if ((scanFlags & SCAN_NEW_INSTALL) == 0
4442                     && mPm.mPackages.containsKey(pkg.getPackageName())) {
4443                 throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
4444                         "Application package " + pkg.getPackageName()
4445                                 + " already installed.  Skipping duplicate.");
4446             }
4447 
4448             if (pkg.isStaticSharedLibrary()) {
4449                 // Static libs have a synthetic package name containing the version
4450                 // but we still want the base name to be unique.
4451                 if ((scanFlags & SCAN_NEW_INSTALL) == 0
4452                         && mPm.mPackages.containsKey(pkg.getManifestPackageName())) {
4453                     throw PackageManagerException.ofInternalError(
4454                             "Duplicate static shared lib provider package",
4455                             PackageManagerException.INTERNAL_ERROR_DUP_STATIC_SHARED_LIB_PROVIDER);
4456                 }
4457                 ScanPackageUtils.assertStaticSharedLibraryIsValid(pkg, scanFlags);
4458                 assertStaticSharedLibraryVersionCodeIsValid(pkg);
4459             }
4460 
4461             // If we're only installing presumed-existing packages, require that the
4462             // scanned APK is both already known and at the path previously established
4463             // for it.  Previously unknown packages we pick up normally, but if we have an
4464             // a priori expectation about this package's install presence, enforce it.
4465             // With a singular exception for new system packages. When an OTA contains
4466             // a new system package, we allow the codepath to change from a system location
4467             // to the user-installed location. If we don't allow this change, any newer,
4468             // user-installed version of the application will be ignored.
4469             if ((scanFlags & SCAN_REQUIRE_KNOWN) != 0) {
4470                 if (mPm.isExpectingBetter(pkg.getPackageName())) {
4471                     Slog.w(TAG, "Relax SCAN_REQUIRE_KNOWN requirement for package "
4472                             + pkg.getPackageName());
4473                 } else {
4474                     PackageSetting known = mPm.mSettings.getPackageLPr(pkg.getPackageName());
4475                     if (known != null) {
4476                         if (DEBUG_PACKAGE_SCANNING) {
4477                             Log.d(TAG, "Examining " + pkg.getPath()
4478                                     + " and requiring known path " + known.getPathString());
4479                         }
4480                         if (!pkg.getPath().equals(known.getPathString())) {
4481                             throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED,
4482                                     "Application package " + pkg.getPackageName()
4483                                             + " found at " + pkg.getPath()
4484                                             + " but expected at " + known.getPathString()
4485                                             + "; ignoring.");
4486                         }
4487                     } else {
4488                         throw new PackageManagerException(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
4489                                 "Application package " + pkg.getPackageName()
4490                                         + " not found; ignoring.");
4491                     }
4492                 }
4493             }
4494 
4495             // Verify that this new package doesn't have any content providers
4496             // that conflict with existing packages.  Only do this if the
4497             // package isn't already installed, since we don't want to break
4498             // things that are installed.
4499             if ((scanFlags & SCAN_NEW_INSTALL) != 0) {
4500                 mPm.mComponentResolver.assertProvidersNotDefined(pkg);
4501             }
4502 
4503             // If this package has defined explicit processes, then ensure that these are
4504             // the only processes used by its components.
4505             ScanPackageUtils.assertProcessesAreValid(pkg);
4506 
4507             // Verify that packages sharing a user with a privileged app are marked as privileged.
4508             assertPackageWithSharedUserIdIsPrivileged(pkg);
4509 
4510             // Apply policies specific for runtime resource overlays (RROs).
4511             if (pkg.getOverlayTarget() != null) {
4512                 assertOverlayIsValid(pkg, parseFlags, scanFlags);
4513             }
4514 
4515             // Ensure the package is signed with at least the minimum signature scheme version
4516             // required for its target SDK.
4517             ScanPackageUtils.assertMinSignatureSchemeIsValid(pkg, parseFlags);
4518         }
4519     }
4520 
assertStaticSharedLibraryVersionCodeIsValid(AndroidPackage pkg)4521     private void assertStaticSharedLibraryVersionCodeIsValid(AndroidPackage pkg)
4522             throws PackageManagerException {
4523         // The version codes must be ordered as lib versions
4524         long minVersionCode = Long.MIN_VALUE;
4525         long maxVersionCode = Long.MAX_VALUE;
4526 
4527         WatchedLongSparseArray<SharedLibraryInfo> versionedLib =
4528                 mSharedLibraries.getSharedLibraryInfos(pkg.getStaticSharedLibraryName());
4529         if (versionedLib != null) {
4530             final int versionCount = versionedLib.size();
4531             for (int i = 0; i < versionCount; i++) {
4532                 SharedLibraryInfo libInfo = versionedLib.valueAt(i);
4533                 final long libVersionCode = libInfo.getDeclaringPackage()
4534                         .getLongVersionCode();
4535                 if (libInfo.getLongVersion() < pkg.getStaticSharedLibraryVersion()) {
4536                     minVersionCode = Math.max(minVersionCode, libVersionCode + 1);
4537                 } else if (libInfo.getLongVersion()
4538                         > pkg.getStaticSharedLibraryVersion()) {
4539                     maxVersionCode = Math.min(maxVersionCode, libVersionCode - 1);
4540                 } else {
4541                     minVersionCode = maxVersionCode = libVersionCode;
4542                     break;
4543                 }
4544             }
4545         }
4546         if (pkg.getLongVersionCode() < minVersionCode
4547                 || pkg.getLongVersionCode() > maxVersionCode) {
4548             throw PackageManagerException.ofInternalError("Static shared"
4549                     + " lib version codes must be ordered as lib versions",
4550                     PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_VERSION_CODES_ORDER);
4551         }
4552     }
4553 
assertOverlayIsValid(AndroidPackage pkg, @ParsingPackageUtils.ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags)4554     private void assertOverlayIsValid(AndroidPackage pkg,
4555             @ParsingPackageUtils.ParseFlags int parseFlags,
4556             @PackageManagerService.ScanFlags int scanFlags) throws PackageManagerException {
4557         // System overlays have some restrictions on their use of the 'static' state.
4558         if ((scanFlags & SCAN_AS_SYSTEM) != 0) {
4559             // We are scanning a system overlay. This can be the first scan of the
4560             // system/vendor/oem partition, or an update to the system overlay.
4561             if ((parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) == 0) {
4562                 // This must be an update to a system overlay. Immutable overlays cannot be
4563                 // upgraded.
4564                 if (!mPm.isOverlayMutable(pkg.getPackageName())) {
4565                     throw PackageManagerException.ofInternalError("Overlay "
4566                             + pkg.getPackageName()
4567                             + " is static and cannot be upgraded.",
4568                             PackageManagerException.INTERNAL_ERROR_SYSTEM_OVERLAY_STATIC);
4569                 }
4570             } else {
4571                 if ((scanFlags & SCAN_AS_VENDOR) != 0) {
4572                     if (pkg.getTargetSdkVersion() < ScanPackageUtils.getVendorPartitionVersion()) {
4573                         Slog.w(TAG, "System overlay " + pkg.getPackageName()
4574                                 + " targets an SDK below the required SDK level of vendor"
4575                                 + " overlays ("
4576                                 + ScanPackageUtils.getVendorPartitionVersion()
4577                                 + ")."
4578                                 + " This will become an install error in a future release");
4579                     }
4580                 } else if (pkg.getTargetSdkVersion() < Build.VERSION.SDK_INT) {
4581                     Slog.w(TAG, "System overlay " + pkg.getPackageName()
4582                             + " targets an SDK below the required SDK level of system"
4583                             + " overlays (" + Build.VERSION.SDK_INT + ")."
4584                             + " This will become an install error in a future release");
4585                 }
4586             }
4587         } else {
4588             // A non-preloaded overlay packages must have targetSdkVersion >= Q, or be
4589             // signed with the platform certificate. Check this in increasing order of
4590             // computational cost.
4591             if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.Q) {
4592                 final PackageSetting platformPkgSetting;
4593                 synchronized (mPm.mLock) {
4594                     platformPkgSetting = mPm.mSettings.getPackageLPr("android");
4595                 }
4596                 if (!comparePackageSignatures(platformPkgSetting, pkg.getSigningDetails())) {
4597                     throw PackageManagerException.ofInternalError("Overlay "
4598                             + pkg.getPackageName()
4599                             + " must target Q or later, "
4600                             + "or be signed with the platform certificate",
4601                             PackageManagerException.INTERNAL_ERROR_OVERLAY_LOW_TARGET_SDK);
4602                 }
4603             }
4604 
4605             // A non-preloaded overlay package, without <overlay android:targetName>, will
4606             // only be used if it is signed with the same certificate as its target OR if
4607             // it is signed with the same certificate as a reference package declared
4608             // in 'overlay-config-signature' tag of SystemConfig.
4609             // If the target is already installed or 'overlay-config-signature' tag in
4610             // SystemConfig is set, check this here to augment the last line of defense
4611             // which is OMS.
4612             if (pkg.getOverlayTargetOverlayableName() == null) {
4613                 final PackageSetting targetPkgSetting;
4614                 synchronized (mPm.mLock) {
4615                     targetPkgSetting = mPm.mSettings.getPackageLPr(pkg.getOverlayTarget());
4616                 }
4617                 if (targetPkgSetting != null) {
4618                     if (!comparePackageSignatures(targetPkgSetting, pkg.getSigningDetails())) {
4619                         // check reference signature
4620                         if (mPm.mOverlayConfigSignaturePackage == null) {
4621                             throw PackageManagerException.ofInternalError("Overlay "
4622                                     + pkg.getPackageName() + " and target "
4623                                     + pkg.getOverlayTarget() + " signed with"
4624                                     + " different certificates, and the overlay lacks"
4625                                     + " <overlay android:targetName>",
4626                                     PackageManagerException.INTERNAL_ERROR_OVERLAY_SIGNATURE1);
4627                         }
4628                         final PackageSetting refPkgSetting;
4629                         synchronized (mPm.mLock) {
4630                             refPkgSetting = mPm.mSettings.getPackageLPr(
4631                                     mPm.mOverlayConfigSignaturePackage);
4632                         }
4633                         if (!comparePackageSignatures(refPkgSetting, pkg.getSigningDetails())) {
4634                             throw PackageManagerException.ofInternalError("Overlay "
4635                                     + pkg.getPackageName() + " signed with a different "
4636                                     + "certificate than both the reference package and "
4637                                     + "target " + pkg.getOverlayTarget() + ", and the "
4638                                     + "overlay lacks <overlay android:targetName>",
4639                                     PackageManagerException.INTERNAL_ERROR_OVERLAY_SIGNATURE2);
4640                         }
4641                     }
4642                 }
4643             }
4644         }
4645     }
4646 
assertPackageWithSharedUserIdIsPrivileged(AndroidPackage pkg)4647     private void assertPackageWithSharedUserIdIsPrivileged(AndroidPackage pkg)
4648             throws PackageManagerException {
4649         if (!AndroidPackageLegacyUtils.isPrivileged(pkg)
4650                 && (pkg.getSharedUserId() != null)
4651                 && !pkg.isLeavingSharedUser()) {
4652             SharedUserSetting sharedUserSetting = null;
4653             try {
4654                 synchronized (mPm.mLock) {
4655                     sharedUserSetting = mPm.mSettings.getSharedUserLPw(pkg.getSharedUserId(),
4656                             0, 0, false);
4657                 }
4658             } catch (PackageManagerException ignore) {
4659             }
4660             if (sharedUserSetting != null && sharedUserSetting.isPrivileged()) {
4661                 // Exempt SharedUsers signed with the platform key.
4662                 final PackageSetting platformPkgSetting;
4663                 synchronized (mPm.mLock) {
4664                     platformPkgSetting = mPm.mSettings.getPackageLPr("android");
4665                 }
4666                 if (!comparePackageSignatures(platformPkgSetting, pkg.getSigningDetails())) {
4667                     throw PackageManagerException.ofInternalError("Apps that share a user with a "
4668                             + "privileged app must themselves be marked as privileged. "
4669                             + pkg.getPackageName() + " shares privileged user "
4670                             + pkg.getSharedUserId() + ".",
4671                             PackageManagerException.INTERNAL_ERROR_NOT_PRIV_SHARED_USER);
4672                 }
4673             }
4674         }
4675     }
4676 
adjustScanFlags( @ackageManagerService.ScanFlags int scanFlags, @Nullable PackageSetting existingPkgSetting, @Nullable PackageSetting disabledPkgSetting, UserHandle user, @NonNull AndroidPackage pkg)4677     private @PackageManagerService.ScanFlags int adjustScanFlags(
4678             @PackageManagerService.ScanFlags int scanFlags,
4679             @Nullable PackageSetting existingPkgSetting,
4680             @Nullable PackageSetting disabledPkgSetting, UserHandle user,
4681             @NonNull AndroidPackage pkg) {
4682         scanFlags = ScanPackageUtils.adjustScanFlagsWithPackageSetting(scanFlags, existingPkgSetting,
4683                 disabledPkgSetting, user);
4684 
4685         // Exception for privileged apps that share a user with a priv-app.
4686         final boolean skipVendorPrivilegeScan = ((scanFlags & SCAN_AS_VENDOR) != 0)
4687                 && ScanPackageUtils.getVendorPartitionVersion() < 28;
4688         if (((scanFlags & SCAN_AS_PRIVILEGED) == 0)
4689                 && !AndroidPackageLegacyUtils.isPrivileged(pkg)
4690                 && (pkg.getSharedUserId() != null)
4691                 && !skipVendorPrivilegeScan
4692                 && !pkg.isLeavingSharedUser()) {
4693             SharedUserSetting sharedUserSetting = null;
4694             synchronized (mPm.mLock) {
4695                 try {
4696                     sharedUserSetting = mPm.mSettings.getSharedUserLPw(pkg.getSharedUserId(), 0,
4697                             0, false);
4698                 } catch (PackageManagerException ignore) {
4699                 }
4700                 if (sharedUserSetting != null && sharedUserSetting.isPrivileged()) {
4701                     // Exempt SharedUsers signed with the platform key.
4702                     // TODO(b/72378145) Fix this exemption. Force signature apps
4703                     // to allowlist their privileged permissions just like other
4704                     // priv-apps.
4705                     PackageSetting platformPkgSetting = mPm.mSettings.getPackageLPr("android");
4706                     if ((compareSignatures(platformPkgSetting.getSigningDetails(),
4707                             pkg.getSigningDetails()) != PackageManager.SIGNATURE_MATCH)) {
4708                         scanFlags |= SCAN_AS_PRIVILEGED;
4709                     }
4710                 }
4711             }
4712         }
4713 
4714         return scanFlags;
4715     }
4716 }
4717