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