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