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