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