1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.pm;
18 
19 import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
20 import static android.content.pm.PackageManager.INSTALL_FAILED_PROCESS_NOT_DEFINED;
21 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES;
22 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
23 
24 import static com.android.server.pm.PackageManagerService.DEBUG_ABI_SELECTION;
25 import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
26 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
27 import static com.android.server.pm.PackageManagerService.SCAN_AS_APEX;
28 import static com.android.server.pm.PackageManagerService.SCAN_AS_FULL_APP;
29 import static com.android.server.pm.PackageManagerService.SCAN_AS_INSTANT_APP;
30 import static com.android.server.pm.PackageManagerService.SCAN_AS_ODM;
31 import static com.android.server.pm.PackageManagerService.SCAN_AS_OEM;
32 import static com.android.server.pm.PackageManagerService.SCAN_AS_PRIVILEGED;
33 import static com.android.server.pm.PackageManagerService.SCAN_AS_PRODUCT;
34 import static com.android.server.pm.PackageManagerService.SCAN_AS_STOPPED_SYSTEM_APP;
35 import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM;
36 import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM_EXT;
37 import static com.android.server.pm.PackageManagerService.SCAN_AS_VENDOR;
38 import static com.android.server.pm.PackageManagerService.SCAN_AS_VIRTUAL_PRELOAD;
39 import static com.android.server.pm.PackageManagerService.SCAN_BOOTING;
40 import static com.android.server.pm.PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE;
41 import static com.android.server.pm.PackageManagerService.SCAN_MOVE;
42 import static com.android.server.pm.PackageManagerService.SCAN_NEW_INSTALL;
43 import static com.android.server.pm.PackageManagerService.SCAN_NO_DEX;
44 import static com.android.server.pm.PackageManagerService.SCAN_UPDATE_TIME;
45 import static com.android.server.pm.PackageManagerService.TAG;
46 import static com.android.server.pm.PackageManagerServiceUtils.compareSignatures;
47 import static com.android.server.pm.PackageManagerServiceUtils.compressedFileExists;
48 import static com.android.server.pm.PackageManagerServiceUtils.deriveAbiOverride;
49 import static com.android.server.pm.PackageManagerServiceUtils.getLastModifiedTime;
50 
51 import android.annotation.NonNull;
52 import android.annotation.Nullable;
53 import android.content.pm.ApplicationInfo;
54 import android.content.pm.PackageManager;
55 import android.content.pm.SharedLibraryInfo;
56 import android.content.pm.SigningDetails;
57 import android.content.pm.parsing.result.ParseResult;
58 import android.content.pm.parsing.result.ParseTypeImpl;
59 import android.os.Build;
60 import android.os.Environment;
61 import android.os.Process;
62 import android.os.SystemProperties;
63 import android.os.Trace;
64 import android.os.UserHandle;
65 import android.text.TextUtils;
66 import android.util.ArrayMap;
67 import android.util.ArraySet;
68 import android.util.Log;
69 import android.util.Pair;
70 import android.util.Slog;
71 import android.util.apk.ApkSignatureVerifier;
72 import android.util.jar.StrictJarFile;
73 
74 import com.android.internal.annotations.GuardedBy;
75 import com.android.internal.annotations.VisibleForTesting;
76 import com.android.internal.util.ArrayUtils;
77 import com.android.server.SystemConfig;
78 import com.android.server.pm.parsing.PackageInfoUtils;
79 import com.android.server.pm.parsing.library.PackageBackwardCompatibility;
80 import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
81 import com.android.server.pm.parsing.pkg.ParsedPackage;
82 import com.android.server.pm.pkg.AndroidPackage;
83 import com.android.server.pm.pkg.PackageStateUtils;
84 import com.android.server.pm.pkg.component.ComponentMutateUtils;
85 import com.android.server.pm.pkg.component.ParsedActivity;
86 import com.android.server.pm.pkg.component.ParsedMainComponent;
87 import com.android.server.pm.pkg.component.ParsedProcess;
88 import com.android.server.pm.pkg.component.ParsedProvider;
89 import com.android.server.pm.pkg.component.ParsedService;
90 import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
91 import com.android.server.utils.WatchedArraySet;
92 
93 import dalvik.system.VMRuntime;
94 
95 import java.io.File;
96 import java.io.IOException;
97 import java.util.ArrayList;
98 import java.util.List;
99 import java.util.Map;
100 import java.util.Objects;
101 import java.util.UUID;
102 
103 /**
104  * Helper class that handles package scanning logic
105  */
106 final class ScanPackageUtils {
107     /**
108      * Just scans the package without any side effects.
109      *
110      * @param injector injector for acquiring dependencies
111      * @param request Information about the package to be scanned
112      * @param isUnderFactoryTest Whether or not the device is under factory test
113      * @param currentTime The current time, in millis
114      * @return The results of the scan
115      */
116     @GuardedBy("mPm.mInstallLock")
117     @VisibleForTesting
118     @NonNull
scanPackageOnlyLI(@onNull ScanRequest request, PackageManagerServiceInjector injector, boolean isUnderFactoryTest, long currentTime)119     public static ScanResult scanPackageOnlyLI(@NonNull ScanRequest request,
120             PackageManagerServiceInjector injector,
121             boolean isUnderFactoryTest, long currentTime)
122             throws PackageManagerException {
123         final PackageAbiHelper packageAbiHelper = injector.getAbiHelper();
124         ParsedPackage parsedPackage = request.mParsedPackage;
125         PackageSetting pkgSetting = request.mPkgSetting;
126         final PackageSetting disabledPkgSetting = request.mDisabledPkgSetting;
127         final PackageSetting originalPkgSetting = request.mOriginalPkgSetting;
128         final @ParsingPackageUtils.ParseFlags int parseFlags = request.mParseFlags;
129         final @PackageManagerService.ScanFlags int scanFlags = request.mScanFlags;
130         final String realPkgName = request.mRealPkgName;
131         final SharedUserSetting oldSharedUserSetting = request.mOldSharedUserSetting;
132         final SharedUserSetting sharedUserSetting = request.mSharedUserSetting;
133         final UserHandle user = request.mUser;
134         final boolean isPlatformPackage = request.mIsPlatformPackage;
135 
136         List<String> changedAbiCodePath = null;
137 
138         if (DEBUG_PACKAGE_SCANNING) {
139             if ((parseFlags & ParsingPackageUtils.PARSE_CHATTY) != 0) {
140                 Log.d(TAG, "Scanning package " + parsedPackage.getPackageName());
141             }
142         }
143 
144         // Initialize package source and resource directories
145         final File destCodeFile = new File(parsedPackage.getPath());
146 
147         // We keep references to the derived CPU Abis from settings in oder to reuse
148         // them in the case where we're not upgrading or booting for the first time.
149         String primaryCpuAbiFromSettings = null;
150         String secondaryCpuAbiFromSettings = null;
151         boolean needToDeriveAbi = (scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0;
152         if (!needToDeriveAbi) {
153             if (pkgSetting != null) {
154                 // TODO(b/154610922): if it is not first boot or upgrade, we should directly use
155                 // API info from existing package setting. However, stub packages currently do not
156                 // preserve ABI info, thus the special condition check here. Remove the special
157                 // check after we fix the stub generation.
158                 if (pkgSetting.getPkg() != null && pkgSetting.getPkg().isStub()) {
159                     needToDeriveAbi = true;
160                 } else {
161                     primaryCpuAbiFromSettings = pkgSetting.getPrimaryCpuAbiLegacy();
162                     secondaryCpuAbiFromSettings = pkgSetting.getSecondaryCpuAbiLegacy();
163                 }
164             } else {
165                 // Re-scanning a system package after uninstalling updates; need to derive ABI
166                 needToDeriveAbi = true;
167             }
168         }
169 
170         if (pkgSetting != null && oldSharedUserSetting != sharedUserSetting) {
171             PackageManagerService.reportSettingsProblem(Log.WARN,
172                     "Package " + parsedPackage.getPackageName() + " shared user changed from "
173                             + (oldSharedUserSetting != null
174                             ? oldSharedUserSetting.name : "<nothing>")
175                             + " to "
176                             + (sharedUserSetting != null ? sharedUserSetting.name : "<nothing>")
177                             + "; replacing with new");
178             pkgSetting = null;
179         }
180 
181         String[] usesSdkLibraries = null;
182         if (!parsedPackage.getUsesSdkLibraries().isEmpty()) {
183             usesSdkLibraries = new String[parsedPackage.getUsesSdkLibraries().size()];
184             parsedPackage.getUsesSdkLibraries().toArray(usesSdkLibraries);
185         }
186 
187         String[] usesStaticLibraries = null;
188         if (!parsedPackage.getUsesStaticLibraries().isEmpty()) {
189             usesStaticLibraries = new String[parsedPackage.getUsesStaticLibraries().size()];
190             parsedPackage.getUsesStaticLibraries().toArray(usesStaticLibraries);
191         }
192 
193         final UUID newDomainSetId = injector.getDomainVerificationManagerInternal().generateNewId();
194 
195         // TODO(b/135203078): Remove appInfoFlag usage in favor of individually assigned booleans
196         //  to avoid adding something that's unsupported due to lack of state, since it's called
197         //  with null.
198         final boolean createNewPackage = (pkgSetting == null);
199         if (createNewPackage) {
200             final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;
201             final boolean virtualPreload = (scanFlags & SCAN_AS_VIRTUAL_PRELOAD) != 0;
202             final boolean isStoppedSystemApp = (scanFlags & SCAN_AS_STOPPED_SYSTEM_APP) != 0;
203 
204             // Flags contain system values stored in the server variant of AndroidPackage,
205             // and so the server-side PackageInfoUtils is still called, even without a
206             // PackageSetting to pass in.
207             int pkgFlags = PackageInfoUtils.appInfoFlags(parsedPackage, null);
208             int pkgPrivateFlags = PackageInfoUtils.appInfoPrivateFlags(parsedPackage, null);
209 
210             // REMOVE SharedUserSetting from method; update in a separate call
211             pkgSetting = Settings.createNewSetting(parsedPackage.getPackageName(),
212                     originalPkgSetting, disabledPkgSetting, realPkgName, sharedUserSetting,
213                     destCodeFile, parsedPackage.getNativeLibraryRootDir(),
214                     AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage),
215                     AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage),
216                     parsedPackage.getLongVersionCode(), pkgFlags, pkgPrivateFlags, user,
217                     true /*allowInstall*/, instantApp, virtualPreload, isStoppedSystemApp,
218                     UserManagerService.getInstance(), usesSdkLibraries,
219                     parsedPackage.getUsesSdkLibrariesVersionsMajor(), usesStaticLibraries,
220                     parsedPackage.getUsesStaticLibrariesVersions(), parsedPackage.getMimeGroups(),
221                     newDomainSetId);
222         } else {
223             // make a deep copy to avoid modifying any existing system state.
224             pkgSetting = new PackageSetting(pkgSetting);
225             pkgSetting.setPkg(parsedPackage);
226 
227             // REMOVE SharedUserSetting from method; update in a separate call.
228             //
229             // TODO(narayan): This update is bogus. nativeLibraryDir & primaryCpuAbi,
230             // secondaryCpuAbi are not known at this point so we always update them
231             // to null here, only to reset them at a later point.
232             Settings.updatePackageSetting(pkgSetting, disabledPkgSetting, oldSharedUserSetting,
233                     sharedUserSetting, destCodeFile, parsedPackage.getNativeLibraryDir(),
234                     pkgSetting.getPrimaryCpuAbi(),
235                     pkgSetting.getSecondaryCpuAbi(),
236                     PackageInfoUtils.appInfoFlags(parsedPackage, pkgSetting),
237                     PackageInfoUtils.appInfoPrivateFlags(parsedPackage, pkgSetting),
238                     UserManagerService.getInstance(),
239                     usesSdkLibraries, parsedPackage.getUsesSdkLibrariesVersionsMajor(),
240                     usesStaticLibraries, parsedPackage.getUsesStaticLibrariesVersions(),
241                     parsedPackage.getMimeGroups(), newDomainSetId);
242         }
243         if (createNewPackage && originalPkgSetting != null) {
244             // This is the initial transition from the original package, so,
245             // fix up the new package's name now. We must do this after looking
246             // up the package under its new name, so getPackageLP takes care of
247             // fiddling things correctly.
248             parsedPackage.setPackageName(originalPkgSetting.getPackageName());
249 
250             // File a report about this.
251             String msg = "New package " + pkgSetting.getRealName()
252                     + " renamed to replace old package " + pkgSetting.getPackageName();
253             PackageManagerService.reportSettingsProblem(Log.WARN, msg);
254         }
255 
256         final int userId = (user == null ? UserHandle.USER_SYSTEM : user.getIdentifier());
257         // for existing packages, change the install state; but, only if it's explicitly specified
258         if (!createNewPackage) {
259             final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;
260             final boolean fullApp = (scanFlags & SCAN_AS_FULL_APP) != 0;
261             setInstantAppForUser(injector, pkgSetting, userId, instantApp, fullApp);
262         }
263         // TODO(patb): see if we can do away with disabled check here.
264         if (disabledPkgSetting != null
265                 || (0 != (scanFlags & SCAN_NEW_INSTALL)
266                 && pkgSetting != null && pkgSetting.isSystem())) {
267             pkgSetting.getPkgState().setUpdatedSystemApp(true);
268         }
269 
270         pkgSetting.getTransientState().setSeInfo(SELinuxMMAC.getSeInfo(pkgSetting, parsedPackage,
271                 sharedUserSetting, injector.getCompatibility()));
272 
273         if (pkgSetting.isSystem()) {
274             configurePackageComponents(parsedPackage);
275         }
276 
277         final String cpuAbiOverride = deriveAbiOverride(request.mCpuAbiOverride);
278         final boolean isSystemApp = pkgSetting.isSystem();
279         final boolean isUpdatedSystemApp = pkgSetting.isUpdatedSystemApp();
280 
281         final File appLib32InstallDir = getAppLib32InstallDir();
282         if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
283             if (needToDeriveAbi) {
284                 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi");
285                 final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths> derivedAbi =
286                         packageAbiHelper.derivePackageAbi(parsedPackage, isSystemApp,
287                                 isUpdatedSystemApp, cpuAbiOverride, appLib32InstallDir);
288                 derivedAbi.first.applyTo(parsedPackage);
289                 derivedAbi.second.applyTo(parsedPackage);
290                 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
291 
292                 // Some system apps still use directory structure for native libraries
293                 // in which case we might end up not detecting abi solely based on apk
294                 // structure. Try to detect abi based on directory structure.
295 
296                 String pkgRawPrimaryCpuAbi = AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage);
297                 if (isSystemApp && !isUpdatedSystemApp && pkgRawPrimaryCpuAbi == null) {
298                     final PackageAbiHelper.Abis abis = packageAbiHelper.getBundledAppAbis(
299                             parsedPackage);
300                     abis.applyTo(parsedPackage);
301                     abis.applyTo(pkgSetting);
302                     final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths =
303                             packageAbiHelper.deriveNativeLibraryPaths(parsedPackage, isSystemApp,
304                                     isUpdatedSystemApp, appLib32InstallDir);
305                     nativeLibraryPaths.applyTo(parsedPackage);
306                 }
307             } else {
308                 // This is not a first boot or an upgrade, don't bother deriving the
309                 // ABI during the scan. Instead, trust the value that was stored in the
310                 // package setting.
311                 parsedPackage.setPrimaryCpuAbi(primaryCpuAbiFromSettings)
312                         .setSecondaryCpuAbi(secondaryCpuAbiFromSettings);
313 
314                 final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths =
315                         packageAbiHelper.deriveNativeLibraryPaths(parsedPackage, isSystemApp,
316                                 isUpdatedSystemApp, appLib32InstallDir);
317                 nativeLibraryPaths.applyTo(parsedPackage);
318 
319                 if (DEBUG_ABI_SELECTION) {
320                     Slog.i(TAG, "Using ABIS and native lib paths from settings : "
321                             + parsedPackage.getPackageName() + " "
322                             + AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage)
323                             + ", "
324                             + AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage));
325                 }
326             }
327         } else {
328             if ((scanFlags & SCAN_MOVE) != 0) {
329                 // We haven't run dex-opt for this move (since we've moved the compiled output too)
330                 // but we already have this packages package info in the PackageSetting. We just
331                 // use that and derive the native library path based on the new code path.
332                 parsedPackage.setPrimaryCpuAbi(pkgSetting.getPrimaryCpuAbiLegacy())
333                         .setSecondaryCpuAbi(pkgSetting.getSecondaryCpuAbiLegacy());
334             }
335 
336             // Set native library paths again. For moves, the path will be updated based on the
337             // ABIs we've determined above. For non-moves, the path will be updated based on the
338             // ABIs we determined during compilation, but the path will depend on the final
339             // package path (after the rename away from the stage path).
340             final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths =
341                     packageAbiHelper.deriveNativeLibraryPaths(parsedPackage, isSystemApp,
342                             isUpdatedSystemApp, appLib32InstallDir);
343             nativeLibraryPaths.applyTo(parsedPackage);
344         }
345 
346         // This is a special case for the "system" package, where the ABI is
347         // dictated by the zygote configuration (and init.rc). We should keep track
348         // of this ABI so that we can deal with "normal" applications that run under
349         // the same UID correctly.
350         if (isPlatformPackage) {
351             parsedPackage.setPrimaryCpuAbi(VMRuntime.getRuntime().is64Bit()
352                     ? Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0]);
353         }
354 
355         // If there's a mismatch between the abi-override in the package setting
356         // and the abiOverride specified for the install. Warn about this because we
357         // would've already compiled the app without taking the package setting into
358         // account.
359         if ((scanFlags & SCAN_NO_DEX) == 0 && (scanFlags & SCAN_NEW_INSTALL) != 0) {
360             if (cpuAbiOverride == null) {
361                 Slog.w(TAG, "Ignoring persisted ABI override for package "
362                         + parsedPackage.getPackageName());
363             }
364         }
365 
366         pkgSetting.setPrimaryCpuAbi(AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage))
367                 .setSecondaryCpuAbi(AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage))
368                 .setCpuAbiOverride(cpuAbiOverride);
369 
370         if (DEBUG_ABI_SELECTION) {
371             Slog.d(TAG, "Resolved nativeLibraryRoot for " + parsedPackage.getPackageName()
372                     + " to root=" + parsedPackage.getNativeLibraryRootDir()
373                     + ", to dir=" + parsedPackage.getNativeLibraryDir()
374                     + ", isa=" + parsedPackage.isNativeLibraryRootRequiresIsa());
375         }
376 
377         // Push the derived path down into PackageSettings so we know what to
378         // clean up at uninstall time.
379         pkgSetting.setLegacyNativeLibraryPath(parsedPackage.getNativeLibraryRootDir());
380 
381         if (DEBUG_ABI_SELECTION) {
382             Log.d(TAG, "Abis for package[" + parsedPackage.getPackageName() + "] are"
383                     + " primary=" + pkgSetting.getPrimaryCpuAbiLegacy()
384                     + " secondary=" + pkgSetting.getSecondaryCpuAbiLegacy()
385                     + " abiOverride=" + pkgSetting.getCpuAbiOverride());
386         }
387 
388         if ((scanFlags & SCAN_BOOTING) == 0 && oldSharedUserSetting != null) {
389             // We don't do this here during boot because we can do it all
390             // at once after scanning all existing packages.
391             //
392             // We also do this *before* we perform dexopt on this package, so that
393             // we can avoid redundant dexopts, and also to make sure we've got the
394             // code and package path correct.
395             changedAbiCodePath = applyAdjustedAbiToSharedUser(oldSharedUserSetting,
396                     parsedPackage, packageAbiHelper.getAdjustedAbiForSharedUser(
397                             oldSharedUserSetting.getPackageStates(), parsedPackage));
398         }
399 
400         parsedPackage.setFactoryTest(isUnderFactoryTest && parsedPackage.getRequestedPermissions()
401                 .contains(android.Manifest.permission.FACTORY_TEST));
402 
403         if (isSystemApp) {
404             pkgSetting.setIsOrphaned(true);
405         }
406 
407         // Take care of first install / last update times.
408         final long scanFileTime = getLastModifiedTime(parsedPackage);
409         final long existingFirstInstallTime = userId == UserHandle.USER_ALL
410                 ? PackageStateUtils.getEarliestFirstInstallTime(pkgSetting.getUserStates())
411                 : pkgSetting.readUserState(userId).getFirstInstallTimeMillis();
412         if (currentTime != 0) {
413             if (existingFirstInstallTime == 0) {
414                 pkgSetting.setFirstInstallTime(currentTime, userId)
415                         .setLastUpdateTime(currentTime);
416             } else if ((scanFlags & SCAN_UPDATE_TIME) != 0) {
417                 pkgSetting.setLastUpdateTime(currentTime);
418             }
419         } else if (existingFirstInstallTime == 0) {
420             // We need *something*.  Take time stamp of the file.
421             pkgSetting.setFirstInstallTime(scanFileTime, userId)
422                     .setLastUpdateTime(scanFileTime);
423         } else if ((parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) != 0) {
424             if (scanFileTime != pkgSetting.getLastModifiedTime()) {
425                 // A package on the system image has changed; consider this
426                 // to be an update.
427                 pkgSetting.setLastUpdateTime(scanFileTime);
428             }
429         }
430         pkgSetting.setLastModifiedTime(scanFileTime);
431         // TODO(b/135203078): Remove, move to constructor
432         pkgSetting.setPkg(parsedPackage)
433                 .setFlags(PackageInfoUtils.appInfoFlags(parsedPackage, pkgSetting))
434                 .setPrivateFlags(PackageInfoUtils.appInfoPrivateFlags(parsedPackage, pkgSetting));
435         if (parsedPackage.getLongVersionCode() != pkgSetting.getVersionCode()) {
436             pkgSetting.setLongVersionCode(parsedPackage.getLongVersionCode());
437         }
438         // Update volume if needed
439         final String volumeUuid = parsedPackage.getVolumeUuid();
440         if (!Objects.equals(volumeUuid, pkgSetting.getVolumeUuid())) {
441             Slog.i(PackageManagerService.TAG,
442                     "Update" + (pkgSetting.isSystem() ? " system" : "")
443                             + " package " + parsedPackage.getPackageName()
444                             + " volume from " + pkgSetting.getVolumeUuid()
445                             + " to " + volumeUuid);
446             pkgSetting.setVolumeUuid(volumeUuid);
447         }
448 
449         SharedLibraryInfo sdkLibraryInfo = null;
450         if (!TextUtils.isEmpty(parsedPackage.getSdkLibraryName())) {
451             sdkLibraryInfo = AndroidPackageUtils.createSharedLibraryForSdk(parsedPackage);
452         }
453         SharedLibraryInfo staticSharedLibraryInfo = null;
454         if (!TextUtils.isEmpty(parsedPackage.getStaticSharedLibraryName())) {
455             staticSharedLibraryInfo =
456                     AndroidPackageUtils.createSharedLibraryForStatic(parsedPackage);
457         }
458         List<SharedLibraryInfo> dynamicSharedLibraryInfos = null;
459         if (!ArrayUtils.isEmpty(parsedPackage.getLibraryNames())) {
460             dynamicSharedLibraryInfos = new ArrayList<>(parsedPackage.getLibraryNames().size());
461             for (String name : parsedPackage.getLibraryNames()) {
462                 dynamicSharedLibraryInfos.add(
463                         AndroidPackageUtils.createSharedLibraryForDynamic(parsedPackage, name));
464             }
465         }
466 
467         return new ScanResult(request, pkgSetting, changedAbiCodePath,
468                 !createNewPackage /* existingSettingCopied */,
469                 Process.INVALID_UID /* previousAppId */ , sdkLibraryInfo,
470                 staticSharedLibraryInfo, dynamicSharedLibraryInfos);
471     }
472 
473     /**
474      * Returns the actual scan flags depending upon the state of the other settings.
475      * <p>Updated system applications will not have the following flags set
476      * by default and need to be adjusted after the fact:
477      * <ul>
478      * <li>{@link PackageManagerService.SCAN_AS_SYSTEM}</li>
479      * <li>{@link PackageManagerService.SCAN_AS_PRIVILEGED}</li>
480      * <li>{@link PackageManagerService.SCAN_AS_OEM}</li>
481      * <li>{@link PackageManagerService.SCAN_AS_VENDOR}</li>
482      * <li>{@link PackageManagerService.SCAN_AS_PRODUCT}</li>
483      * <li>{@link PackageManagerService.SCAN_AS_SYSTEM_EXT}</li>
484      * <li>{@link PackageManagerService.SCAN_AS_INSTANT_APP}</li>
485      * <li>{@link PackageManagerService.SCAN_AS_VIRTUAL_PRELOAD}</li>
486      * <li>{@link PackageManagerService.SCAN_AS_ODM}</li>
487      * </ul>
488      */
adjustScanFlagsWithPackageSetting( @ackageManagerService.ScanFlags int scanFlags, PackageSetting pkgSetting, PackageSetting disabledPkgSetting, UserHandle user)489     public static @PackageManagerService.ScanFlags int adjustScanFlagsWithPackageSetting(
490             @PackageManagerService.ScanFlags int scanFlags,
491             PackageSetting pkgSetting, PackageSetting disabledPkgSetting, UserHandle user) {
492 
493         // TODO(patb): Do away entirely with disabledPkgSetting here. PkgSetting will always contain
494         // the correct isSystem value now that we don't disable system packages before scan.
495         final PackageSetting systemPkgSetting =
496                 (scanFlags & SCAN_NEW_INSTALL) != 0 && disabledPkgSetting == null
497                         && pkgSetting != null && pkgSetting.isSystem()
498                         ? pkgSetting
499                         : disabledPkgSetting;
500         if (systemPkgSetting != null)  {
501             // updated system application, must at least have SCAN_AS_SYSTEM
502             scanFlags |= SCAN_AS_SYSTEM;
503             if ((systemPkgSetting.getPrivateFlags()
504                     & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) {
505                 scanFlags |= SCAN_AS_PRIVILEGED;
506             }
507             if ((systemPkgSetting.getPrivateFlags()
508                     & ApplicationInfo.PRIVATE_FLAG_OEM) != 0) {
509                 scanFlags |= SCAN_AS_OEM;
510             }
511             if ((systemPkgSetting.getPrivateFlags()
512                     & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0) {
513                 scanFlags |= SCAN_AS_VENDOR;
514             }
515             if ((systemPkgSetting.getPrivateFlags()
516                     & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0) {
517                 scanFlags |= SCAN_AS_PRODUCT;
518             }
519             if ((systemPkgSetting.getPrivateFlags()
520                     & ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT) != 0) {
521                 scanFlags |= SCAN_AS_SYSTEM_EXT;
522             }
523             if ((systemPkgSetting.getPrivateFlags()
524                     & ApplicationInfo.PRIVATE_FLAG_ODM) != 0) {
525                 scanFlags |= SCAN_AS_ODM;
526             }
527         }
528         if (pkgSetting != null) {
529             final int userId = ((user == null) ? 0 : user.getIdentifier());
530             if (pkgSetting.getInstantApp(userId)) {
531                 scanFlags |= SCAN_AS_INSTANT_APP;
532             }
533             if (pkgSetting.getVirtualPreload(userId)) {
534                 scanFlags |= SCAN_AS_VIRTUAL_PRELOAD;
535             }
536         }
537 
538         return scanFlags;
539     }
540 
541     /**
542      * Enforces code policy for the package. This ensures that if an APK has
543      * declared hasCode="true" in its manifest that the APK actually contains
544      * code.
545      *
546      * @throws PackageManagerException If bytecode could not be found when it should exist
547      */
assertCodePolicy(AndroidPackage pkg)548     public static void assertCodePolicy(AndroidPackage pkg)
549             throws PackageManagerException {
550         final boolean shouldHaveCode = pkg.isDeclaredHavingCode();
551         if (shouldHaveCode && !apkHasCode(pkg.getBaseApkPath())) {
552             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
553                     "Package " + pkg.getBaseApkPath() + " code is missing");
554         }
555 
556         if (!ArrayUtils.isEmpty(pkg.getSplitCodePaths())) {
557             for (int i = 0; i < pkg.getSplitCodePaths().length; i++) {
558                 final boolean splitShouldHaveCode =
559                         (pkg.getSplitFlags()[i] & ApplicationInfo.FLAG_HAS_CODE) != 0;
560                 if (splitShouldHaveCode && !apkHasCode(pkg.getSplitCodePaths()[i])) {
561                     throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
562                             "Package " + pkg.getSplitCodePaths()[i] + " code is missing");
563                 }
564             }
565         }
566     }
567 
assertStaticSharedLibraryIsValid(AndroidPackage pkg, @PackageManagerService.ScanFlags int scanFlags)568     public static void assertStaticSharedLibraryIsValid(AndroidPackage pkg,
569             @PackageManagerService.ScanFlags int scanFlags) throws PackageManagerException {
570         // Static shared libraries should have at least O target SDK
571         if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.O) {
572             throw PackageManagerException.ofInternalError(
573                     "Packages declaring static-shared libs must target O SDK or higher",
574                     PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_LOW_SDK);
575         }
576 
577         // Package declaring static a shared lib cannot be instant apps
578         if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
579             throw PackageManagerException.ofInternalError(
580                     "Packages declaring static-shared libs cannot be instant apps",
581                     PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_INSTANT);
582         }
583 
584         // Package declaring static a shared lib cannot be renamed since the package
585         // name is synthetic and apps can't code around package manager internals.
586         if (!ArrayUtils.isEmpty(pkg.getOriginalPackages())) {
587             throw PackageManagerException.ofInternalError(
588                     "Packages declaring static-shared libs cannot be renamed",
589                     PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_RENAMED);
590         }
591 
592         // Package declaring static a shared lib cannot declare dynamic libs
593         if (!ArrayUtils.isEmpty(pkg.getLibraryNames())) {
594             throw PackageManagerException.ofInternalError(
595                     "Packages declaring static-shared libs cannot declare dynamic libs",
596                     PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_DYNAMIC);
597         }
598 
599         // Package declaring static a shared lib cannot declare shared users
600         if (pkg.getSharedUserId() != null) {
601             throw PackageManagerException.ofInternalError(
602                     "Packages declaring static-shared libs cannot declare shared users",
603                     PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_SHARED_USER);
604         }
605 
606         // Static shared libs cannot declare activities
607         if (!pkg.getActivities().isEmpty()) {
608             throw PackageManagerException.ofInternalError(
609                     "Static shared libs cannot declare activities",
610                     PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_ACTIVITY);
611         }
612 
613         // Static shared libs cannot declare services
614         if (!pkg.getServices().isEmpty()) {
615             throw PackageManagerException.ofInternalError(
616                     "Static shared libs cannot declare services",
617                     PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_SERVICE);
618         }
619 
620         // Static shared libs cannot declare providers
621         if (!pkg.getProviders().isEmpty()) {
622             throw PackageManagerException.ofInternalError(
623                     "Static shared libs cannot declare content providers",
624                     PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_CONTENT_PROVIDER);
625         }
626 
627         // Static shared libs cannot declare receivers
628         if (!pkg.getReceivers().isEmpty()) {
629             throw PackageManagerException.ofInternalError(
630                     "Static shared libs cannot declare broadcast receivers",
631                     PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_BROADCAST_RECEIVER);
632         }
633 
634         // Static shared libs cannot declare permission groups
635         if (!pkg.getPermissionGroups().isEmpty()) {
636             throw PackageManagerException.ofInternalError(
637                     "Static shared libs cannot declare permission groups",
638                     PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_PERMISSION_GROUP);
639         }
640 
641         // Static shared libs cannot declare attributions
642         if (!pkg.getAttributions().isEmpty()) {
643             throw PackageManagerException.ofInternalError(
644                     "Static shared libs cannot declare features",
645                     PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_FEATURE);
646         }
647 
648         // Static shared libs cannot declare permissions
649         if (!pkg.getPermissions().isEmpty()) {
650             throw PackageManagerException.ofInternalError(
651                     "Static shared libs cannot declare permissions",
652                     PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_PERMISSION);
653         }
654 
655         // Static shared libs cannot declare protected broadcasts
656         if (!pkg.getProtectedBroadcasts().isEmpty()) {
657             throw PackageManagerException.ofInternalError(
658                     "Static shared libs cannot declare protected broadcasts",
659                     PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_PROTECTED_BROADCAST);
660         }
661 
662         // Static shared libs cannot be overlay targets
663         if (pkg.getOverlayTarget() != null) {
664             throw PackageManagerException.ofInternalError(
665                     "Static shared libs cannot be overlay targets",
666                     PackageManagerException.INTERNAL_ERROR_STATIC_SHARED_LIB_OVERLAY_TARGETS);
667         }
668     }
669 
assertProcessesAreValid(AndroidPackage pkg)670     public static void assertProcessesAreValid(AndroidPackage pkg) throws PackageManagerException {
671         final Map<String, ParsedProcess> procs = pkg.getProcesses();
672         if (!procs.isEmpty()) {
673             if (!procs.containsKey(pkg.getProcessName())) {
674                 throw new PackageManagerException(
675                         INSTALL_FAILED_PROCESS_NOT_DEFINED,
676                         "Can't install because application tag's process attribute "
677                                 + pkg.getProcessName()
678                                 + " (in package " + pkg.getPackageName()
679                                 + ") is not included in the <processes> list");
680             }
681             assertPackageProcesses(pkg, pkg.getActivities(), procs, "activity");
682             assertPackageProcesses(pkg, pkg.getServices(), procs, "service");
683             assertPackageProcesses(pkg, pkg.getReceivers(), procs, "receiver");
684             assertPackageProcesses(pkg, pkg.getProviders(), procs, "provider");
685         }
686     }
687 
assertPackageProcesses(AndroidPackage pkg, List<T> components, Map<String, ParsedProcess> procs, String compName)688     private static <T extends ParsedMainComponent> void assertPackageProcesses(AndroidPackage pkg,
689             List<T> components, Map<String, ParsedProcess> procs, String compName)
690             throws PackageManagerException {
691         if (components == null) {
692             return;
693         }
694         for (int i = components.size() - 1; i >= 0; i--) {
695             final ParsedMainComponent component = components.get(i);
696             if (!procs.containsKey(component.getProcessName())) {
697                 throw new PackageManagerException(
698                         INSTALL_FAILED_PROCESS_NOT_DEFINED,
699                         "Can't install because " + compName + " " + component.getClassName()
700                                 + "'s process attribute " + component.getProcessName()
701                                 + " (in package " + pkg.getPackageName()
702                                 + ") is not included in the <processes> list");
703             }
704         }
705     }
706 
assertMinSignatureSchemeIsValid(AndroidPackage pkg, @ParsingPackageUtils.ParseFlags int parseFlags)707     public static void assertMinSignatureSchemeIsValid(AndroidPackage pkg,
708             @ParsingPackageUtils.ParseFlags int parseFlags) throws PackageManagerException {
709         int minSignatureSchemeVersion =
710                 ApkSignatureVerifier.getMinimumSignatureSchemeVersionForTargetSdk(
711                         pkg.getTargetSdkVersion());
712         if (pkg.getSigningDetails().getSignatureSchemeVersion()
713                 < minSignatureSchemeVersion) {
714             throw new PackageManagerException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
715                     "No signature found in package of version " + minSignatureSchemeVersion
716                             + " or newer for package " + pkg.getPackageName());
717         }
718     }
719 
720     /**
721      * Returns the "real" name of the package.
722      * <p>This may differ from the package's actual name if the application has already
723      * been installed under one of this package's original names.
724      */
getRealPackageName(@onNull AndroidPackage pkg, @Nullable String renamedPkgName, boolean isSystemApp)725     public static @Nullable String getRealPackageName(@NonNull AndroidPackage pkg,
726             @Nullable String renamedPkgName, boolean isSystemApp) {
727         if (isPackageRenamed(pkg, renamedPkgName)) {
728             return AndroidPackageUtils.getRealPackageOrNull(pkg, isSystemApp);
729         }
730         return null;
731     }
732 
733     /** Returns {@code true} if the package has been renamed. Otherwise, {@code false}. */
isPackageRenamed(@onNull AndroidPackage pkg, @Nullable String renamedPkgName)734     public static boolean isPackageRenamed(@NonNull AndroidPackage pkg,
735             @Nullable String renamedPkgName) {
736         return pkg.getOriginalPackages().contains(renamedPkgName);
737     }
738 
739     /**
740      * Renames the package if it was installed under a different name.
741      * <p>When we've already installed the package under an original name, update
742      * the new package so we can continue to have the old name.
743      */
ensurePackageRenamed(@onNull ParsedPackage parsedPackage, @NonNull String renamedPackageName)744     public static void ensurePackageRenamed(@NonNull ParsedPackage parsedPackage,
745             @NonNull String renamedPackageName) {
746         if (!parsedPackage.getOriginalPackages().contains(renamedPackageName)
747                 || parsedPackage.getPackageName().equals(renamedPackageName)) {
748             return;
749         }
750         parsedPackage.setPackageName(renamedPackageName);
751     }
752 
753     /**
754      * Returns {@code true} if the given file contains code. Otherwise {@code false}.
755      */
apkHasCode(String fileName)756     public static boolean apkHasCode(String fileName) {
757         StrictJarFile jarFile = null;
758         try {
759             jarFile = new StrictJarFile(fileName,
760                     false /*verify*/, false /*signatureSchemeRollbackProtectionsEnforced*/);
761             return jarFile.findEntry("classes.dex") != null;
762         } catch (IOException ignore) {
763         } finally {
764             try {
765                 if (jarFile != null) {
766                     jarFile.close();
767                 }
768             } catch (IOException ignore) {
769             }
770         }
771         return false;
772     }
773 
774     /**
775      * Sets the enabled state of components configured through {@link SystemConfig}.
776      * This modifies the {@link PackageSetting} object.
777      *
778      * TODO(b/135203078): Move this to package parsing
779      **/
configurePackageComponents(AndroidPackage pkg)780     public static void configurePackageComponents(AndroidPackage pkg) {
781         final ArrayMap<String, Boolean> componentsEnabledStates = SystemConfig.getInstance()
782                 .getComponentsEnabledStates(pkg.getPackageName());
783         if (componentsEnabledStates == null) {
784             return;
785         }
786 
787         for (int i = ArrayUtils.size(pkg.getActivities()) - 1; i >= 0; i--) {
788             final ParsedActivity component = pkg.getActivities().get(i);
789             final Boolean enabled = componentsEnabledStates.get(component.getName());
790             if (enabled != null) {
791                 ComponentMutateUtils.setEnabled(component, enabled);
792             }
793         }
794 
795         for (int i = ArrayUtils.size(pkg.getReceivers()) - 1; i >= 0; i--) {
796             final ParsedActivity component = pkg.getReceivers().get(i);
797             final Boolean enabled = componentsEnabledStates.get(component.getName());
798             if (enabled != null) {
799                 ComponentMutateUtils.setEnabled(component, enabled);
800             }
801         }
802 
803         for (int i = ArrayUtils.size(pkg.getProviders()) - 1; i >= 0; i--) {
804             final ParsedProvider component = pkg.getProviders().get(i);
805             final Boolean enabled = componentsEnabledStates.get(component.getName());
806             if (enabled != null) {
807                 ComponentMutateUtils.setEnabled(component, enabled);
808             }
809         }
810 
811         for (int i = ArrayUtils.size(pkg.getServices()) - 1; i >= 0; i--) {
812             final ParsedService component = pkg.getServices().get(i);
813             final Boolean enabled = componentsEnabledStates.get(component.getName());
814             if (enabled != null) {
815                 ComponentMutateUtils.setEnabled(component, enabled);
816             }
817         }
818     }
819 
getVendorPartitionVersion()820     public static int getVendorPartitionVersion() {
821         final String version = SystemProperties.get("ro.vndk.version");
822         if (!version.isEmpty()) {
823             try {
824                 return Integer.parseInt(version);
825             } catch (NumberFormatException ignore) {
826                 if (ArrayUtils.contains(Build.VERSION.ACTIVE_CODENAMES, version)) {
827                     return Build.VERSION_CODES.CUR_DEVELOPMENT;
828                 }
829             }
830         }
831         return Build.VERSION_CODES.P;
832     }
833 
834     /**
835      * Applies policy to the parsed package based upon the given policy flags.
836      * Ensures the package is in a good state.
837      * <p>
838      * Implementation detail: This method must NOT have any side effect. It would
839      * ideally be static, but, it requires locks to read system state.
840      */
applyPolicy(ParsedPackage parsedPackage, final @PackageManagerService.ScanFlags int scanFlags, @Nullable AndroidPackage platformPkg, boolean isUpdatedSystemApp)841     public static void applyPolicy(ParsedPackage parsedPackage,
842             final @PackageManagerService.ScanFlags int scanFlags,
843             @Nullable AndroidPackage platformPkg, boolean isUpdatedSystemApp) {
844         // TODO: In the real APIs, an updated system app is always a system app, but that may not
845         //  hold true during scan because PMS doesn't propagate the SCAN_AS_SYSTEM flag for the data
846         //  directory. This tries to emulate that behavior by using either the flag or the boolean,
847         //  but this logic is fragile. Specifically, it may affect the PackageBackwardCompatibility
848         //  checker, which switches branches based on whether an app is a system app. When install
849         //  is refactored, the scan policy flags should not be read this late and instead passed
850         //  around in the PackageSetting or a temporary object which infers these values early, so
851         //  that all further consumers agree on their values.
852         boolean isSystemApp = isUpdatedSystemApp;
853         if ((scanFlags & SCAN_AS_SYSTEM) != 0) {
854             isSystemApp = true;
855             parsedPackage.setSystem(true);
856             // TODO(b/135203078): Can this be done in PackageParser? Or just inferred when the flag
857             //  is set during parse.
858             if (parsedPackage.isDirectBootAware()) {
859                 parsedPackage.setAllComponentsDirectBootAware(true);
860             }
861             if (compressedFileExists(parsedPackage.getPath())) {
862                 parsedPackage.setStub(true);
863             }
864         } else {
865             parsedPackage
866                     // Non system apps cannot mark any broadcast as protected
867                     .clearProtectedBroadcasts()
868                     // non system apps can't be flagged as core
869                     .setCoreApp(false)
870                     // clear flags not applicable to regular apps
871                     .setPersistent(false)
872                     .setDefaultToDeviceProtectedStorage(false)
873                     .setDirectBootAware(false)
874                     // non system apps can't have permission priority
875                     .capPermissionPriorities();
876         }
877         if ((scanFlags & SCAN_AS_PRIVILEGED) == 0) {
878             parsedPackage
879                     .markNotActivitiesAsNotExportedIfSingleUser();
880         }
881 
882         parsedPackage.setApex((scanFlags & SCAN_AS_APEX) != 0);
883 
884         parsedPackage.setPrivileged((scanFlags & SCAN_AS_PRIVILEGED) != 0)
885                 .setOem((scanFlags & SCAN_AS_OEM) != 0)
886                 .setVendor((scanFlags & SCAN_AS_VENDOR) != 0)
887                 .setProduct((scanFlags & SCAN_AS_PRODUCT) != 0)
888                 .setSystemExt((scanFlags & SCAN_AS_SYSTEM_EXT) != 0)
889                 .setOdm((scanFlags & SCAN_AS_ODM) != 0);
890 
891         // Check if the package is signed with the same key as the platform package.
892         parsedPackage.setSignedWithPlatformKey(
893                 (PLATFORM_PACKAGE_NAME.equals(parsedPackage.getPackageName())
894                         || (platformPkg != null && compareSignatures(
895                         platformPkg.getSigningDetails().getSignatures(),
896                         parsedPackage.getSigningDetails().getSignatures()
897                 ) == PackageManager.SIGNATURE_MATCH))
898         );
899 
900         if (!isSystemApp) {
901             // Only system apps can use these features.
902             parsedPackage.clearOriginalPackages()
903                     .clearAdoptPermissions();
904         }
905 
906         PackageBackwardCompatibility.modifySharedLibraries(parsedPackage, isSystemApp,
907                 isUpdatedSystemApp);
908     }
909 
910     /**
911      * Applies the adjusted ABI calculated by
912      * {@link PackageAbiHelper#getAdjustedAbiForSharedUser(ArraySet, AndroidPackage)} to all
913      * relevant packages and settings.
914      * @param sharedUserSetting The {@code SharedUserSetting} to adjust
915      * @param scannedPackage the package being scanned or null
916      * @param adjustedAbi the adjusted ABI calculated by {@link PackageAbiHelper}
917      * @return the list of code paths that belong to packages that had their ABIs adjusted.
918      */
applyAdjustedAbiToSharedUser(SharedUserSetting sharedUserSetting, ParsedPackage scannedPackage, String adjustedAbi)919     public static List<String> applyAdjustedAbiToSharedUser(SharedUserSetting sharedUserSetting,
920             ParsedPackage scannedPackage, String adjustedAbi) {
921         if (scannedPackage != null)  {
922             scannedPackage.setPrimaryCpuAbi(adjustedAbi);
923         }
924         List<String> changedAbiCodePath = null;
925         final WatchedArraySet<PackageSetting> sharedUserPackageSettings =
926                 sharedUserSetting.getPackageSettings();
927         for (int i = 0; i < sharedUserPackageSettings.size(); i++) {
928             PackageSetting ps = sharedUserPackageSettings.valueAt(i);
929             if (scannedPackage == null
930                     || !scannedPackage.getPackageName().equals(ps.getPackageName())) {
931                 if (ps.getPrimaryCpuAbiLegacy() != null) {
932                     continue;
933                 }
934 
935                 ps.setPrimaryCpuAbi(adjustedAbi);
936                 ps.onChanged();
937                 if (ps.getPkg() != null) {
938                     if (!TextUtils.equals(adjustedAbi,
939                             AndroidPackageUtils.getRawPrimaryCpuAbi(ps.getPkg()))) {
940                         if (DEBUG_ABI_SELECTION) {
941                             Slog.i(TAG,
942                                     "Adjusting ABI for " + ps.getPackageName() + " to "
943                                             + adjustedAbi + " (scannedPackage="
944                                             + (scannedPackage != null ? scannedPackage : "null")
945                                             + ")");
946                         }
947                         if (changedAbiCodePath == null) {
948                             changedAbiCodePath = new ArrayList<>();
949                         }
950                         changedAbiCodePath.add(ps.getPathString());
951                     }
952                 }
953             }
954         }
955         return changedAbiCodePath;
956     }
957 
collectCertificatesLI(PackageSetting ps, ParsedPackage parsedPackage, Settings.VersionInfo settingsVersionForPackage, boolean forceCollect, boolean skipVerify, boolean isPreNMR1Upgrade)958     public static void collectCertificatesLI(PackageSetting ps, ParsedPackage parsedPackage,
959             Settings.VersionInfo settingsVersionForPackage, boolean forceCollect,
960             boolean skipVerify, boolean isPreNMR1Upgrade)
961             throws PackageManagerException {
962         // When upgrading from pre-N MR1, verify the package time stamp using the package
963         // directory and not the APK file.
964         final long lastModifiedTime = isPreNMR1Upgrade
965                 ? new File(parsedPackage.getPath()).lastModified()
966                 : getLastModifiedTime(parsedPackage);
967         if (ps != null && !forceCollect
968                 && ps.getPathString().equals(parsedPackage.getPath())
969                 && ps.getLastModifiedTime() == lastModifiedTime
970                 && !ReconcilePackageUtils.isCompatSignatureUpdateNeeded(settingsVersionForPackage)
971                 && !ReconcilePackageUtils.isRecoverSignatureUpdateNeeded(
972                 settingsVersionForPackage)) {
973             if (ps.getSigningDetails().getSignatures() != null
974                     && ps.getSigningDetails().getSignatures().length != 0
975                     && ps.getSigningDetails().getSignatureSchemeVersion()
976                     != SigningDetails.SignatureSchemeVersion.UNKNOWN) {
977                 // Optimization: reuse the existing cached signing data
978                 // if the package appears to be unchanged.
979                 parsedPackage.setSigningDetails(
980                         new SigningDetails(ps.getSigningDetails()));
981                 return;
982             }
983 
984             Slog.w(TAG, "PackageSetting for " + ps.getPackageName()
985                     + " is missing signatures.  Collecting certs again to recover them.");
986         } else {
987             Slog.i(TAG, parsedPackage.getPath() + " changed; collecting certs"
988                     + (forceCollect ? " (forced)" : ""));
989         }
990 
991         try {
992             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
993             final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
994             final ParseResult<SigningDetails> result = ParsingPackageUtils.getSigningDetails(
995                     input, parsedPackage, skipVerify);
996             if (result.isError()) {
997                 throw new PackageManagerException(
998                         result.getErrorCode(), result.getErrorMessage(), result.getException());
999             }
1000             parsedPackage.setSigningDetails(result.getResult());
1001         } finally {
1002             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
1003         }
1004     }
1005 
setInstantAppForUser(PackageManagerServiceInjector injector, PackageSetting pkgSetting, int userId, boolean instantApp, boolean fullApp)1006     public static void setInstantAppForUser(PackageManagerServiceInjector injector,
1007             PackageSetting pkgSetting, int userId, boolean instantApp, boolean fullApp) {
1008         // no state specified; do nothing
1009         if (!instantApp && !fullApp) {
1010             return;
1011         }
1012         if (userId != UserHandle.USER_ALL) {
1013             if (instantApp && !pkgSetting.getInstantApp(userId)) {
1014                 pkgSetting.setInstantApp(true /*instantApp*/, userId);
1015             } else if (fullApp && pkgSetting.getInstantApp(userId)) {
1016                 pkgSetting.setInstantApp(false /*instantApp*/, userId);
1017             }
1018         } else {
1019             for (int currentUserId : injector.getUserManagerInternal().getUserIds()) {
1020                 if (instantApp && !pkgSetting.getInstantApp(currentUserId)) {
1021                     pkgSetting.setInstantApp(true /*instantApp*/, currentUserId);
1022                 } else if (fullApp && pkgSetting.getInstantApp(currentUserId)) {
1023                     pkgSetting.setInstantApp(false /*instantApp*/, currentUserId);
1024                 }
1025             }
1026         }
1027     }
1028 
1029     /** Directory where installed application's 32-bit native libraries are copied. */
getAppLib32InstallDir()1030     public static File getAppLib32InstallDir() {
1031         return new File(Environment.getDataDirectory(), "app-lib");
1032     }
1033 }
1034