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