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