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