1 /* 2 * Copyright (C) 2017 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 android.content.pm; 18 19 import android.annotation.FlaggedApi; 20 import android.annotation.IntDef; 21 import android.annotation.IntRange; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.TestApi; 25 import android.os.Parcel; 26 import android.os.Parcelable; 27 import android.util.Pair; 28 29 import java.lang.annotation.Retention; 30 import java.lang.annotation.RetentionPolicy; 31 import java.util.ArrayList; 32 import java.util.Arrays; 33 import java.util.Collections; 34 import java.util.List; 35 import java.util.Objects; 36 37 /** 38 * This class provides information for a shared library. There are 39 * four types of shared libraries: builtin - non-updatable part of 40 * the OS; dynamic - updatable backwards-compatible dynamically linked; 41 * static - non backwards-compatible emulating static linking; 42 * SDK - updatable backwards-incompatible dynamically loaded. 43 */ 44 public final class SharedLibraryInfo implements Parcelable { 45 46 /** @hide */ 47 @IntDef(flag = true, prefix = { "TYPE_" }, value = { 48 TYPE_BUILTIN, 49 TYPE_DYNAMIC, 50 TYPE_STATIC, 51 TYPE_SDK_PACKAGE, 52 }) 53 @Retention(RetentionPolicy.SOURCE) 54 public @interface Type{} 55 56 /** 57 * Shared library type: this library is a part of the OS 58 * and cannot be updated or uninstalled. 59 */ 60 public static final int TYPE_BUILTIN = 0; 61 62 /** 63 * Shared library type: this library is backwards-compatible, can 64 * be updated, and updates can be uninstalled. Clients link against 65 * the latest version of the library. 66 */ 67 public static final int TYPE_DYNAMIC = 1; 68 69 /** 70 * Shared library type: this library is <strong>not</strong> backwards 71 * -compatible, can be updated and updates can be uninstalled. Clients 72 * link against a specific version of the library. 73 * 74 * Static shared libraries simulate static linking while allowing for 75 * multiple clients to reuse the same instance of the library. 76 */ 77 public static final int TYPE_STATIC = 2; 78 79 /** 80 * SDK package shared library type: this library is <strong>not</strong> 81 * compatible between versions, can be updated and updates can be 82 * uninstalled. Clients depend on a specific version of the library. 83 * 84 * SDK packages are not loaded automatically by the OS and rely 85 * e.g. on 3P libraries to make them available for the clients. 86 */ 87 public static final int TYPE_SDK_PACKAGE = 3; 88 89 /** 90 * Constant for referring to an undefined version. 91 */ 92 public static final int VERSION_UNDEFINED = -1; 93 94 private final String mPath; 95 private final String mPackageName; 96 private final String mName; 97 private List<String> mCodePaths; 98 99 private final long mVersion; 100 private final @Type int mType; 101 private final boolean mIsNative; 102 private final VersionedPackage mDeclaringPackage; 103 private final List<VersionedPackage> mDependentPackages; 104 105 private final List<VersionedPackage> mOptionalDependentPackages; 106 private List<SharedLibraryInfo> mDependencies; 107 108 private final List<String> mCertDigests; 109 110 /** 111 * Creates a new instance. 112 * 113 * @param codePaths For a non {@link #TYPE_BUILTIN builtin} library, the locations of 114 * jars of 115 * this shared library. Null for builtin library. 116 * @param name The lib name. 117 * @param version The lib version if not builtin. 118 * @param type The lib type. 119 * @param declaringPackage The package that declares the library. 120 * @param dependentPackages The packages that depend on the library. 121 * @param isNative indicate if this shared lib is a native lib or not (i.e. java) 122 * @hide 123 */ SharedLibraryInfo(String path, String packageName, List<String> codePaths, String name, long version, int type, VersionedPackage declaringPackage, List<VersionedPackage> dependentPackages, List<SharedLibraryInfo> dependencies, boolean isNative)124 public SharedLibraryInfo(String path, String packageName, List<String> codePaths, 125 String name, long version, int type, 126 VersionedPackage declaringPackage, List<VersionedPackage> dependentPackages, 127 List<SharedLibraryInfo> dependencies, boolean isNative) { 128 mPath = path; 129 mPackageName = packageName; 130 mCodePaths = codePaths; 131 mName = name; 132 mVersion = version; 133 mType = type; 134 mDeclaringPackage = declaringPackage; 135 mDependentPackages = dependentPackages; 136 mDependencies = dependencies; 137 mIsNative = isNative; 138 mOptionalDependentPackages = null; 139 mCertDigests = null; 140 } 141 142 /** 143 * Creates a new instance. 144 * 145 * @param codePaths For a non {@link #TYPE_BUILTIN builtin} library, the locations of jars of 146 * this shared library. Null for builtin library. 147 * @param name The lib name. 148 * @param version The lib version if not builtin. 149 * @param type The lib type. 150 * @param declaringPackage The package that declares the library. 151 * @param isNative indicate if this shared lib is a native lib or not (i.e. java) 152 * @param allDependentPackages All packages that depend on the library (including the optional 153 * sdk libraries). 154 * 155 * @hide 156 */ SharedLibraryInfo(String path, String packageName, List<String> codePaths, String name, long version, int type, VersionedPackage declaringPackage, List<SharedLibraryInfo> dependencies, boolean isNative, Pair<List<VersionedPackage>, List<Boolean>> allDependentPackages)157 public SharedLibraryInfo(String path, String packageName, List<String> codePaths, 158 String name, long version, int type, 159 VersionedPackage declaringPackage, 160 List<SharedLibraryInfo> dependencies, boolean isNative, 161 Pair<List<VersionedPackage>, List<Boolean>> allDependentPackages) { 162 mPath = path; 163 mPackageName = packageName; 164 mCodePaths = codePaths; 165 mName = name; 166 mVersion = version; 167 mType = type; 168 mDeclaringPackage = declaringPackage; 169 mDependencies = dependencies; 170 mIsNative = isNative; 171 mCertDigests = null; 172 173 var allDependents = allDependentPackages.first; 174 var usesLibOptional = allDependentPackages.second; 175 mDependentPackages = allDependents; 176 List<VersionedPackage> optionalDependents = null; 177 if (mType == SharedLibraryInfo.TYPE_SDK_PACKAGE 178 && Flags.sdkLibIndependence() && allDependents != null 179 && usesLibOptional != null 180 && allDependents.size() == usesLibOptional.size()) { 181 for (int k = 0; k < allDependents.size(); k++) { 182 VersionedPackage versionedPackage = allDependents.get(k); 183 if (usesLibOptional.get(k)) { 184 if (optionalDependents == null) { 185 optionalDependents = new ArrayList<>(); 186 } 187 optionalDependents.add(versionedPackage); 188 } 189 } 190 } 191 mOptionalDependentPackages = optionalDependents; 192 } 193 SharedLibraryInfo(Parcel parcel)194 private SharedLibraryInfo(Parcel parcel) { 195 mPath = parcel.readString8(); 196 mPackageName = parcel.readString8(); 197 if (parcel.readInt() != 0) { 198 mCodePaths = Arrays.asList(parcel.createString8Array()); 199 } else { 200 mCodePaths = null; 201 } 202 mName = parcel.readString8(); 203 mVersion = parcel.readLong(); 204 mType = parcel.readInt(); 205 mDeclaringPackage = 206 parcel.readParcelable(null, android.content.pm.VersionedPackage.class); 207 mDependentPackages = 208 parcel.readArrayList(null, android.content.pm.VersionedPackage.class); 209 mDependencies = parcel.createTypedArrayList(SharedLibraryInfo.CREATOR); 210 mIsNative = parcel.readBoolean(); 211 mOptionalDependentPackages = parcel.readParcelableList(new ArrayList<>(), 212 VersionedPackage.class.getClassLoader(), VersionedPackage.class); 213 mCertDigests = parcel.createStringArrayList(); 214 } 215 216 /** 217 * @hide 218 * @param name 219 * @param versionMajor 220 */ SharedLibraryInfo(String name, long versionMajor, int type)221 public SharedLibraryInfo(String name, long versionMajor, int type) { 222 //TODO: change to this(name, versionMajor, type, /* certDigest= */null); after flag removal 223 mPath = null; 224 mPackageName = null; 225 mName = name; 226 mVersion = versionMajor; 227 mType = type; 228 mDeclaringPackage = null; 229 mDependentPackages = null; 230 mDependencies = null; 231 mIsNative = false; 232 mOptionalDependentPackages = null; 233 mCertDigests = null; 234 } 235 236 /** 237 * @hide 238 * @param name The lib name. 239 * @param versionMajor The lib major version. 240 * @param type The type of shared library. 241 * @param certDigests The list of certificate digests for this shared library. 242 */ 243 @FlaggedApi(Flags.FLAG_SDK_DEPENDENCY_INSTALLER) SharedLibraryInfo(String name, long versionMajor, int type, List<String> certDigests)244 public SharedLibraryInfo(String name, long versionMajor, int type, List<String> certDigests) { 245 mPath = null; 246 mPackageName = null; 247 mName = name; 248 mVersion = versionMajor; 249 mType = type; 250 mDeclaringPackage = null; 251 mDependentPackages = null; 252 mDependencies = null; 253 mIsNative = false; 254 mOptionalDependentPackages = null; 255 mCertDigests = certDigests; 256 } 257 258 /** 259 * Gets the type of this library. 260 * 261 * @return The library type. 262 */ getType()263 public @Type int getType() { 264 return mType; 265 } 266 267 /** 268 * Tells whether this library is a native shared library or not. 269 * 270 * @hide 271 */ 272 @TestApi isNative()273 public boolean isNative() { 274 return mIsNative; 275 } 276 277 /** 278 * Gets the library name an app defines in its manifest 279 * to depend on the library. 280 * 281 * @return The name. 282 */ getName()283 public String getName() { 284 return mName; 285 } 286 287 /** 288 * If the shared library is a jar file, returns the path of that jar. Null otherwise. 289 * Only libraries with TYPE_BUILTIN are in jar files. 290 * 291 * @return The path. 292 * 293 * @hide 294 */ getPath()295 public @Nullable String getPath() { 296 return mPath; 297 } 298 299 /** 300 * If the shared library is an apk, returns the package name. Null otherwise. 301 * Only libraries with TYPE_DYNAMIC or TYPE_STATIC are in apks. 302 * 303 * @return The package name. 304 * 305 * @hide 306 */ getPackageName()307 public @Nullable String getPackageName() { 308 return mPackageName; 309 } 310 311 /** 312 * Get all code paths for that library. 313 * 314 * @return All code paths. 315 * 316 * @hide 317 */ 318 @TestApi getAllCodePaths()319 public @NonNull List<String> getAllCodePaths() { 320 if (getPath() != null) { 321 // Builtin library. 322 ArrayList<String> list = new ArrayList<>(); 323 list.add(getPath()); 324 return list; 325 } else { 326 // Static or dynamic library. 327 return Objects.requireNonNull(mCodePaths); 328 } 329 } 330 331 /** 332 * Sets new all code paths for that library. 333 * 334 * @hide 335 */ setAllCodePaths(List<String> paths)336 public void setAllCodePaths(List<String> paths) { 337 mCodePaths = paths; 338 } 339 340 /** 341 * Add a library dependency to that library. Note that this 342 * should be called under the package manager lock. 343 * 344 * @hide 345 */ addDependency(@ullable SharedLibraryInfo info)346 public void addDependency(@Nullable SharedLibraryInfo info) { 347 if (info == null) { 348 // For convenience of the caller, allow null to be passed. 349 // This can happen when we create the dependencies of builtin 350 // libraries. 351 return; 352 } 353 if (mDependencies == null) { 354 mDependencies = new ArrayList<>(); 355 } 356 mDependencies.add(info); 357 } 358 359 /** 360 * Clear all dependencies. 361 * 362 * @hide 363 */ clearDependencies()364 public void clearDependencies() { 365 mDependencies = null; 366 } 367 368 /** 369 * Gets the libraries this library directly depends on. Note that 370 * the package manager prevents recursive dependencies when installing 371 * a package. 372 * 373 * @return The dependencies. 374 * 375 * @hide 376 */ getDependencies()377 public @Nullable List<SharedLibraryInfo> getDependencies() { 378 return mDependencies; 379 } 380 381 /** 382 * @deprecated Use {@link #getLongVersion()} instead. 383 */ 384 @Deprecated getVersion()385 public @IntRange(from = -1) int getVersion() { 386 return mVersion < 0 ? (int) mVersion : (int) (mVersion & 0x7fffffff); 387 } 388 389 /** 390 * Gets the version of the library. For {@link #TYPE_STATIC static} libraries 391 * this is the declared version and for {@link #TYPE_DYNAMIC dynamic} and 392 * {@link #TYPE_BUILTIN builtin} it is {@link #VERSION_UNDEFINED} as these 393 * are not versioned. 394 * 395 * @return The version. 396 */ getLongVersion()397 public @IntRange(from = -1) long getLongVersion() { 398 return mVersion; 399 } 400 401 /** 402 * @removed 403 */ isBuiltin()404 public boolean isBuiltin() { 405 return mType == TYPE_BUILTIN; 406 } 407 408 /** 409 * @removed 410 */ isDynamic()411 public boolean isDynamic() { 412 return mType == TYPE_DYNAMIC; 413 } 414 415 /** 416 * @removed 417 */ isStatic()418 public boolean isStatic() { 419 return mType == TYPE_STATIC; 420 } 421 422 /** 423 * @hide 424 */ isSdk()425 public boolean isSdk() { 426 return mType == TYPE_SDK_PACKAGE; 427 } 428 429 /** 430 * Gets the package that declares the library. 431 * 432 * @return The package declaring the library. 433 */ getDeclaringPackage()434 public @NonNull VersionedPackage getDeclaringPackage() { 435 return mDeclaringPackage; 436 } 437 438 /** 439 * Gets the packages that depend on the library. 440 * 441 * NOTE: the list also contains the result of {@link #getOptionalDependentPackages}. 442 * 443 * @return The dependent packages. 444 */ getDependentPackages()445 public @NonNull List<VersionedPackage> getDependentPackages() { 446 if (mDependentPackages == null) { 447 return Collections.emptyList(); 448 } 449 return mDependentPackages; 450 } 451 452 /** 453 * Gets the packages that optionally depend on the library. 454 * 455 * @return The dependent packages. 456 */ 457 @FlaggedApi(Flags.FLAG_SDK_LIB_INDEPENDENCE) getOptionalDependentPackages()458 public @NonNull List<VersionedPackage> getOptionalDependentPackages() { 459 if (mOptionalDependentPackages == null) { 460 return Collections.emptyList(); 461 } 462 return mOptionalDependentPackages; 463 } 464 465 /** 466 * Gets the list of certificate digests for the shared library. 467 * 468 * @return The list of certificate digests 469 */ 470 @FlaggedApi(Flags.FLAG_SDK_DEPENDENCY_INSTALLER) getCertDigests()471 public @NonNull List<String> getCertDigests() { 472 if (mCertDigests == null) { 473 return Collections.emptyList(); 474 } 475 return mCertDigests; 476 } 477 478 @Override describeContents()479 public int describeContents() { 480 return 0; 481 } 482 483 @Override toString()484 public String toString() { 485 return "SharedLibraryInfo{name:" + mName + ", type:" + typeToString(mType) 486 + ", version:" + mVersion + (!getDependentPackages().isEmpty() 487 ? " has dependents" : "") + "}"; 488 } 489 490 @Override writeToParcel(Parcel parcel, int flags)491 public void writeToParcel(Parcel parcel, int flags) { 492 parcel.writeString8(mPath); 493 parcel.writeString8(mPackageName); 494 if (mCodePaths != null) { 495 parcel.writeInt(1); 496 parcel.writeString8Array(mCodePaths.toArray(new String[mCodePaths.size()])); 497 } else { 498 parcel.writeInt(0); 499 } 500 parcel.writeString8(mName); 501 parcel.writeLong(mVersion); 502 parcel.writeInt(mType); 503 parcel.writeParcelable(mDeclaringPackage, flags); 504 parcel.writeList(mDependentPackages); 505 parcel.writeTypedList(mDependencies); 506 parcel.writeBoolean(mIsNative); 507 parcel.writeParcelableList(mOptionalDependentPackages, flags); 508 parcel.writeStringList(mCertDigests); 509 } 510 typeToString(int type)511 private static String typeToString(int type) { 512 switch (type) { 513 case TYPE_BUILTIN: { 514 return "builtin"; 515 } 516 case TYPE_DYNAMIC: { 517 return "dynamic"; 518 } 519 case TYPE_STATIC: { 520 return "static"; 521 } 522 case TYPE_SDK_PACKAGE: { 523 return "sdk"; 524 } 525 default: { 526 return "unknown"; 527 } 528 } 529 } 530 531 public static final @android.annotation.NonNull Parcelable.Creator<SharedLibraryInfo> CREATOR = 532 new Parcelable.Creator<SharedLibraryInfo>() { 533 public SharedLibraryInfo createFromParcel(Parcel source) { 534 return new SharedLibraryInfo(source); 535 } 536 537 public SharedLibraryInfo[] newArray(int size) { 538 return new SharedLibraryInfo[size]; 539 } 540 }; 541 } 542