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