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