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