• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.pm;
18 
19 import static android.content.pm.PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
20 
21 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
22 import static com.android.server.pm.PackageManagerService.TAG;
23 
24 import android.annotation.NonNull;
25 import android.annotation.Nullable;
26 import android.compat.annotation.ChangeId;
27 import android.compat.annotation.EnabledAfter;
28 import android.content.pm.PackageManager;
29 import android.content.pm.SharedLibraryInfo;
30 import android.content.pm.Signature;
31 import android.content.pm.SigningDetails;
32 import android.content.pm.VersionedPackage;
33 import android.os.Build;
34 import android.os.Process;
35 import android.os.UserHandle;
36 import android.os.storage.StorageManager;
37 import android.service.pm.PackageServiceDumpProto;
38 import android.util.ArraySet;
39 import android.util.PackageUtils;
40 import android.util.Pair;
41 import android.util.Slog;
42 import android.util.proto.ProtoOutputStream;
43 
44 import com.android.internal.annotations.GuardedBy;
45 import com.android.internal.annotations.VisibleForTesting;
46 import com.android.internal.util.ArrayUtils;
47 import com.android.server.SystemConfig;
48 import com.android.server.compat.PlatformCompat;
49 import com.android.server.pm.parsing.pkg.AndroidPackage;
50 import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
51 import com.android.server.pm.parsing.pkg.ParsedPackage;
52 import com.android.server.pm.pkg.PackageStateInternal;
53 import com.android.server.utils.Snappable;
54 import com.android.server.utils.SnapshotCache;
55 import com.android.server.utils.Watchable;
56 import com.android.server.utils.WatchableImpl;
57 import com.android.server.utils.Watched;
58 import com.android.server.utils.WatchedArrayMap;
59 import com.android.server.utils.WatchedLongSparseArray;
60 import com.android.server.utils.Watcher;
61 
62 import libcore.util.HexEncoding;
63 
64 import java.io.File;
65 import java.io.IOException;
66 import java.io.PrintWriter;
67 import java.util.ArrayList;
68 import java.util.Arrays;
69 import java.util.Collections;
70 import java.util.LinkedHashSet;
71 import java.util.List;
72 import java.util.Map;
73 import java.util.Set;
74 import java.util.function.BiConsumer;
75 
76 /**
77  * Current known shared libraries on the device.
78  */
79 public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable, Snappable {
80     private static final boolean DEBUG_SHARED_LIBRARIES = false;
81 
82     /**
83      * Apps targeting Android S and above need to declare dependencies to the public native
84      * shared libraries that are defined by the device maker using {@code uses-native-library} tag
85      * in its {@code AndroidManifest.xml}.
86      *
87      * If any of the dependencies cannot be satisfied, i.e. one of the dependency doesn't exist,
88      * the package manager rejects to install the app. The dependency can be specified as optional
89      * using {@code android:required} attribute in the tag, in which case failing to satisfy the
90      * dependency doesn't stop the installation.
91      * <p>Once installed, an app is provided with only the native shared libraries that are
92      * specified in the app manifest. {@code dlopen}ing a native shared library that doesn't appear
93      * in the app manifest will fail even if it actually exists on the device.
94      */
95     @ChangeId
96     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
97     private static final long ENFORCE_NATIVE_SHARED_LIBRARY_DEPENDENCIES = 142191088;
98 
99     // TODO(b/200588896): remove PMS dependency
100     private final PackageManagerService mPm;
101     private final PackageManagerServiceInjector mInjector;
102     private DeletePackageHelper mDeletePackageHelper; // late init
103 
104     // A map of library name to a list of {@link SharedLibraryInfo}s with different versions.
105     @Watched
106     private final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
107             mSharedLibraries;
108     private final SnapshotCache<WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>>
109             mSharedLibrariesSnapshot;
110 
111     // A map of declaring package name to a list of {@link SharedLibraryInfo}s with different
112     // versions.
113     @Watched
114     private final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
115             mStaticLibsByDeclaringPackage;
116     private final SnapshotCache<WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>>
117             mStaticLibsByDeclaringPackageSnapshot;
118 
119     /**
120      * Watchable machinery
121      */
122     private final WatchableImpl mWatchable = new WatchableImpl();
123 
124     /**
125      * The observer that watches for changes from array members
126      */
127     private final Watcher mObserver = new Watcher() {
128         @Override
129         public void onChange(@Nullable Watchable what) {
130             SharedLibrariesImpl.this.dispatchChange(what);
131         }
132     };
133 
134     private final SnapshotCache<SharedLibrariesImpl> mSnapshot;
135 
136     // Create a snapshot cache
makeCache()137     private SnapshotCache<SharedLibrariesImpl> makeCache() {
138         return new SnapshotCache<SharedLibrariesImpl>(this /* source */, this /* watchable */) {
139             @Override
140             public SharedLibrariesImpl createSnapshot() {
141                 final SharedLibrariesImpl sharedLibrariesImpl = new SharedLibrariesImpl(mSource);
142                 sharedLibrariesImpl.mWatchable.seal();
143                 return sharedLibrariesImpl;
144             }};
145     }
146 
147     /**
148      * Default constructor used in PackageManagerService.
149      */
150     SharedLibrariesImpl(PackageManagerService pm, PackageManagerServiceInjector injector) {
151         mPm = pm;
152         mInjector = injector;
153 
154         mSharedLibraries = new WatchedArrayMap<>();
155         mSharedLibrariesSnapshot = new SnapshotCache.Auto<>(mSharedLibraries, mSharedLibraries,
156                 "SharedLibrariesImpl.mSharedLibraries");
157         mStaticLibsByDeclaringPackage = new WatchedArrayMap<>();
158         mStaticLibsByDeclaringPackageSnapshot = new SnapshotCache.Auto<>(
159                 mStaticLibsByDeclaringPackage, mStaticLibsByDeclaringPackage,
160                 "SharedLibrariesImpl.mStaticLibsByDeclaringPackage");
161 
162         registerObservers();
163         Watchable.verifyWatchedAttributes(this, mObserver);
164         mSnapshot = makeCache();
165     }
166 
167     /**
168      * Invoked by PMS constructor after the instance of {@link DeletePackageHelper} is ready.
169      */
170     void setDeletePackageHelper(DeletePackageHelper deletePackageHelper) {
171         mDeletePackageHelper = deletePackageHelper;
172     }
173 
174     private void registerObservers() {
175         mSharedLibraries.registerObserver(mObserver);
176         mStaticLibsByDeclaringPackage.registerObserver(mObserver);
177     }
178 
179     /**
180      * A copy constructor used in snapshot().
181      */
182     private SharedLibrariesImpl(SharedLibrariesImpl source) {
183         mPm = source.mPm;
184         mInjector = source.mInjector;
185 
186         mSharedLibraries = source.mSharedLibrariesSnapshot.snapshot();
187         mSharedLibrariesSnapshot = new SnapshotCache.Sealed<>();
188         mStaticLibsByDeclaringPackage = source.mStaticLibsByDeclaringPackageSnapshot.snapshot();
189         mStaticLibsByDeclaringPackageSnapshot = new SnapshotCache.Sealed<>();
190 
191         // Do not register any Watchables and do not create a snapshot cache.
192         mSnapshot = new SnapshotCache.Sealed();
193     }
194 
195     /**
196      * Ensures an observer is in the list, exactly once. The observer cannot be null.  The
197      * function quietly returns if the observer is already in the list.
198      *
199      * @param observer The {@link Watcher} to be notified when the {@link Watchable} changes.
200      */
201     @Override
202     public void registerObserver(@NonNull Watcher observer) {
203         mWatchable.registerObserver(observer);
204     }
205 
206     /**
207      * Ensures an observer is not in the list. The observer must not be null.  The function
208      * quietly returns if the objserver is not in the list.
209      *
210      * @param observer The {@link Watcher} that should not be in the notification list.
211      */
212     @Override
213     public void unregisterObserver(@NonNull Watcher observer) {
214         mWatchable.unregisterObserver(observer);
215     }
216 
217     /**
218      * Return true if the {@link Watcher} is a registered observer.
219      * @param observer A {@link Watcher} that might be registered
220      * @return true if the observer is registered with this {@link Watchable}.
221      */
222     @Override
223     public boolean isRegisteredObserver(@NonNull Watcher observer) {
224         return mWatchable.isRegisteredObserver(observer);
225     }
226 
227     /**
228      * Invokes {@link Watcher#onChange} on each registered observer.  The method can be called
229      * with the {@link Watchable} that generated the event.  In a tree of {@link Watchable}s, this
230      * is generally the first (deepest) {@link Watchable} to detect a change.
231      *
232      * @param what The {@link Watchable} that generated the event.
233      */
234     @Override
235     public void dispatchChange(@Nullable Watchable what) {
236         mWatchable.dispatchChange(what);
237     }
238 
239     /**
240      * Create an immutable copy of the object, suitable for read-only methods.  A snapshot
241      * is free to omit state that is only needed for mutating methods.
242      */
243     @Override
244     public @NonNull SharedLibrariesRead snapshot() {
245         return mSnapshot.snapshot();
246     }
247 
248     /**
249      * Returns all shared libraries on the device.
250      */
251     @GuardedBy("mPm.mLock")
252     @Override
253     public @NonNull WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>> getAll() {
254         return mSharedLibraries;
255     }
256 
257     /**
258      * Given the library name, returns a list of shared libraries on all versions.
259      * TODO: Remove, this is used for live mutation outside of the defined commit path
260      */
261     @GuardedBy("mPm.mLock")
262     @Override
263     public @NonNull WatchedLongSparseArray<SharedLibraryInfo> getSharedLibraryInfos(
264             @NonNull String libName) {
265         return mSharedLibraries.get(libName);
266     }
267 
268     @VisibleForTesting
269     public WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>> getSharedLibraries() {
270         return mSharedLibraries;
271     }
272 
273     /**
274      * Returns the shared library with given library name and version number.
275      */
276     @GuardedBy("mPm.mLock")
277     @Override
278     public @Nullable SharedLibraryInfo getSharedLibraryInfo(@NonNull String libName, long version) {
279         final WatchedLongSparseArray<SharedLibraryInfo> versionedLib =
280                 mSharedLibraries.get(libName);
281         if (versionedLib == null) {
282             return null;
283         }
284         return versionedLib.get(version);
285     }
286 
287     /**
288      * Given the declaring package name, returns a list of static shared libraries on all versions.
289      */
290     @GuardedBy("mPm.mLock")
291     @Override
292     public @NonNull WatchedLongSparseArray<SharedLibraryInfo> getStaticLibraryInfos(
293             @NonNull String declaringPackageName) {
294         return mStaticLibsByDeclaringPackage.get(declaringPackageName);
295     }
296 
297     @Nullable
298     private PackageStateInternal getLibraryPackage(@NonNull Computer computer,
299             @NonNull SharedLibraryInfo libInfo) {
300         final VersionedPackage declaringPackage = libInfo.getDeclaringPackage();
301         if (libInfo.isStatic()) {
302             // Resolve the package name - we use synthetic package names internally
303             final String internalPackageName = computer.resolveInternalPackageName(
304                     declaringPackage.getPackageName(),
305                     declaringPackage.getLongVersionCode());
306             return computer.getPackageStateInternal(internalPackageName);
307         }
308         if (libInfo.isSdk()) {
309             return computer.getPackageStateInternal(declaringPackage.getPackageName());
310         }
311         return null;
312     }
313 
314     /**
315      * Finds all unused shared libraries which have cached more than the given
316      * {@code maxCachePeriod}. Deletes them one by one until the available storage space on the
317      * device is larger than {@code neededSpace}.
318      *
319      * @param neededSpace A minimum available storage space the device needs to reach
320      * @param maxCachePeriod A maximum period of time an unused shared library can be cached
321      *                       on the device.
322      * @return {@code true} if the available storage space is reached.
323      */
324     boolean pruneUnusedStaticSharedLibraries(@NonNull Computer computer, long neededSpace,
325             long maxCachePeriod)
326             throws IOException {
327         final StorageManager storage = mInjector.getSystemService(StorageManager.class);
328         final File volume = storage.findPathForUuid(StorageManager.UUID_PRIVATE_INTERNAL);
329 
330         final ArrayList<VersionedPackage> packagesToDelete = new ArrayList<>();
331         final long now = System.currentTimeMillis();
332 
333         // Important: We skip shared libs used for some user since
334         // in such a case we need to keep the APK on the device. The check for
335         // a lib being used for any user is performed by the uninstall call.
336         final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
337                 sharedLibraries = computer.getSharedLibraries();
338         final int libCount = sharedLibraries.size();
339         for (int i = 0; i < libCount; i++) {
340             final WatchedLongSparseArray<SharedLibraryInfo> versionedLib =
341                     sharedLibraries.valueAt(i);
342             if (versionedLib == null) {
343                 continue;
344             }
345             final int versionCount = versionedLib.size();
346             for (int j = 0; j < versionCount; j++) {
347                 SharedLibraryInfo libInfo = versionedLib.valueAt(j);
348                 final PackageStateInternal ps = getLibraryPackage(computer, libInfo);
349                 if (ps == null) {
350                     continue;
351                 }
352                 // Skip unused libs cached less than the min period to prevent pruning a lib
353                 // needed by a subsequently installed package.
354                 if (now - ps.getLastUpdateTime() < maxCachePeriod) {
355                     continue;
356                 }
357 
358                 if (ps.getPkg().isSystem()) {
359                     continue;
360                 }
361 
362                 packagesToDelete.add(new VersionedPackage(ps.getPkg().getPackageName(),
363                         libInfo.getDeclaringPackage().getLongVersionCode()));
364             }
365         }
366 
367         final int packageCount = packagesToDelete.size();
368         for (int i = 0; i < packageCount; i++) {
369             final VersionedPackage pkgToDelete = packagesToDelete.get(i);
370             // Delete the package synchronously (will fail of the lib used for any user).
371             if (mDeletePackageHelper.deletePackageX(pkgToDelete.getPackageName(),
372                     pkgToDelete.getLongVersionCode(), UserHandle.USER_SYSTEM,
373                     PackageManager.DELETE_ALL_USERS,
374                     true /*removedBySystem*/) == PackageManager.DELETE_SUCCEEDED) {
375                 if (volume.getUsableSpace() >= neededSpace) {
376                     return true;
377                 }
378             }
379         }
380 
381         return false;
382     }
383 
384     /**
385      * Given a package of static shared library, returns its shared library info of
386      * the latest version.
387      *
388      * @param pkg A package of static shared library.
389      * @return The latest version of shared library info.
390      */
391     @GuardedBy("mPm.mLock")
392     @Nullable SharedLibraryInfo getLatestStaticSharedLibraVersionLPr(@NonNull AndroidPackage pkg) {
393         WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
394                 pkg.getStaticSharedLibName());
395         if (versionedLib == null) {
396             return null;
397         }
398         long previousLibVersion = -1;
399         final int versionCount = versionedLib.size();
400         for (int i = 0; i < versionCount; i++) {
401             final long libVersion = versionedLib.keyAt(i);
402             if (libVersion < pkg.getStaticSharedLibVersion()) {
403                 previousLibVersion = Math.max(previousLibVersion, libVersion);
404             }
405         }
406         if (previousLibVersion >= 0) {
407             return versionedLib.get(previousLibVersion);
408         }
409         return null;
410     }
411 
412     /**
413      * Given a package scanned result of a static shared library, returns its package setting of
414      * the latest version
415      *
416      * @param scanResult The scanned result of a static shared library package.
417      * @return The package setting that represents the latest version of shared library info.
418      */
419     @Nullable
420     PackageSetting getStaticSharedLibLatestVersionSetting(@NonNull ScanResult scanResult) {
421         PackageSetting sharedLibPackage = null;
422         synchronized (mPm.mLock) {
423             final SharedLibraryInfo latestSharedLibraVersionLPr =
424                     getLatestStaticSharedLibraVersionLPr(scanResult.mRequest.mParsedPackage);
425             if (latestSharedLibraVersionLPr != null) {
426                 sharedLibPackage = mPm.mSettings.getPackageLPr(
427                         latestSharedLibraVersionLPr.getPackageName());
428             }
429         }
430         return sharedLibPackage;
431     }
432 
433     /**
434      * Apply a given {@code action} to all the libraries defining in the package.
435      *
436      * @param pkg A package defining libraries.
437      * @param libInfo An extra shared library info passing to the action.
438      * @param action The action to apply.
439      */
440     @GuardedBy("mPm.mLock")
441     private void applyDefiningSharedLibraryUpdateLPr(
442             @NonNull AndroidPackage pkg, @Nullable SharedLibraryInfo libInfo,
443             @NonNull BiConsumer<SharedLibraryInfo, SharedLibraryInfo> action) {
444         // Note that libraries defined by this package may be null if:
445         // - Package manager was unable to create the shared library. The package still
446         //   gets installed, but the shared library does not get created.
447         // Or:
448         // - Package manager is in a state where package isn't scanned yet. This will
449         //   get called again after scanning to fix the dependencies.
450         if (AndroidPackageUtils.isLibrary(pkg)) {
451             if (pkg.getSdkLibName() != null) {
452                 SharedLibraryInfo definedLibrary = getSharedLibraryInfo(
453                         pkg.getSdkLibName(), pkg.getSdkLibVersionMajor());
454                 if (definedLibrary != null) {
455                     action.accept(definedLibrary, libInfo);
456                 }
457             } else if (pkg.getStaticSharedLibName() != null) {
458                 SharedLibraryInfo definedLibrary = getSharedLibraryInfo(
459                         pkg.getStaticSharedLibName(), pkg.getStaticSharedLibVersion());
460                 if (definedLibrary != null) {
461                     action.accept(definedLibrary, libInfo);
462                 }
463             } else {
464                 for (String libraryName : pkg.getLibraryNames()) {
465                     SharedLibraryInfo definedLibrary = getSharedLibraryInfo(
466                             libraryName, SharedLibraryInfo.VERSION_UNDEFINED);
467                     if (definedLibrary != null) {
468                         action.accept(definedLibrary, libInfo);
469                     }
470                 }
471             }
472         }
473     }
474 
475     /**
476      * Adds shared library {@code libInfo}'s self code paths and using library files to the list
477      * {@code usesLibraryFiles}. Also, adds the dependencies to the shared libraries that are
478      * defining in the {@code pkg}.
479      *
480      * @param pkg A package that is using the {@code libInfo}.
481      * @param usesLibraryFiles A list to add code paths to.
482      * @param libInfo A shared library info that is used by the {@code pkg}.
483      * @param changingLib The updating library package.
484      * @param changingLibSetting The updating library package setting.
485      */
486     @GuardedBy("mPm.mLock")
487     private void addSharedLibraryLPr(@NonNull AndroidPackage pkg,
488             @NonNull Set<String> usesLibraryFiles, @NonNull SharedLibraryInfo libInfo,
489             @Nullable AndroidPackage changingLib, @Nullable PackageSetting changingLibSetting) {
490         if (libInfo.getPath() != null) {
491             usesLibraryFiles.add(libInfo.getPath());
492             return;
493         }
494         AndroidPackage pkgForCodePaths = mPm.mPackages.get(libInfo.getPackageName());
495         PackageSetting pkgSetting = mPm.mSettings.getPackageLPr(libInfo.getPackageName());
496         if (changingLib != null && changingLib.getPackageName().equals(libInfo.getPackageName())) {
497             // If we are doing this while in the middle of updating a library apk,
498             // then we need to make sure to use that new apk for determining the
499             // dependencies here.  (We haven't yet finished committing the new apk
500             // to the package manager state.)
501             if (pkgForCodePaths == null
502                     || pkgForCodePaths.getPackageName().equals(changingLib.getPackageName())) {
503                 pkgForCodePaths = changingLib;
504                 pkgSetting = changingLibSetting;
505             }
506         }
507         if (pkgForCodePaths != null) {
508             usesLibraryFiles.addAll(AndroidPackageUtils.getAllCodePaths(pkgForCodePaths));
509             // If the package provides libraries, add the dependency to them.
510             applyDefiningSharedLibraryUpdateLPr(pkg, libInfo, SharedLibraryInfo::addDependency);
511             if (pkgSetting != null) {
512                 usesLibraryFiles.addAll(pkgSetting.getPkgState().getUsesLibraryFiles());
513             }
514         }
515     }
516 
517     /**
518      * Collects all shared libraries being used by the target package. Rebuilds the dependencies
519      * of shared libraries and update the correct shared library code paths for it.
520      *
521      * @param pkg The target package to update shared library dependency.
522      * @param pkgSetting The target's package setting.
523      * @param changingLib The updating library package.
524      * @param changingLibSetting The updating library package setting.
525      * @param availablePackages All installed packages and current being installed packages.
526      */
527     @GuardedBy("mPm.mLock")
528     void updateSharedLibrariesLPw(@NonNull AndroidPackage pkg, @NonNull PackageSetting pkgSetting,
529             @Nullable AndroidPackage changingLib, @Nullable PackageSetting changingLibSetting,
530             @NonNull Map<String, AndroidPackage> availablePackages)
531             throws PackageManagerException {
532         final ArrayList<SharedLibraryInfo> sharedLibraryInfos = collectSharedLibraryInfos(
533                 pkg, availablePackages, null /* newLibraries */);
534         executeSharedLibrariesUpdateLPw(pkg, pkgSetting, changingLib, changingLibSetting,
535                 sharedLibraryInfos, mPm.mUserManager.getUserIds());
536     }
537 
538     /**
539      * Rebuilds the dependencies of shared libraries for the target package, and update the
540      * shared library code paths to its package setting.
541      *
542      * @param pkg The target package to update shared library dependency.
543      * @param pkgSetting The target's package setting.
544      * @param changingLib The updating library package.
545      * @param changingLibSetting The updating library package setting.
546      * @param usesLibraryInfos The shared libraries used by the target package.
547      * @param allUsers All user ids on the device.
548      */
549     @GuardedBy("mPm.mLock")
550     void executeSharedLibrariesUpdateLPw(AndroidPackage pkg,
551             @NonNull PackageSetting pkgSetting, @Nullable AndroidPackage changingLib,
552             @Nullable PackageSetting changingLibSetting,
553             ArrayList<SharedLibraryInfo> usesLibraryInfos, int[] allUsers) {
554         // If the package provides libraries, clear their old dependencies.
555         // This method will set them up again.
556         applyDefiningSharedLibraryUpdateLPr(pkg, null, (definingLibrary, dependency) -> {
557             definingLibrary.clearDependencies();
558         });
559         if (usesLibraryInfos != null) {
560             pkgSetting.getPkgState().setUsesLibraryInfos(usesLibraryInfos);
561             // Use LinkedHashSet to preserve the order of files added to
562             // usesLibraryFiles while eliminating duplicates.
563             Set<String> usesLibraryFiles = new LinkedHashSet<>();
564             for (SharedLibraryInfo libInfo : usesLibraryInfos) {
565                 addSharedLibraryLPr(pkg, usesLibraryFiles, libInfo, changingLib,
566                         changingLibSetting);
567             }
568             pkgSetting.setPkgStateLibraryFiles(usesLibraryFiles);
569 
570             // let's make sure we mark all static shared libraries as installed for the same users
571             // that its dependent packages are installed for.
572             int[] installedUsers = new int[allUsers.length];
573             int installedUserCount = 0;
574             for (int u = 0; u < allUsers.length; u++) {
575                 if (pkgSetting.getInstalled(allUsers[u])) {
576                     installedUsers[installedUserCount++] = allUsers[u];
577                 }
578             }
579             for (SharedLibraryInfo sharedLibraryInfo : usesLibraryInfos) {
580                 if (!sharedLibraryInfo.isStatic()) {
581                     continue;
582                 }
583                 final PackageSetting staticLibPkgSetting =
584                         mPm.getPackageSettingForMutation(sharedLibraryInfo.getPackageName());
585                 if (staticLibPkgSetting == null) {
586                     Slog.wtf(TAG, "Shared lib without setting: " + sharedLibraryInfo);
587                     continue;
588                 }
589                 for (int u = 0; u < installedUserCount; u++) {
590                     staticLibPkgSetting.setInstalled(true, installedUsers[u]);
591                 }
592             }
593         } else {
594             pkgSetting.getPkgState().setUsesLibraryInfos(Collections.emptyList())
595                     .setUsesLibraryFiles(Collections.emptyList());
596         }
597     }
598 
599     private static boolean hasString(List<String> list, List<String> which) {
600         if (list == null || which == null) {
601             return false;
602         }
603         for (int i = list.size() - 1; i >= 0; i--) {
604             for (int j = which.size() - 1; j >= 0; j--) {
605                 if (which.get(j).equals(list.get(i))) {
606                     return true;
607                 }
608             }
609         }
610         return false;
611     }
612 
613     /**
614      * Update shared library dependencies and code paths for applications that are using the
615      * library {@code updatedPkg}. Update all applications if the {@code updatedPkg} is null.
616      *
617      * @param updatedPkg The updating shared library package.
618      * @param updatedPkgSetting The updating shared library package setting.
619      * @param availablePackages All available packages on the device.
620      * @return Packages that has been updated.
621      */
622     @GuardedBy("mPm.mLock")
623     @Nullable ArrayList<AndroidPackage> updateAllSharedLibrariesLPw(
624             @Nullable AndroidPackage updatedPkg, @Nullable PackageSetting updatedPkgSetting,
625             @NonNull Map<String, AndroidPackage> availablePackages) {
626         ArrayList<AndroidPackage> resultList = null;
627         // Set of all descendants of a library; used to eliminate cycles
628         ArraySet<String> descendants = null;
629         // The current list of packages that need updating
630         List<Pair<AndroidPackage, PackageSetting>> needsUpdating = null;
631         if (updatedPkg != null && updatedPkgSetting != null) {
632             needsUpdating = new ArrayList<>(1);
633             needsUpdating.add(Pair.create(updatedPkg, updatedPkgSetting));
634         }
635         do {
636             final Pair<AndroidPackage, PackageSetting> changingPkgPair =
637                     (needsUpdating == null) ? null : needsUpdating.remove(0);
638             final AndroidPackage changingPkg = changingPkgPair != null
639                     ? changingPkgPair.first : null;
640             final PackageSetting changingPkgSetting = changingPkgPair != null
641                     ? changingPkgPair.second : null;
642             for (int i = mPm.mPackages.size() - 1; i >= 0; --i) {
643                 final AndroidPackage pkg = mPm.mPackages.valueAt(i);
644                 final PackageSetting pkgSetting = mPm.mSettings.getPackageLPr(pkg.getPackageName());
645                 if (changingPkg != null
646                         && !hasString(pkg.getUsesLibraries(), changingPkg.getLibraryNames())
647                         && !hasString(pkg.getUsesOptionalLibraries(), changingPkg.getLibraryNames())
648                         && !ArrayUtils.contains(pkg.getUsesStaticLibraries(),
649                         changingPkg.getStaticSharedLibName())
650                         && !ArrayUtils.contains(pkg.getUsesSdkLibraries(),
651                         changingPkg.getSdkLibName())) {
652                     continue;
653                 }
654                 if (resultList == null) {
655                     resultList = new ArrayList<>();
656                 }
657                 resultList.add(pkg);
658                 // if we're updating a shared library, all of its descendants must be updated
659                 if (changingPkg != null) {
660                     if (descendants == null) {
661                         descendants = new ArraySet<>();
662                     }
663                     if (!descendants.contains(pkg.getPackageName())) {
664                         descendants.add(pkg.getPackageName());
665                         needsUpdating.add(Pair.create(pkg, pkgSetting));
666                     }
667                 }
668                 try {
669                     updateSharedLibrariesLPw(pkg, pkgSetting, changingPkg,
670                             changingPkgSetting, availablePackages);
671                 } catch (PackageManagerException e) {
672                     // If a system app update or an app and a required lib missing we
673                     // delete the package and for updated system apps keep the data as
674                     // it is better for the user to reinstall than to be in an limbo
675                     // state. Also libs disappearing under an app should never happen
676                     // - just in case.
677                     if (!pkg.isSystem() || pkgSetting.getPkgState().isUpdatedSystemApp()) {
678                         final int flags = pkgSetting.getPkgState().isUpdatedSystemApp()
679                                 ? PackageManager.DELETE_KEEP_DATA : 0;
680                         mDeletePackageHelper.deletePackageLIF(pkg.getPackageName(), null, true,
681                                 mPm.mUserManager.getUserIds(), flags, null,
682                                 true);
683                     }
684                     Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
685                 }
686             }
687         } while (needsUpdating != null && needsUpdating.size() > 0);
688         return resultList;
689     }
690 
691     /**
692      * Add a build-in shared library info by given system configuration.
693      */
694     @GuardedBy("mPm.mLock")
695     void addBuiltInSharedLibraryLPw(@NonNull SystemConfig.SharedLibraryEntry entry) {
696         // check if built-in or dynamic library exists
697         if (getSharedLibraryInfo(entry.name, SharedLibraryInfo.VERSION_UNDEFINED) != null) {
698             return;
699         }
700 
701         SharedLibraryInfo libraryInfo = new SharedLibraryInfo(entry.filename, null, null,
702                 entry.name, SharedLibraryInfo.VERSION_UNDEFINED,
703                 SharedLibraryInfo.TYPE_BUILTIN,
704                 new VersionedPackage(PLATFORM_PACKAGE_NAME, 0L), null, null,
705                 entry.isNative);
706 
707         commitSharedLibraryInfoLPw(libraryInfo);
708     }
709 
710     /**
711      * Add a shared library info to the system. This is invoked when the package is being added or
712      * scanned.
713      */
714     @GuardedBy("mPm.mLock")
715     void commitSharedLibraryInfoLPw(@NonNull SharedLibraryInfo libraryInfo) {
716         final String name = libraryInfo.getName();
717         WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
718         if (versionedLib == null) {
719             versionedLib = new WatchedLongSparseArray<>();
720             mSharedLibraries.put(name, versionedLib);
721         }
722         final String declaringPackageName = libraryInfo.getDeclaringPackage().getPackageName();
723         if (libraryInfo.getType() == SharedLibraryInfo.TYPE_STATIC) {
724             mStaticLibsByDeclaringPackage.put(declaringPackageName, versionedLib);
725         }
726         versionedLib.put(libraryInfo.getLongVersion(), libraryInfo);
727     }
728 
729     /**
730      * Remove a shared library from the system.
731      */
732     @GuardedBy("mPm.mLock")
733     boolean removeSharedLibraryLPw(@NonNull String libName, long version) {
734         WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(libName);
735         if (versionedLib == null) {
736             return false;
737         }
738         final int libIdx = versionedLib.indexOfKey(version);
739         if (libIdx < 0) {
740             return false;
741         }
742         SharedLibraryInfo libraryInfo = versionedLib.valueAt(libIdx);
743 
744         final Computer snapshot = mPm.snapshotComputer();
745 
746         // Remove the shared library overlays from its dependent packages.
747         for (int currentUserId : mPm.mUserManager.getUserIds()) {
748             final List<VersionedPackage> dependents = snapshot.getPackagesUsingSharedLibrary(
749                     libraryInfo, 0, Process.SYSTEM_UID, currentUserId);
750             if (dependents == null) {
751                 continue;
752             }
753             for (VersionedPackage dependentPackage : dependents) {
754                 final PackageSetting ps = mPm.mSettings.getPackageLPr(
755                         dependentPackage.getPackageName());
756                 if (ps != null) {
757                     ps.setOverlayPathsForLibrary(libraryInfo.getName(), null, currentUserId);
758                 }
759             }
760         }
761 
762         versionedLib.remove(version);
763         if (versionedLib.size() <= 0) {
764             mSharedLibraries.remove(libName);
765             if (libraryInfo.getType() == SharedLibraryInfo.TYPE_STATIC) {
766                 mStaticLibsByDeclaringPackage.remove(libraryInfo.getDeclaringPackage()
767                         .getPackageName());
768             }
769         }
770         return true;
771     }
772 
773     /**
774      * Compare the newly scanned package with current system state to see which of its declared
775      * shared libraries should be allowed to be added to the system.
776      */
777     List<SharedLibraryInfo> getAllowedSharedLibInfos(ScanResult scanResult) {
778         // Let's used the parsed package as scanResult.pkgSetting may be null
779         final ParsedPackage parsedPackage = scanResult.mRequest.mParsedPackage;
780         if (scanResult.mSdkSharedLibraryInfo == null && scanResult.mStaticSharedLibraryInfo == null
781                 && scanResult.mDynamicSharedLibraryInfos == null) {
782             return null;
783         }
784 
785         // Any app can add new SDKs and static shared libraries.
786         if (scanResult.mSdkSharedLibraryInfo != null) {
787             return Collections.singletonList(scanResult.mSdkSharedLibraryInfo);
788         }
789         if (scanResult.mStaticSharedLibraryInfo != null) {
790             return Collections.singletonList(scanResult.mStaticSharedLibraryInfo);
791         }
792         final boolean hasDynamicLibraries = parsedPackage.isSystem()
793                 && scanResult.mDynamicSharedLibraryInfos != null;
794         if (!hasDynamicLibraries) {
795             return null;
796         }
797         final boolean isUpdatedSystemApp = scanResult.mPkgSetting.getPkgState()
798                 .isUpdatedSystemApp();
799         // We may not yet have disabled the updated package yet, so be sure to grab the
800         // current setting if that's the case.
801         final PackageSetting updatedSystemPs = isUpdatedSystemApp
802                 ? scanResult.mRequest.mDisabledPkgSetting == null
803                 ? scanResult.mRequest.mOldPkgSetting
804                 : scanResult.mRequest.mDisabledPkgSetting
805                 : null;
806         if (isUpdatedSystemApp && (updatedSystemPs.getPkg() == null
807                 || updatedSystemPs.getPkg().getLibraryNames() == null)) {
808             Slog.w(TAG, "Package " + parsedPackage.getPackageName()
809                     + " declares libraries that are not declared on the system image; skipping");
810             return null;
811         }
812         final ArrayList<SharedLibraryInfo> infos =
813                 new ArrayList<>(scanResult.mDynamicSharedLibraryInfos.size());
814         for (SharedLibraryInfo info : scanResult.mDynamicSharedLibraryInfos) {
815             final String name = info.getName();
816             if (isUpdatedSystemApp) {
817                 // New library entries can only be added through the
818                 // system image.  This is important to get rid of a lot
819                 // of nasty edge cases: for example if we allowed a non-
820                 // system update of the app to add a library, then uninstalling
821                 // the update would make the library go away, and assumptions
822                 // we made such as through app install filtering would now
823                 // have allowed apps on the device which aren't compatible
824                 // with it.  Better to just have the restriction here, be
825                 // conservative, and create many fewer cases that can negatively
826                 // impact the user experience.
827                 if (!updatedSystemPs.getPkg().getLibraryNames().contains(name)) {
828                     Slog.w(TAG, "Package " + parsedPackage.getPackageName()
829                             + " declares library " + name
830                             + " that is not declared on system image; skipping");
831                     continue;
832                 }
833             }
834             synchronized (mPm.mLock) {
835                 if (getSharedLibraryInfo(name, SharedLibraryInfo.VERSION_UNDEFINED) != null) {
836                     Slog.w(TAG, "Package " + parsedPackage.getPackageName() + " declares library "
837                             + name + " that already exists; skipping");
838                     continue;
839                 }
840             }
841             infos.add(info);
842         }
843         return infos;
844     }
845 
846     /**
847      * Collects shared library infos that are being used by the given package.
848      *
849      * @param pkg The package using shared libraries.
850      * @param availablePackages The available packages which are installed and being installed,
851      * @param newLibraries Shared libraries defined by packages which are being installed.
852      * @return A list of shared library infos
853      */
854     ArrayList<SharedLibraryInfo> collectSharedLibraryInfos(@Nullable AndroidPackage pkg,
855             @NonNull Map<String, AndroidPackage> availablePackages,
856             @Nullable final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> newLibraries)
857             throws PackageManagerException {
858         if (pkg == null) {
859             return null;
860         }
861         final PlatformCompat platformCompat = mInjector.getCompatibility();
862         // The collection used here must maintain the order of addition (so
863         // that libraries are searched in the correct order) and must have no
864         // duplicates.
865         ArrayList<SharedLibraryInfo> usesLibraryInfos = null;
866         if (!pkg.getUsesLibraries().isEmpty()) {
867             usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesLibraries(), null, null,
868                     pkg.getPackageName(), "shared", true, pkg.getTargetSdkVersion(), null,
869                     availablePackages, newLibraries);
870         }
871         if (!pkg.getUsesStaticLibraries().isEmpty()) {
872             usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesStaticLibraries(),
873                     pkg.getUsesStaticLibrariesVersions(), pkg.getUsesStaticLibrariesCertDigests(),
874                     pkg.getPackageName(), "static shared", true, pkg.getTargetSdkVersion(),
875                     usesLibraryInfos, availablePackages, newLibraries);
876         }
877         if (!pkg.getUsesOptionalLibraries().isEmpty()) {
878             usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesOptionalLibraries(), null, null,
879                     pkg.getPackageName(), "shared", false, pkg.getTargetSdkVersion(),
880                     usesLibraryInfos, availablePackages, newLibraries);
881         }
882         if (platformCompat.isChangeEnabledInternal(ENFORCE_NATIVE_SHARED_LIBRARY_DEPENDENCIES,
883                 pkg.getPackageName(), pkg.getTargetSdkVersion())) {
884             if (!pkg.getUsesNativeLibraries().isEmpty()) {
885                 usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesNativeLibraries(), null,
886                         null, pkg.getPackageName(), "native shared", true,
887                         pkg.getTargetSdkVersion(), usesLibraryInfos, availablePackages,
888                         newLibraries);
889             }
890             if (!pkg.getUsesOptionalNativeLibraries().isEmpty()) {
891                 usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesOptionalNativeLibraries(),
892                         null, null, pkg.getPackageName(), "native shared", false,
893                         pkg.getTargetSdkVersion(), usesLibraryInfos, availablePackages,
894                         newLibraries);
895             }
896         }
897         if (!pkg.getUsesSdkLibraries().isEmpty()) {
898             usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesSdkLibraries(),
899                     pkg.getUsesSdkLibrariesVersionsMajor(), pkg.getUsesSdkLibrariesCertDigests(),
900                     pkg.getPackageName(), "sdk", true, pkg.getTargetSdkVersion(), usesLibraryInfos,
901                     availablePackages, newLibraries);
902         }
903         return usesLibraryInfos;
904     }
905 
906     private ArrayList<SharedLibraryInfo> collectSharedLibraryInfos(
907             @NonNull List<String> requestedLibraries,
908             @Nullable long[] requiredVersions, @Nullable String[][] requiredCertDigests,
909             @NonNull String packageName, @NonNull String libraryType, boolean required,
910             int targetSdk, @Nullable ArrayList<SharedLibraryInfo> outUsedLibraries,
911             @NonNull final Map<String, AndroidPackage> availablePackages,
912             @Nullable final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> newLibraries)
913             throws PackageManagerException {
914         final int libCount = requestedLibraries.size();
915         for (int i = 0; i < libCount; i++) {
916             final String libName = requestedLibraries.get(i);
917             final long libVersion = requiredVersions != null ? requiredVersions[i]
918                     : SharedLibraryInfo.VERSION_UNDEFINED;
919             final SharedLibraryInfo libraryInfo;
920             synchronized (mPm.mLock) {
921                 libraryInfo = SharedLibraryUtils.getSharedLibraryInfo(
922                         libName, libVersion, mSharedLibraries, newLibraries);
923             }
924             if (libraryInfo == null) {
925                 if (required) {
926                     throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
927                             "Package " + packageName + " requires unavailable " + libraryType
928                                     + " library " + libName + "; failing!");
929                 } else if (DEBUG_SHARED_LIBRARIES) {
930                     Slog.i(TAG, "Package " + packageName + " desires unavailable " + libraryType
931                             + " library " + libName + "; ignoring!");
932                 }
933             } else {
934                 if (requiredVersions != null && requiredCertDigests != null) {
935                     if (libraryInfo.getLongVersion() != requiredVersions[i]) {
936                         throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
937                                 "Package " + packageName + " requires unavailable " + libraryType
938                                         + " library " + libName + " version "
939                                         + libraryInfo.getLongVersion() + "; failing!");
940                     }
941                     AndroidPackage pkg = availablePackages.get(libraryInfo.getPackageName());
942                     SigningDetails libPkg = pkg == null ? null : pkg.getSigningDetails();
943                     if (libPkg == null) {
944                         throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
945                                 "Package " + packageName + " requires unavailable " + libraryType
946                                         + " library; failing!");
947                     }
948                     final String[] expectedCertDigests = requiredCertDigests[i];
949                     if (expectedCertDigests.length > 1) {
950                         // For apps targeting O MR1 we require explicit enumeration of all certs.
951                         final String[] libCertDigests = (targetSdk >= Build.VERSION_CODES.O_MR1)
952                                 ? PackageUtils.computeSignaturesSha256Digests(
953                                 libPkg.getSignatures())
954                                 : PackageUtils.computeSignaturesSha256Digests(
955                                         new Signature[]{libPkg.getSignatures()[0]});
956 
957                         // Take a shortcut if sizes don't match. Note that if an app doesn't
958                         // target O we don't parse the "additional-certificate" tags similarly
959                         // how we only consider all certs only for apps targeting O (see above).
960                         // Therefore, the size check is safe to make.
961                         if (expectedCertDigests.length != libCertDigests.length) {
962                             throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
963                                     "Package " + packageName + " requires differently signed "
964                                             + libraryType + " library; failing!");
965                         }
966 
967                         // Use a predictable order as signature order may vary
968                         Arrays.sort(libCertDigests);
969                         Arrays.sort(expectedCertDigests);
970 
971                         final int certCount = libCertDigests.length;
972                         for (int j = 0; j < certCount; j++) {
973                             if (!libCertDigests[j].equalsIgnoreCase(expectedCertDigests[j])) {
974                                 throw new PackageManagerException(
975                                         INSTALL_FAILED_MISSING_SHARED_LIBRARY,
976                                         "Package " + packageName + " requires differently signed "
977                                                 + libraryType + " library; failing!");
978                             }
979                         }
980                     } else {
981                         // lib signing cert could have rotated beyond the one expected, check to see
982                         // if the new one has been blessed by the old
983                         byte[] digestBytes = HexEncoding.decode(
984                                 expectedCertDigests[0], false /* allowSingleChar */);
985                         if (!libPkg.hasSha256Certificate(digestBytes)) {
986                             throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
987                                     "Package " + packageName + " requires differently signed "
988                                             + libraryType + " library; failing!");
989                         }
990                     }
991                 }
992                 if (outUsedLibraries == null) {
993                     outUsedLibraries = new ArrayList<>();
994                 }
995                 outUsedLibraries.add(libraryInfo);
996             }
997         }
998         return outUsedLibraries;
999     }
1000 
1001     /**
1002      * Dump all shared libraries.
1003      */
1004     @GuardedBy("mPm.mLock")
1005     @Override
1006     public void dump(@NonNull PrintWriter pw, @NonNull DumpState dumpState) {
1007         final boolean checkin = dumpState.isCheckIn();
1008         boolean printedHeader = false;
1009         final int numSharedLibraries = mSharedLibraries.size();
1010         for (int index = 0; index < numSharedLibraries; index++) {
1011             final String libName = mSharedLibraries.keyAt(index);
1012             final WatchedLongSparseArray<SharedLibraryInfo> versionedLib =
1013                     mSharedLibraries.get(libName);
1014             if (versionedLib == null) {
1015                 continue;
1016             }
1017             final int versionCount = versionedLib.size();
1018             for (int i = 0; i < versionCount; i++) {
1019                 SharedLibraryInfo libraryInfo = versionedLib.valueAt(i);
1020                 if (!checkin) {
1021                     if (!printedHeader) {
1022                         if (dumpState.onTitlePrinted()) {
1023                             pw.println();
1024                         }
1025                         pw.println("Libraries:");
1026                         printedHeader = true;
1027                     }
1028                     pw.print("  ");
1029                 } else {
1030                     pw.print("lib,");
1031                 }
1032                 pw.print(libraryInfo.getName());
1033                 if (libraryInfo.isStatic()) {
1034                     pw.print(" version=" + libraryInfo.getLongVersion());
1035                 }
1036                 if (!checkin) {
1037                     pw.print(" -> ");
1038                 }
1039                 if (libraryInfo.getPath() != null) {
1040                     if (libraryInfo.isNative()) {
1041                         pw.print(" (so) ");
1042                     } else {
1043                         pw.print(" (jar) ");
1044                     }
1045                     pw.print(libraryInfo.getPath());
1046                 } else {
1047                     pw.print(" (apk) ");
1048                     pw.print(libraryInfo.getPackageName());
1049                 }
1050                 pw.println();
1051             }
1052         }
1053     }
1054 
1055     /**
1056      * Dump all shared libraries to given proto output stream.
1057      */
1058     @GuardedBy("mPm.mLock")
1059     @Override
1060     public void dumpProto(@NonNull ProtoOutputStream proto) {
1061         final int count = mSharedLibraries.size();
1062         for (int i = 0; i < count; i++) {
1063             final String libName = mSharedLibraries.keyAt(i);
1064             WatchedLongSparseArray<SharedLibraryInfo> versionedLib =
1065                     mSharedLibraries.get(libName);
1066             if (versionedLib == null) {
1067                 continue;
1068             }
1069             final int versionCount = versionedLib.size();
1070             for (int j = 0; j < versionCount; j++) {
1071                 final SharedLibraryInfo libraryInfo = versionedLib.valueAt(j);
1072                 final long sharedLibraryToken =
1073                         proto.start(PackageServiceDumpProto.SHARED_LIBRARIES);
1074                 proto.write(PackageServiceDumpProto.SharedLibraryProto.NAME, libraryInfo.getName());
1075                 final boolean isJar = (libraryInfo.getPath() != null);
1076                 proto.write(PackageServiceDumpProto.SharedLibraryProto.IS_JAR, isJar);
1077                 if (isJar) {
1078                     proto.write(PackageServiceDumpProto.SharedLibraryProto.PATH,
1079                             libraryInfo.getPath());
1080                 } else {
1081                     proto.write(PackageServiceDumpProto.SharedLibraryProto.APK,
1082                             libraryInfo.getPackageName());
1083                 }
1084                 proto.end(sharedLibraryToken);
1085             }
1086         }
1087     }
1088 }
1089