Revert "Revert "SDK libraries.""

This reverts commit a22b7e05d4ee2dddb6e89726102b10f0d8257381.

Reason for revert: This is a roll forwards with the fix applied.

Fixes: 208710019

Change-Id: Id4e9029ebe5864ddcc5583ce525e8e70da79f82c
diff --git a/core/api/current.txt b/core/api/current.txt
index f5f3bb09..7949c80 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -13237,6 +13237,7 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.SharedLibraryInfo> CREATOR;
     field public static final int TYPE_BUILTIN = 0; // 0x0
     field public static final int TYPE_DYNAMIC = 1; // 0x1
+    field public static final int TYPE_SDK = 3; // 0x3
     field public static final int TYPE_STATIC = 2; // 0x2
     field public static final int VERSION_UNDEFINED = -1; // 0xffffffff
   }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index c777bf5..a7f3801 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -697,7 +697,7 @@
             MATCH_DISABLED_COMPONENTS,
             MATCH_DISABLED_UNTIL_USED_COMPONENTS,
             MATCH_INSTANT,
-            MATCH_STATIC_SHARED_LIBRARIES,
+            MATCH_STATIC_SHARED_AND_SDK_LIBRARIES,
             GET_DISABLED_UNTIL_USED_COMPONENTS,
             GET_UNINSTALLED_PACKAGES,
             MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS,
@@ -721,7 +721,7 @@
             MATCH_SYSTEM_ONLY,
             MATCH_UNINSTALLED_PACKAGES,
             MATCH_INSTANT,
-            MATCH_STATIC_SHARED_LIBRARIES,
+            MATCH_STATIC_SHARED_AND_SDK_LIBRARIES,
             GET_DISABLED_COMPONENTS,
             GET_DISABLED_UNTIL_USED_COMPONENTS,
             GET_UNINSTALLED_PACKAGES,
@@ -1038,14 +1038,14 @@
     public static final int MATCH_EXPLICITLY_VISIBLE_ONLY = 0x02000000;
 
     /**
-     * Internal {@link PackageInfo} flag: include static shared libraries.
-     * Apps that depend on static shared libs can always access the version
+     * Internal {@link PackageInfo} flag: include static shared and SDK libraries.
+     * Apps that depend on static shared/SDK libs can always access the version
      * of the lib they depend on. System/shell/root can access all shared
      * libs regardless of dependency but need to explicitly ask for them
      * via this flag.
      * @hide
      */
-    public static final int MATCH_STATIC_SHARED_LIBRARIES = 0x04000000;
+    public static final int MATCH_STATIC_SHARED_AND_SDK_LIBRARIES = 0x04000000;
 
     /**
      * {@link PackageInfo} flag: return the signing certificates associated with
diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java
index 7abb694..4ba2ee6 100644
--- a/core/java/android/content/pm/SharedLibraryInfo.java
+++ b/core/java/android/content/pm/SharedLibraryInfo.java
@@ -70,6 +70,13 @@
     public static final int TYPE_STATIC = 2;
 
     /**
+     * SDK library type: this library is <strong>not</strong> backwards
+     * -compatible, can be updated and updates can be uninstalled. Clients
+     * depend on a specific version of the library.
+     */
+    public static final int TYPE_SDK = 3;
+
+    /**
      * Constant for referring to an undefined version.
      */
     public static final int VERSION_UNDEFINED = -1;
@@ -289,6 +296,13 @@
     }
 
     /**
+     * @hide
+     */
+    public boolean isSdk() {
+        return mType == TYPE_SDK;
+    }
+
+    /**
      * Gets the package that declares the library.
      *
      * @return The package declaring the library.
@@ -351,6 +365,9 @@
             case TYPE_STATIC: {
                 return "static";
             }
+            case TYPE_SDK: {
+                return "sdk";
+            }
             default: {
                 return "unknown";
             }
diff --git a/core/java/android/content/pm/parsing/ParsingPackage.java b/core/java/android/content/pm/parsing/ParsingPackage.java
index 056f99f..63332e7 100644
--- a/core/java/android/content/pm/parsing/ParsingPackage.java
+++ b/core/java/android/content/pm/parsing/ParsingPackage.java
@@ -103,11 +103,11 @@
 
     ParsingPackage addUsesOptionalNativeLibrary(String libraryName);
 
-    ParsingPackage addUsesStaticLibrary(String libraryName);
+    ParsingPackage addUsesSdkLibrary(String libraryName, long versionMajor,
+            String[] certSha256Digests);
 
-    ParsingPackage addUsesStaticLibraryCertDigests(String[] certSha256Digests);
-
-    ParsingPackage addUsesStaticLibraryVersion(long version);
+    ParsingPackage addUsesStaticLibrary(String libraryName, long version,
+            String[] certSha256Digests);
 
     ParsingPackage addQueriesIntent(Intent intent);
 
@@ -212,6 +212,12 @@
 
     ParsingPackage setRestoreAnyVersion(boolean restoreAnyVersion);
 
+    ParsingPackage setSdkLibName(String sdkLibName);
+
+    ParsingPackage setSdkLibVersionMajor(int sdkLibVersionMajor);
+
+    ParsingPackage setSdkLibrary(boolean sdkLibrary);
+
     ParsingPackage setSplitHasCode(int splitIndex, boolean splitHasCode);
 
     ParsingPackage setStaticSharedLibrary(boolean staticSharedLibrary);
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index d5957a2..19a8ce9 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -179,6 +179,10 @@
 
     @Nullable
     @DataClass.ParcelWith(ForInternedString.class)
+    private String sdkLibName;
+    private int sdkLibVersionMajor;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
     private String staticSharedLibName;
     private long staticSharedLibVersion;
     @NonNull
@@ -203,10 +207,17 @@
     private List<String> usesStaticLibraries = emptyList();
     @Nullable
     private long[] usesStaticLibrariesVersions;
-
     @Nullable
     private String[][] usesStaticLibrariesCertDigests;
 
+    @NonNull
+    @DataClass.ParcelWith(ForInternedStringList.class)
+    private List<String> usesSdkLibraries = emptyList();
+    @Nullable
+    private long[] usesSdkLibrariesVersionsMajor;
+    @Nullable
+    private String[][] usesSdkLibrariesCertDigests;
+
     @Nullable
     @DataClass.ParcelWith(ForInternedString.class)
     private String sharedUserId;
@@ -518,6 +529,7 @@
         private static final long REQUEST_FOREGROUND_SERVICE_EXEMPTION = 1L << 46;
         private static final long ATTRIBUTIONS_ARE_USER_VISIBLE = 1L << 47;
         private static final long RESET_ENABLED_SETTINGS_ON_APP_DATA_CLEARED = 1L << 48;
+        private static final long SDK_LIBRARY = 1L << 49;
     }
 
     private ParsingPackageImpl setBoolean(@Booleans.Values long flag, boolean value) {
@@ -828,21 +840,24 @@
     }
 
     @Override
-    public ParsingPackageImpl addUsesStaticLibrary(String libraryName) {
+    public ParsingPackageImpl addUsesSdkLibrary(String libraryName, long versionMajor,
+            String[] certSha256Digests) {
+        this.usesSdkLibraries = CollectionUtils.add(this.usesSdkLibraries,
+                TextUtils.safeIntern(libraryName));
+        this.usesSdkLibrariesVersionsMajor = ArrayUtils.appendLong(
+                this.usesSdkLibrariesVersionsMajor, versionMajor, true);
+        this.usesSdkLibrariesCertDigests = ArrayUtils.appendElement(String[].class,
+                this.usesSdkLibrariesCertDigests, certSha256Digests, true);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addUsesStaticLibrary(String libraryName, long version,
+            String[] certSha256Digests) {
         this.usesStaticLibraries = CollectionUtils.add(this.usesStaticLibraries,
                 TextUtils.safeIntern(libraryName));
-        return this;
-    }
-
-    @Override
-    public ParsingPackageImpl addUsesStaticLibraryVersion(long version) {
         this.usesStaticLibrariesVersions = ArrayUtils.appendLong(this.usesStaticLibrariesVersions,
                 version, true);
-        return this;
-    }
-
-    @Override
-    public ParsingPackageImpl addUsesStaticLibraryCertDigests(String[] certSha256Digests) {
         this.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String[].class,
                 this.usesStaticLibrariesCertDigests, certSha256Digests, true);
         return this;
@@ -1136,6 +1151,8 @@
         dest.writeString(this.overlayCategory);
         dest.writeInt(this.overlayPriority);
         sForInternedStringValueMap.parcel(this.overlayables, dest, flags);
+        sForInternedString.parcel(this.sdkLibName, dest, flags);
+        dest.writeInt(this.sdkLibVersionMajor);
         sForInternedString.parcel(this.staticSharedLibName, dest, flags);
         dest.writeLong(this.staticSharedLibVersion);
         sForInternedStringList.parcel(this.libraryNames, dest, flags);
@@ -1143,9 +1160,9 @@
         sForInternedStringList.parcel(this.usesOptionalLibraries, dest, flags);
         sForInternedStringList.parcel(this.usesNativeLibraries, dest, flags);
         sForInternedStringList.parcel(this.usesOptionalNativeLibraries, dest, flags);
+
         sForInternedStringList.parcel(this.usesStaticLibraries, dest, flags);
         dest.writeLongArray(this.usesStaticLibrariesVersions);
-
         if (this.usesStaticLibrariesCertDigests == null) {
             dest.writeInt(-1);
         } else {
@@ -1155,6 +1172,17 @@
             }
         }
 
+        sForInternedStringList.parcel(this.usesSdkLibraries, dest, flags);
+        dest.writeLongArray(this.usesSdkLibrariesVersionsMajor);
+        if (this.usesSdkLibrariesCertDigests == null) {
+            dest.writeInt(-1);
+        } else {
+            dest.writeInt(this.usesSdkLibrariesCertDigests.length);
+            for (int index = 0; index < this.usesSdkLibrariesCertDigests.length; index++) {
+                dest.writeStringArray(this.usesSdkLibrariesCertDigests[index]);
+            }
+        }
+
         sForInternedString.parcel(this.sharedUserId, dest, flags);
         dest.writeInt(this.sharedUserLabel);
         dest.writeTypedList(this.configPreferences);
@@ -1259,6 +1287,8 @@
         this.overlayCategory = in.readString();
         this.overlayPriority = in.readInt();
         this.overlayables = sForInternedStringValueMap.unparcel(in);
+        this.sdkLibName = sForInternedString.unparcel(in);
+        this.sdkLibVersionMajor = in.readInt();
         this.staticSharedLibName = sForInternedString.unparcel(in);
         this.staticSharedLibVersion = in.readLong();
         this.libraryNames = sForInternedStringList.unparcel(in);
@@ -1266,14 +1296,29 @@
         this.usesOptionalLibraries = sForInternedStringList.unparcel(in);
         this.usesNativeLibraries = sForInternedStringList.unparcel(in);
         this.usesOptionalNativeLibraries = sForInternedStringList.unparcel(in);
+
         this.usesStaticLibraries = sForInternedStringList.unparcel(in);
         this.usesStaticLibrariesVersions = in.createLongArray();
+        {
+            int digestsSize = in.readInt();
+            if (digestsSize >= 0) {
+                this.usesStaticLibrariesCertDigests = new String[digestsSize][];
+                for (int index = 0; index < digestsSize; index++) {
+                    this.usesStaticLibrariesCertDigests[index] = sForInternedStringArray.unparcel(
+                            in);
+                }
+            }
+        }
 
-        int digestsSize = in.readInt();
-        if (digestsSize >= 0) {
-            this.usesStaticLibrariesCertDigests = new String[digestsSize][];
-            for (int index = 0; index < digestsSize; index++) {
-                this.usesStaticLibrariesCertDigests[index] = sForInternedStringArray.unparcel(in);
+        this.usesSdkLibraries = sForInternedStringList.unparcel(in);
+        this.usesSdkLibrariesVersionsMajor = in.createLongArray();
+        {
+            int digestsSize = in.readInt();
+            if (digestsSize >= 0) {
+                this.usesSdkLibrariesCertDigests = new String[digestsSize][];
+                for (int index = 0; index < digestsSize; index++) {
+                    this.usesSdkLibrariesCertDigests[index] = sForInternedStringArray.unparcel(in);
+                }
             }
         }
 
@@ -1479,6 +1524,17 @@
 
     @Nullable
     @Override
+    public String getSdkLibName() {
+        return sdkLibName;
+    }
+
+    @Override
+    public int getSdkLibVersionMajor() {
+        return sdkLibVersionMajor;
+    }
+
+    @Nullable
+    @Override
     public String getStaticSharedLibName() {
         return staticSharedLibName;
     }
@@ -1536,6 +1592,18 @@
         return usesStaticLibrariesCertDigests;
     }
 
+    @NonNull
+    @Override
+    public List<String> getUsesSdkLibraries() { return usesSdkLibraries; }
+
+    @Nullable
+    @Override
+    public long[] getUsesSdkLibrariesVersionsMajor() { return usesSdkLibrariesVersionsMajor; }
+
+    @Nullable
+    @Override
+    public String[][] getUsesSdkLibrariesCertDigests() { return usesSdkLibrariesCertDigests; }
+
     @Nullable
     @Override
     public String getSharedUserId() {
@@ -2083,6 +2151,11 @@
     }
 
     @Override
+    public boolean isSdkLibrary() {
+        return getBoolean(Booleans.SDK_LIBRARY);
+    }
+
+    @Override
     public boolean isOverlay() {
         return getBoolean(Booleans.OVERLAY);
     }
@@ -2558,6 +2631,23 @@
     }
 
     @Override
+    public ParsingPackageImpl setSdkLibName(String sdkLibName) {
+        this.sdkLibName = TextUtils.safeIntern(sdkLibName);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setSdkLibVersionMajor(int sdkLibVersionMajor) {
+        this.sdkLibVersionMajor = sdkLibVersionMajor;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setSdkLibrary(boolean value) {
+        return setBoolean(Booleans.SDK_LIBRARY, value);
+    }
+
+    @Override
     public ParsingPackageImpl setStaticSharedLibrary(boolean value) {
         return setBoolean(Booleans.STATIC_SHARED_LIBRARY, value);
     }
diff --git a/core/java/android/content/pm/parsing/ParsingPackageRead.java b/core/java/android/content/pm/parsing/ParsingPackageRead.java
index 2933f95..49b3b08 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageRead.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageRead.java
@@ -196,6 +196,17 @@
     int[] getSplitFlags();
 
     /**
+     * @see R.styleable#AndroidManifestSdkLibrary_name
+     */
+    @Nullable
+    String getSdkLibName();
+
+    /**
+     * @see R.styleable#AndroidManifestSdkLibrary_versionMajor
+     */
+    int getSdkLibVersionMajor();
+
+    /**
      * @see R.styleable#AndroidManifestStaticLibrary_name
      */
     @Nullable
@@ -267,6 +278,26 @@
     @Nullable
     long[] getUsesStaticLibrariesVersions();
 
+    /**
+     * TODO(b/135203078): Move SDK library stuff to an inner data class
+     *
+     * @see R.styleable#AndroidManifestUsesSdkLibrary
+     */
+    @NonNull
+    List<String> getUsesSdkLibraries();
+
+    /**
+     * @see R.styleable#AndroidManifestUsesSdkLibrary_certDigest
+     */
+    @Nullable
+    String[][] getUsesSdkLibrariesCertDigests();
+
+    /**
+     * @see R.styleable#AndroidManifestUsesSdkLibrary_versionMajor
+     */
+    @Nullable
+    long[] getUsesSdkLibrariesVersionsMajor();
+
     boolean hasPreserveLegacyExternalStorage();
 
     /**
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index d2ac8739..3e537c8 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -117,6 +117,7 @@
 
 import libcore.io.IoUtils;
 import libcore.util.EmptyArray;
+import libcore.util.HexEncoding;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -848,6 +849,8 @@
                     pkg.addProperty(propertyResult.getResult());
                 }
                 return propertyResult;
+            case "uses-sdk-library":
+                return parseUsesSdkLibrary(input, pkg, res, parser);
             case "uses-static-library":
                 return parseUsesStaticLibrary(input, pkg, res, parser);
             case "uses-library":
@@ -2212,7 +2215,8 @@
             }
         }
 
-        if (TextUtils.isEmpty(pkg.getStaticSharedLibName())) {
+        if (TextUtils.isEmpty(pkg.getStaticSharedLibName()) && TextUtils.isEmpty(
+                pkg.getSdkLibName())) {
             // Add a hidden app detail activity to normal apps which forwards user to App Details
             // page.
             ParseResult<ParsedActivity> a = generateAppDetailsHiddenActivity(input, pkg);
@@ -2351,10 +2355,14 @@
                     pkg.addProperty(propertyResult.getResult());
                 }
                 return propertyResult;
+            case "sdk-library":
+                return parseSdkLibrary(pkg, res, parser, input);
             case "static-library":
                 return parseStaticLibrary(pkg, res, parser, input);
             case "library":
                 return parseLibrary(pkg, res, parser, input);
+            case "uses-sdk-library":
+                return parseUsesSdkLibrary(input, pkg, res, parser);
             case "uses-static-library":
                 return parseUsesStaticLibrary(input, pkg, res, parser);
             case "uses-library":
@@ -2375,6 +2383,41 @@
     }
 
     @NonNull
+    private static ParseResult<ParsingPackage> parseSdkLibrary(
+            ParsingPackage pkg, Resources res,
+            XmlResourceParser parser, ParseInput input) {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestSdkLibrary);
+        try {
+            // Note: don't allow this value to be a reference to a resource that may change.
+            String lname = sa.getNonResourceString(
+                    R.styleable.AndroidManifestSdkLibrary_name);
+            final int versionMajor = sa.getInt(
+                    R.styleable.AndroidManifestSdkLibrary_versionMajor,
+                    -1);
+
+            // Fail if malformed.
+            if (lname == null || versionMajor < 0) {
+                return input.error("Bad sdk-library declaration name: " + lname
+                        + " version: " + versionMajor);
+            } else if (pkg.getSharedUserId() != null) {
+                return input.error(
+                        PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID,
+                        "sharedUserId not allowed in SDK library"
+                );
+            } else if (pkg.getSdkLibName() != null) {
+                return input.error("Multiple SDKs for package "
+                        + pkg.getPackageName());
+            }
+
+            return input.success(pkg.setSdkLibName(lname.intern())
+                    .setSdkLibVersionMajor(versionMajor)
+                    .setSdkLibrary(true));
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    @NonNull
     private static ParseResult<ParsingPackage> parseStaticLibrary(
             ParsingPackage pkg, Resources res,
             XmlResourceParser parser, ParseInput input) {
@@ -2436,6 +2479,68 @@
     }
 
     @NonNull
+    private static ParseResult<ParsingPackage> parseUsesSdkLibrary(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser)
+            throws XmlPullParserException, IOException {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesSdkLibrary);
+        try {
+            // Note: don't allow this value to be a reference to a resource that may change.
+            String lname = sa.getNonResourceString(
+                    R.styleable.AndroidManifestUsesSdkLibrary_name);
+            final int versionMajor = sa.getInt(
+                    R.styleable.AndroidManifestUsesSdkLibrary_versionMajor, -1);
+            String certSha256Digest = sa.getNonResourceString(R.styleable
+                    .AndroidManifestUsesSdkLibrary_certDigest);
+
+            // Since an APK providing a static shared lib can only provide the lib - fail if
+            // malformed
+            if (lname == null || versionMajor < 0 || certSha256Digest == null) {
+                return input.error("Bad uses-sdk-library declaration name: " + lname
+                        + " version: " + versionMajor + " certDigest" + certSha256Digest);
+            }
+
+            // Can depend only on one version of the same library
+            List<String> usesSdkLibraries = pkg.getUsesSdkLibraries();
+            if (usesSdkLibraries.contains(lname)) {
+                return input.error(
+                        "Depending on multiple versions of SDK library " + lname);
+            }
+
+            lname = lname.intern();
+            // We allow ":" delimiters in the SHA declaration as this is the format
+            // emitted by the certtool making it easy for developers to copy/paste.
+            certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
+
+            if ("".equals(certSha256Digest)) {
+                // Test-only uses-sdk-library empty certificate digest override.
+                certSha256Digest = SystemProperties.get(
+                        "debug.pm.uses_sdk_library_default_cert_digest", "");
+                // Validate the overridden digest.
+                try {
+                    HexEncoding.decode(certSha256Digest, false);
+                } catch (IllegalArgumentException e) {
+                    certSha256Digest = "";
+                }
+            }
+
+            ParseResult<String[]> certResult = parseAdditionalCertificates(input, res, parser);
+            if (certResult.isError()) {
+                return input.error(certResult);
+            }
+            String[] additionalCertSha256Digests = certResult.getResult();
+
+            final String[] certSha256Digests = new String[additionalCertSha256Digests.length + 1];
+            certSha256Digests[0] = certSha256Digest;
+            System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests,
+                    1, additionalCertSha256Digests.length);
+
+            return input.success(pkg.addUsesSdkLibrary(lname, versionMajor, certSha256Digests));
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    @NonNull
     private static ParseResult<ParsingPackage> parseUsesStaticLibrary(ParseInput input,
             ParsingPackage pkg, Resources res, XmlResourceParser parser)
             throws XmlPullParserException, IOException {
@@ -2483,9 +2588,7 @@
             System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests,
                     1, additionalCertSha256Digests.length);
 
-            return input.success(pkg.addUsesStaticLibrary(lname)
-                    .addUsesStaticLibraryVersion(version)
-                    .addUsesStaticLibraryCertDigests(certSha256Digests));
+            return input.success(pkg.addUsesStaticLibrary(lname, version, certSha256Digests));
         } finally {
             sa.recycle();
         }
diff --git a/core/java/android/content/pm/parsing/PkgWithoutStateAppInfo.java b/core/java/android/content/pm/parsing/PkgWithoutStateAppInfo.java
index fcad10c..625b9d1 100644
--- a/core/java/android/content/pm/parsing/PkgWithoutStateAppInfo.java
+++ b/core/java/android/content/pm/parsing/PkgWithoutStateAppInfo.java
@@ -21,8 +21,6 @@
 import android.content.pm.ApplicationInfo;
 import android.util.SparseArray;
 
-import com.android.internal.R;
-
 /**
  * Container for fields that are eventually exposed through {@link ApplicationInfo}.
  * <p>
@@ -576,6 +574,11 @@
     boolean isStaticSharedLibrary();
 
     /**
+     * True means that this package/app contains an SDK library.
+     */
+    boolean isSdkLibrary();
+
+    /**
      * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >= {@link
      * android.os.Build.VERSION_CODES#GINGERBREAD}.
      *
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 94717b1..fe58114 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -2303,6 +2303,36 @@
         <attr name="authorities" />
     </declare-styleable>
 
+    <!-- The <code>sdk-library</code> tag declares that this apk is providing itself
+    as an SDK library for other applications to use. Any app can declare an SDK library and there
+    can be only one SDK library per package. These SDK libraries are updatable, multiple major
+    versions can be installed at the same time, and an app depends on a specific version.
+    Other apks can link to it with the {@link #AndroidManifestUsesSdkLibrary uses-sdk-library} tag.
+
+    <p>This appears as a child tag of the {@link #AndroidManifestApplication application} tag. -->
+    <declare-styleable name="AndroidManifestSdkLibrary" parent="AndroidManifestApplication">
+        <!-- Required public name of the SDK library, which other components and packages will use
+        when referring to this SDK library. This is a string using Java-style scoping to ensure
+        it is unique.
+        Both name and version should typically form the apk's package name: name_versionMajor. -->
+        <attr name="name" />
+        <!-- Required major version of the SDK library. -->
+        <attr name="versionMajor" format="integer" />
+    </declare-styleable>
+
+
+    <!-- The <code>uses-sdk-library</code> specifies a shared <strong>SDK</strong> library that this
+    package requires to be present on the device.
+
+    <p>This appears as a child tag of the {@link #AndroidManifestApplication application} tag. -->
+    <declare-styleable name="AndroidManifestUsesSdkLibrary" parent="AndroidManifestApplication">
+        <!-- Required name of the SDK library you use. -->
+        <attr name="name" />
+        <!-- Specify which major version of the SDK library you use. -->
+        <attr name="versionMajor" format="integer" />
+        <!-- The SHA-256 digest of the SDK library signing certificate. -->
+        <attr name="certDigest" format="string" />
+    </declare-styleable>
 
     <!-- The <code>static-library</code> tag declares that this apk is providing itself
        as a static shared library for other applications to use. Any app can declare such
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 2d61773..9b21790 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -2232,11 +2232,12 @@
         return false;
     }
 
-    public final boolean filterSharedLibPackage(@Nullable PackageStateInternal ps, int uid,
+    private boolean filterStaticSharedLibPackage(@Nullable PackageStateInternal ps, int uid,
             int userId, @PackageManager.ComponentInfoFlags long flags) {
-        // Callers can access only the libs they depend on, otherwise they need to explicitly
-        // ask for the shared libraries given the caller is allowed to access all static libs.
-        if ((flags & PackageManager.MATCH_STATIC_SHARED_LIBRARIES) != 0) {
+        // Callers can access only the static shared libs they depend on, otherwise they need to
+        // explicitly ask for the static shared libraries given the caller is allowed to access
+        // all static libs.
+        if ((flags & PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES) != 0) {
             // System/shell/root get to see all static libs
             final int appId = UserHandle.getAppId(uid);
             if (appId == Process.SYSTEM_UID || appId == Process.SHELL_UID
@@ -2287,6 +2288,69 @@
         return true;
     }
 
+    private boolean filterSdkLibPackage(@Nullable PackageStateInternal ps, int uid,
+            int userId, @PackageManager.ComponentInfoFlags long flags) {
+        // Callers can access only the SDK libs they depend on, otherwise they need to
+        // explicitly ask for the SDKs given the caller is allowed to access
+        // all shared libs.
+        if ((flags & PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES) != 0) {
+            // System/shell/root get to see all SDK libs.
+            final int appId = UserHandle.getAppId(uid);
+            if (appId == Process.SYSTEM_UID || appId == Process.SHELL_UID
+                    || appId == Process.ROOT_UID) {
+                return false;
+            }
+            // Installer gets to see all SDK libs.
+            if (PackageManager.PERMISSION_GRANTED
+                    == checkUidPermission(Manifest.permission.INSTALL_PACKAGES, uid)) {
+                return false;
+            }
+        }
+
+        // No package means no static lib as it is always on internal storage
+        if (ps == null || ps.getPkg() == null || !ps.getPkg().isSdkLibrary()) {
+            return false;
+        }
+
+        final SharedLibraryInfo libraryInfo = getSharedLibraryInfo(
+                ps.getPkg().getSdkLibName(), ps.getPkg().getSdkLibVersionMajor());
+        if (libraryInfo == null) {
+            return false;
+        }
+
+        final int resolvedUid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
+        final String[] uidPackageNames = getPackagesForUid(resolvedUid);
+        if (uidPackageNames == null) {
+            return true;
+        }
+
+        for (String uidPackageName : uidPackageNames) {
+            if (ps.getPackageName().equals(uidPackageName)) {
+                return false;
+            }
+            PackageStateInternal uidPs = mSettings.getPackage(uidPackageName);
+            if (uidPs != null) {
+                final int index = ArrayUtils.indexOf(uidPs.getUsesSdkLibraries(),
+                        libraryInfo.getName());
+                if (index < 0) {
+                    continue;
+                }
+                if (uidPs.getPkg().getUsesSdkLibrariesVersionsMajor()[index]
+                        == libraryInfo.getLongVersion()) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public final boolean filterSharedLibPackage(@Nullable PackageStateInternal ps, int uid,
+            int userId, @PackageManager.ComponentInfoFlags long flags) {
+        return filterStaticSharedLibPackage(ps, uid, userId, flags) || filterSdkLibPackage(ps, uid,
+                userId, flags);
+    }
+
     private boolean hasCrossUserPermission(
             int callingUid, int callingUserId, int userId, boolean requireFullPermission,
             boolean requirePermissionWhenSameUser) {
@@ -3719,7 +3783,7 @@
 
         flags = updateFlagsForPackage(flags, userId);
 
-        final boolean canSeeStaticLibraries =
+        final boolean canSeeStaticAndSdkLibraries =
                 mContext.checkCallingOrSelfPermission(INSTALL_PACKAGES)
                         == PERMISSION_GRANTED
                         || mContext.checkCallingOrSelfPermission(DELETE_PACKAGES)
@@ -3744,7 +3808,7 @@
             final int versionCount = versionedLib.size();
             for (int j = 0; j < versionCount; j++) {
                 SharedLibraryInfo libInfo = versionedLib.valueAt(j);
-                if (!canSeeStaticLibraries && libInfo.isStatic()) {
+                if (!canSeeStaticAndSdkLibraries && (libInfo.isStatic() || libInfo.isSdk())) {
                     break;
                 }
                 final long identity = Binder.clearCallingIdentity();
@@ -3753,7 +3817,7 @@
                     PackageInfo packageInfo = getPackageInfoInternal(
                             declaringPackage.getPackageName(),
                             declaringPackage.getLongVersionCode(),
-                            flags | PackageManager.MATCH_STATIC_SHARED_LIBRARIES,
+                            flags | PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES,
                             Binder.getCallingUid(), userId);
                     if (packageInfo == null) {
                         continue;
@@ -3853,12 +3917,17 @@
             }
 
             final String libName = libInfo.getName();
-            if (libInfo.isStatic()) {
-                final int libIdx = ArrayUtils.indexOf(ps.getUsesStaticLibraries(), libName);
+            if (libInfo.isStatic() || libInfo.isSdk()) {
+                final String[] libs =
+                        libInfo.isStatic() ? ps.getUsesStaticLibraries() : ps.getUsesSdkLibraries();
+                final long[] libsVersions = libInfo.isStatic() ? ps.getUsesStaticLibrariesVersions()
+                        : ps.getUsesSdkLibrariesVersionsMajor();
+
+                final int libIdx = ArrayUtils.indexOf(libs, libName);
                 if (libIdx < 0) {
                     continue;
                 }
-                if (ps.getUsesStaticLibrariesVersions()[libIdx] != libInfo.getLongVersion()) {
+                if (libsVersions[libIdx] != libInfo.getLongVersion()) {
                     continue;
                 }
                 if (shouldFilterApplication(ps, callingUid, userId)) {
@@ -3939,7 +4008,7 @@
                     PackageInfo packageInfo = getPackageInfoInternal(
                             declaringPackage.getPackageName(),
                             declaringPackage.getLongVersionCode(),
-                            flags | PackageManager.MATCH_STATIC_SHARED_LIBRARIES,
+                            flags | PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES,
                             Binder.getCallingUid(), userId);
                     if (packageInfo == null) {
                         continue;
@@ -4034,7 +4103,7 @@
                         getPackageStateInternal(libraryInfo.getPackageName());
                 if (ps != null && !filterSharedLibPackage(ps, Binder.getCallingUid(),
                         UserHandle.getUserId(Binder.getCallingUid()),
-                        PackageManager.MATCH_STATIC_SHARED_LIBRARIES)) {
+                        PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES)) {
                     if (libs == null) {
                         libs = new ArraySet<>();
                     }
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index 43d60cc..641f24f 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -164,9 +164,16 @@
 
             allUsers = mUserManagerInternal.getUserIds();
 
-            if (pkg != null && pkg.getStaticSharedLibName() != null) {
-                SharedLibraryInfo libraryInfo = mPm.getSharedLibraryInfo(
-                        pkg.getStaticSharedLibName(), pkg.getStaticSharedLibVersion());
+            if (pkg != null) {
+                SharedLibraryInfo libraryInfo = null;
+                if (pkg.getStaticSharedLibName() != null) {
+                    libraryInfo = mPm.getSharedLibraryInfo(pkg.getStaticSharedLibName(),
+                            pkg.getStaticSharedLibVersion());
+                } else if (pkg.getSdkLibName() != null) {
+                    libraryInfo = mPm.getSharedLibraryInfo(pkg.getSdkLibName(),
+                            pkg.getSdkLibVersionMajor());
+                }
+
                 if (libraryInfo != null) {
                     for (int currUserId : allUsers) {
                         if (removeUser != UserHandle.USER_ALL && removeUser != currUserId) {
@@ -828,9 +835,10 @@
                 continue;
             }
             final String packageName = ps.getPkg().getPackageName();
-            // Skip over if system app or static shared library
+            // Skip over if system app, static shared library or and SDK library.
             if ((ps.getFlags() & ApplicationInfo.FLAG_SYSTEM) != 0
-                    || !TextUtils.isEmpty(ps.getPkg().getStaticSharedLibName())) {
+                    || !TextUtils.isEmpty(ps.getPkg().getStaticSharedLibName())
+                    || !TextUtils.isEmpty(ps.getPkg().getSdkLibName())) {
                 continue;
             }
             if (DEBUG_CLEAN_APKS) {
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 5ca0618..d2087ee 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -254,12 +254,11 @@
             final List<SharedLibraryInfo> allowedSharedLibInfos =
                     SharedLibraryHelper.getAllowedSharedLibInfos(scanResult,
                             request.mSharedLibrarySource);
-            final SharedLibraryInfo staticLib = scanResult.mStaticSharedLibraryInfo;
             if (allowedSharedLibInfos != null) {
                 for (SharedLibraryInfo info : allowedSharedLibInfos) {
                     if (!SharedLibraryHelper.addSharedLibraryToPackageVersionMap(
                             incomingSharedLibraries, info)) {
-                        throw new ReconcileFailure("Static Shared Library " + staticLib.getName()
+                        throw new ReconcileFailure("Shared Library " + info.getName()
                                 + " is being installed twice in this set!");
                     }
                 }
@@ -1188,7 +1187,8 @@
                     createdAppId.put(packageName, optimisticallyRegisterAppId(result));
                     versionInfos.put(result.mPkgSetting.getPkg().getPackageName(),
                             mPm.getSettingsVersionForPackage(result.mPkgSetting.getPkg()));
-                    if (result.mStaticSharedLibraryInfo != null) {
+                    if (result.mStaticSharedLibraryInfo != null
+                            || result.mSdkSharedLibraryInfo != null) {
                         final PackageSetting sharedLibLatestVersionSetting =
                                 mPm.getSharedLibLatestVersionSetting(result);
                         if (sharedLibLatestVersionSetting != null) {
@@ -2695,7 +2695,7 @@
                 }
             }
 
-            if (dataOwnerPkg != null) {
+            if (dataOwnerPkg != null && !dataOwnerPkg.isSdkLibrary()) {
                 if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags,
                         dataOwnerPkg.isDebuggable())) {
                     try {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 4767d3a..26a5bbb 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -1328,7 +1328,7 @@
         PackageInfo packageInfo = null;
         try {
             packageInfo = AppGlobals.getPackageManager().getPackageInfo(
-                    basePackageName, PackageManager.MATCH_STATIC_SHARED_LIBRARIES, userId);
+                    basePackageName, PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES, userId);
         } catch (RemoteException ignored) {
         }
         if (packageInfo == null || packageInfo.applicationInfo == null) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index f299e1e..28204ea 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -2903,7 +2903,7 @@
 
         final PackageInfo pkgInfo = mPm.getPackageInfo(
                 params.appPackageName, PackageManager.GET_SIGNATURES
-                        | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
+                        | PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES /*flags*/, userId);
 
         // Partial installs must be consistent with existing install
         if (params.mode == SessionParams.MODE_INHERIT_EXISTING
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9f5adcb..fe5bce13 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4034,7 +4034,13 @@
         // - Package manager is in a state where package isn't scanned yet. This will
         //   get called again after scanning to fix the dependencies.
         if (AndroidPackageUtils.isLibrary(pkg)) {
-            if (pkg.getStaticSharedLibName() != null) {
+            if (pkg.getSdkLibName() != null) {
+                SharedLibraryInfo definedLibrary = getSharedLibraryInfo(
+                        pkg.getSdkLibName(), pkg.getSdkLibVersionMajor());
+                if (definedLibrary != null) {
+                    action.accept(definedLibrary, libInfo);
+                }
+            } else if (pkg.getStaticSharedLibName() != null) {
                 SharedLibraryInfo definedLibrary = getSharedLibraryInfo(
                         pkg.getStaticSharedLibName(), pkg.getStaticSharedLibVersion());
                 if (definedLibrary != null) {
@@ -4186,7 +4192,9 @@
                         && !hasString(pkg.getUsesLibraries(), changingPkg.getLibraryNames())
                         && !hasString(pkg.getUsesOptionalLibraries(), changingPkg.getLibraryNames())
                         && !ArrayUtils.contains(pkg.getUsesStaticLibraries(),
-                        changingPkg.getStaticSharedLibName())) {
+                        changingPkg.getStaticSharedLibName())
+                        && !ArrayUtils.contains(pkg.getUsesSdkLibraries(),
+                        changingPkg.getSdkLibName())) {
                     continue;
                 }
                 if (resultList == null) {
@@ -4477,15 +4485,24 @@
                     Slog.w(TAG, "Cannot hide package: android");
                     return false;
                 }
-                // Cannot hide static shared libs as they are considered
-                // a part of the using app (emulating static linking). Also
-                // static libs are installed always on internal storage.
                 AndroidPackage pkg = mPackages.get(packageName);
-                if (pkg != null && pkg.getStaticSharedLibName() != null) {
-                    Slog.w(TAG, "Cannot hide package: " + packageName
-                            + " providing static shared library: "
-                            + pkg.getStaticSharedLibName());
-                    return false;
+                if (pkg != null) {
+                    // Cannot hide SDK libs as they are controlled by SDK manager.
+                    if (pkg.getSdkLibName() != null) {
+                        Slog.w(TAG, "Cannot hide package: " + packageName
+                                + " providing SDK library: "
+                                + pkg.getSdkLibName());
+                        return false;
+                    }
+                    // Cannot hide static shared libs as they are considered
+                    // a part of the using app (emulating static linking). Also
+                    // static libs are installed always on internal storage.
+                    if (pkg.getStaticSharedLibName() != null) {
+                        Slog.w(TAG, "Cannot hide package: " + packageName
+                                + " providing static shared library: "
+                                + pkg.getStaticSharedLibName());
+                        return false;
+                    }
                 }
                 // Only allow protected packages to hide themselves.
                 if (hidden && !UserHandle.isSameApp(callingUid, pkgSetting.getAppId())
@@ -5154,15 +5171,24 @@
                         continue;
                     }
 
-                    // Cannot suspend static shared libs as they are considered
-                    // a part of the using app (emulating static linking). Also
-                    // static libs are installed always on internal storage.
                     AndroidPackage pkg = mPackages.get(packageName);
-                    if (pkg != null && pkg.isStaticSharedLibrary()) {
-                        Slog.w(TAG, "Cannot suspend package: " + packageName
-                                + " providing static shared library: "
-                                + pkg.getStaticSharedLibName());
-                        continue;
+                    if (pkg != null) {
+                        // Cannot suspend SDK libs as they are controlled by SDK manager.
+                        if (pkg.isSdkLibrary()) {
+                            Slog.w(TAG, "Cannot suspend package: " + packageName
+                                    + " providing SDK library: "
+                                    + pkg.getSdkLibName());
+                            continue;
+                        }
+                        // Cannot suspend static shared libs as they are considered
+                        // a part of the using app (emulating static linking). Also
+                        // static libs are installed always on internal storage.
+                        if (pkg.isStaticSharedLibrary()) {
+                            Slog.w(TAG, "Cannot suspend package: " + packageName
+                                    + " providing static shared library: "
+                                    + pkg.getStaticSharedLibName());
+                            continue;
+                        }
                     }
                 }
                 if (PLATFORM_PACKAGE_NAME.equals(packageName)) {
@@ -5612,14 +5638,22 @@
                 android.Manifest.permission.DELETE_PACKAGES, null);
         // TODO (b/157774108): This should fail on non-existent packages.
         synchronized (mLock) {
-            // Cannot block uninstall of static shared libs as they are
-            // considered a part of the using app (emulating static linking).
-            // Also static libs are installed always on internal storage.
             AndroidPackage pkg = mPackages.get(packageName);
-            if (pkg != null && pkg.getStaticSharedLibName() != null) {
-                Slog.w(TAG, "Cannot block uninstall of package: " + packageName
-                        + " providing static shared library: " + pkg.getStaticSharedLibName());
-                return false;
+            if (pkg != null) {
+                // Cannot block uninstall SDK libs as they are controlled by SDK manager.
+                if (pkg.getSdkLibName() != null) {
+                    Slog.w(TAG, "Cannot block uninstall of package: " + packageName
+                            + " providing SDK library: " + pkg.getSdkLibName());
+                    return false;
+                }
+                // Cannot block uninstall of static shared libs as they are
+                // considered a part of the using app (emulating static linking).
+                // Also static libs are installed always on internal storage.
+                if (pkg.getStaticSharedLibName() != null) {
+                    Slog.w(TAG, "Cannot block uninstall of package: " + packageName
+                            + " providing static shared library: " + pkg.getStaticSharedLibName());
+                    return false;
+                }
             }
             mSettings.setBlockUninstallLPw(userId, packageName, blockUninstall);
             mSettings.writePackageRestrictionsLPr(userId);
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index fb70470..0564e85 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -49,6 +49,7 @@
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
 import android.content.pm.ResolveInfo;
+import android.content.pm.SharedLibraryInfo;
 import android.content.pm.SuspendDialogInfo;
 import android.content.pm.UserInfo;
 import android.content.pm.VersionedPackage;
@@ -667,6 +668,8 @@
                 return runListPermissions();
             case "staged-sessions":
                 return runListStagedSessions();
+            case "sdks":
+                return runListSdks();
             case "users":
                 ServiceManager.getService("user").shellCommand(
                         getInFileDescriptor(), getOutFileDescriptor(), getErrFileDescriptor(),
@@ -792,6 +795,15 @@
     }
 
     private int runListPackages(boolean showSourceDir) throws RemoteException {
+        return runListPackages(showSourceDir, false);
+    }
+
+    private int runListSdks() throws RemoteException {
+        return runListPackages(false, true);
+    }
+
+    private int runListPackages(boolean showSourceDir, boolean showSdks) throws RemoteException {
+        final String prefix = showSdks ? "sdk:" : "package:";
         final PrintWriter pw = getOutPrintWriter();
         int getFlags = 0;
         boolean listDisabled = false, listEnabled = false;
@@ -866,6 +878,9 @@
         if (userId == UserHandle.USER_ALL) {
             getFlags |= PackageManager.MATCH_KNOWN_PACKAGES;
         }
+        if (showSdks) {
+            getFlags |= PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES;
+        }
         final int translatedUserId =
                 translateUserId(userId, UserHandle.USER_SYSTEM, "runListPackages");
         @SuppressWarnings("unchecked")
@@ -885,37 +900,61 @@
             }
 
             final boolean isSystem = !isApex &&
-                    (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
+                    (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
             final boolean isEnabled = !isApex && info.applicationInfo.enabled;
-            if ((!listDisabled || !isEnabled) &&
-                    (!listEnabled || isEnabled) &&
-                    (!listSystem || isSystem) &&
-                    (!listThirdParty || !isSystem) &&
-                    (!listApexOnly || isApex)) {
-                pw.print("package:");
-                if (showSourceDir) {
-                    pw.print(info.applicationInfo.sourceDir);
-                    pw.print("=");
+            if ((listDisabled && isEnabled) ||
+                    (listEnabled && !isEnabled) ||
+                    (listSystem && !isSystem) ||
+                    (listThirdParty && isSystem) ||
+                    (listApexOnly && !isApex)) {
+                continue;
+            }
+
+            String name = null;
+            if (showSdks) {
+                final ParceledListSlice<SharedLibraryInfo> libsSlice =
+                        mInterface.getDeclaredSharedLibraries(info.packageName, getFlags, userId);
+                if (libsSlice == null) {
+                    continue;
                 }
-                pw.print(info.packageName);
-                if (showVersionCode) {
-                    pw.print(" versionCode:");
-                    if (info.applicationInfo != null) {
-                        pw.print(info.applicationInfo.longVersionCode);
-                    } else {
-                        pw.print(info.getLongVersionCode());
+                final List<SharedLibraryInfo> libs = libsSlice.getList();
+                for (int l = 0, lsize = libs.size(); l < lsize; ++l) {
+                    SharedLibraryInfo lib = libs.get(l);
+                    if (lib.getType() == SharedLibraryInfo.TYPE_SDK) {
+                        name = lib.getName() + ":" + lib.getLongVersion();
+                        break;
                     }
                 }
-                if (listInstaller) {
-                    pw.print("  installer=");
-                    pw.print(mInterface.getInstallerPackageName(info.packageName));
+                if (name == null) {
+                    continue;
                 }
-                if (showUid && !isApex) {
-                    pw.print(" uid:");
-                    pw.print(info.applicationInfo.uid);
-                }
-                pw.println();
+            } else {
+                name = info.packageName;
             }
+
+            pw.print(prefix);
+            if (showSourceDir) {
+                pw.print(info.applicationInfo.sourceDir);
+                pw.print("=");
+            }
+            pw.print(name);
+            if (showVersionCode) {
+                pw.print(" versionCode:");
+                if (info.applicationInfo != null) {
+                    pw.print(info.applicationInfo.longVersionCode);
+                } else {
+                    pw.print(info.getLongVersionCode());
+                }
+            }
+            if (listInstaller) {
+                pw.print("  installer=");
+                pw.print(mInterface.getInstallerPackageName(info.packageName));
+            }
+            if (showUid && !isApex) {
+                pw.print(" uid:");
+                pw.print(info.applicationInfo.uid);
+            }
+            pw.println();
         }
         return 0;
     }
@@ -2060,7 +2099,7 @@
         } else {
             if ((flags & PackageManager.DELETE_ALL_USERS) == 0) {
                 final PackageInfo info = mInterface.getPackageInfo(packageName,
-                        PackageManager.MATCH_STATIC_SHARED_LIBRARIES, translatedUserId);
+                        PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES, translatedUserId);
                 if (info == null) {
                     pw.println("Failure [not installed for " + translatedUserId + "]");
                     return 1;
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index dc514c1..923a133 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -32,12 +32,6 @@
 import android.content.pm.SuspendDialogInfo;
 import android.content.pm.UserInfo;
 import android.content.pm.overlay.OverlayPaths;
-
-import com.android.server.pm.pkg.PackageStateInternal;
-import com.android.server.pm.pkg.PackageUserState;
-import com.android.server.pm.pkg.PackageUserStateImpl;
-import com.android.server.pm.pkg.PackageUserStateInternal;
-import com.android.server.pm.pkg.SuspendParams;
 import android.os.PersistableBundle;
 import android.service.pm.PackageProto;
 import android.util.ArrayMap;
@@ -53,7 +47,12 @@
 import com.android.server.pm.permission.LegacyPermissionState;
 import com.android.server.pm.pkg.AndroidPackageApi;
 import com.android.server.pm.pkg.PackageState;
+import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.PackageStateUnserialized;
+import com.android.server.pm.pkg.PackageUserState;
+import com.android.server.pm.pkg.PackageUserStateImpl;
+import com.android.server.pm.pkg.PackageUserStateInternal;
+import com.android.server.pm.pkg.SuspendParams;
 import com.android.server.utils.SnapshotCache;
 
 import libcore.util.EmptyArray;
@@ -94,6 +93,12 @@
     private Set<String> mOldCodePaths;
 
     @Nullable
+    private String[] usesSdkLibraries;
+
+    @Nullable
+    private long[] usesSdkLibrariesVersionsMajor;
+
+    @Nullable
     private String[] usesStaticLibraries;
 
     @Nullable
@@ -208,12 +213,16 @@
             String legacyNativeLibraryPath, String primaryCpuAbi,
             String secondaryCpuAbi, String cpuAbiOverride,
             long longVersionCode, int pkgFlags, int pkgPrivateFlags,
-            int sharedUserId, String[] usesStaticLibraries,
-            long[] usesStaticLibrariesVersions, Map<String, Set<String>> mimeGroups,
+            int sharedUserId,
+            String[] usesSdkLibraries, long[] usesSdkLibrariesVersionsMajor,
+            String[] usesStaticLibraries, long[] usesStaticLibrariesVersions,
+            Map<String, Set<String>> mimeGroups,
             @NonNull UUID domainSetId) {
         super(pkgFlags, pkgPrivateFlags);
         this.mName = name;
         this.mRealName = realName;
+        this.usesSdkLibraries = usesSdkLibraries;
+        this.usesSdkLibrariesVersionsMajor = usesSdkLibrariesVersionsMajor;
         this.usesStaticLibraries = usesStaticLibraries;
         this.usesStaticLibrariesVersions = usesStaticLibrariesVersions;
         this.mPath = path;
@@ -617,6 +626,13 @@
         forceQueryableOverride = other.forceQueryableOverride;
         mDomainSetId = other.mDomainSetId;
 
+        usesSdkLibraries = other.usesSdkLibraries != null
+                ? Arrays.copyOf(other.usesSdkLibraries,
+                other.usesSdkLibraries.length) : null;
+        usesSdkLibrariesVersionsMajor = other.usesSdkLibrariesVersionsMajor != null
+                ? Arrays.copyOf(other.usesSdkLibrariesVersionsMajor,
+                other.usesSdkLibrariesVersionsMajor.length) : null;
+
         usesStaticLibraries = other.usesStaticLibraries != null
                 ? Arrays.copyOf(other.usesStaticLibraries,
                 other.usesStaticLibraries.length) : null;
@@ -1225,6 +1241,19 @@
 
     @NonNull
     @Override
+    public String[] getUsesSdkLibraries() {
+        return usesSdkLibraries == null ? EmptyArray.STRING : usesSdkLibraries;
+    }
+
+    @NonNull
+    @Override
+    public long[] getUsesSdkLibrariesVersionsMajor() {
+        return usesSdkLibrariesVersionsMajor == null ? EmptyArray.LONG
+                : usesSdkLibrariesVersionsMajor;
+    }
+
+    @NonNull
+    @Override
     public String[] getUsesStaticLibraries() {
         return usesStaticLibraries == null ? EmptyArray.STRING : usesStaticLibraries;
     }
@@ -1300,6 +1329,18 @@
         return this;
     }
 
+    public PackageSetting setUsesSdkLibraries(String[] usesSdkLibraries) {
+        this.usesSdkLibraries = usesSdkLibraries;
+        onChanged();
+        return this;
+    }
+
+    public PackageSetting setUsesSdkLibrariesVersionsMajor(long[] usesSdkLibrariesVersions) {
+        this.usesSdkLibrariesVersionsMajor = usesSdkLibrariesVersions;
+        onChanged();
+        return this;
+    }
+
     public PackageSetting setUsesStaticLibraries(String[] usesStaticLibraries) {
         this.usesStaticLibraries = usesStaticLibraries;
         onChanged();
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index 48b893b..749495c 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -189,7 +189,19 @@
 
         r = null;
 
-        // Any package can hold static shared libraries.
+        // Any package can hold SDK or static shared libraries.
+        if (pkg.getSdkLibName() != null) {
+            if (removeSharedLibraryLPw(pkg.getSdkLibName(), pkg.getSdkLibVersionMajor())) {
+                if (DEBUG_REMOVE && chatty) {
+                    if (r == null) {
+                        r = new StringBuilder(256);
+                    } else {
+                        r.append(' ');
+                    }
+                    r.append(pkg.getSdkLibName());
+                }
+            }
+        }
         if (pkg.getStaticSharedLibName() != null) {
             if (removeSharedLibraryLPw(pkg.getStaticSharedLibName(),
                     pkg.getStaticSharedLibVersion())) {
diff --git a/services/core/java/com/android/server/pm/ScanPackageHelper.java b/services/core/java/com/android/server/pm/ScanPackageHelper.java
index 9b08ef9..eafe0d98 100644
--- a/services/core/java/com/android/server/pm/ScanPackageHelper.java
+++ b/services/core/java/com/android/server/pm/ScanPackageHelper.java
@@ -294,6 +294,12 @@
             }
         }
 
+        String[] usesSdkLibraries = null;
+        if (!parsedPackage.getUsesSdkLibraries().isEmpty()) {
+            usesSdkLibraries = new String[parsedPackage.getUsesSdkLibraries().size()];
+            parsedPackage.getUsesSdkLibraries().toArray(usesSdkLibraries);
+        }
+
         String[] usesStaticLibraries = null;
         if (!parsedPackage.getUsesStaticLibraries().isEmpty()) {
             usesStaticLibraries = new String[parsedPackage.getUsesStaticLibraries().size()];
@@ -324,7 +330,8 @@
                     AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage),
                     parsedPackage.getLongVersionCode(), pkgFlags, pkgPrivateFlags, user,
                     true /*allowInstall*/, instantApp, virtualPreload,
-                    UserManagerService.getInstance(), usesStaticLibraries,
+                    UserManagerService.getInstance(), usesSdkLibraries,
+                    parsedPackage.getUsesSdkLibrariesVersionsMajor(), usesStaticLibraries,
                     parsedPackage.getUsesStaticLibrariesVersions(), parsedPackage.getMimeGroups(),
                     newDomainSetId);
         } else {
@@ -344,6 +351,7 @@
                     PackageInfoUtils.appInfoFlags(parsedPackage, pkgSetting),
                     PackageInfoUtils.appInfoPrivateFlags(parsedPackage, pkgSetting),
                     UserManagerService.getInstance(),
+                    usesSdkLibraries, parsedPackage.getUsesSdkLibrariesVersionsMajor(),
                     usesStaticLibraries, parsedPackage.getUsesStaticLibrariesVersions(),
                     parsedPackage.getMimeGroups(), newDomainSetId);
         }
@@ -552,6 +560,10 @@
             pkgSetting.setVolumeUuid(volumeUuid);
         }
 
+        SharedLibraryInfo sdkLibraryInfo = null;
+        if (!TextUtils.isEmpty(parsedPackage.getSdkLibName())) {
+            sdkLibraryInfo = AndroidPackageUtils.createSharedLibraryForSdk(parsedPackage);
+        }
         SharedLibraryInfo staticSharedLibraryInfo = null;
         if (!TextUtils.isEmpty(parsedPackage.getStaticSharedLibName())) {
             staticSharedLibraryInfo =
@@ -568,7 +580,7 @@
 
         return new ScanResult(request, true, pkgSetting, changedAbiCodePath,
                 !createNewPackage /* existingSettingCopied */,
-                previousAppId, staticSharedLibraryInfo,
+                previousAppId, sdkLibraryInfo, staticSharedLibraryInfo,
                 dynamicSharedLibraryInfos);
     }
 
diff --git a/services/core/java/com/android/server/pm/ScanResult.java b/services/core/java/com/android/server/pm/ScanResult.java
index eb44a82..f77be1f 100644
--- a/services/core/java/com/android/server/pm/ScanResult.java
+++ b/services/core/java/com/android/server/pm/ScanResult.java
@@ -51,6 +51,8 @@
     /** ABI code paths that have changed in the package scan */
     @Nullable public final List<String> mChangedAbiCodePath;
 
+    public final SharedLibraryInfo mSdkSharedLibraryInfo;
+
     public final SharedLibraryInfo mStaticSharedLibraryInfo;
 
     public final List<SharedLibraryInfo> mDynamicSharedLibraryInfos;
@@ -60,6 +62,7 @@
             @Nullable PackageSetting pkgSetting,
             @Nullable List<String> changedAbiCodePath, boolean existingSettingCopied,
             int previousAppId,
+            SharedLibraryInfo sdkSharedLibraryInfo,
             SharedLibraryInfo staticSharedLibraryInfo,
             List<SharedLibraryInfo> dynamicSharedLibraryInfos) {
         mRequest = request;
@@ -68,6 +71,7 @@
         mChangedAbiCodePath = changedAbiCodePath;
         mExistingSettingCopied = existingSettingCopied;
         mPreviousAppId = previousAppId;
+        mSdkSharedLibraryInfo = sdkSharedLibraryInfo;
         mStaticSharedLibraryInfo = staticSharedLibraryInfo;
         mDynamicSharedLibraryInfos = dynamicSharedLibraryInfos;
     }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 6a163b2..45994f6 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -276,6 +276,7 @@
     private static final String TAG_RUNTIME_PERMISSIONS = "runtime-permissions";
     private static final String TAG_PERMISSIONS = "perms";
     private static final String TAG_CHILD_PACKAGE = "child-package";
+    private static final String TAG_USES_SDK_LIB = "uses-sdk-lib";
     private static final String TAG_USES_STATIC_LIB = "uses-static-lib";
     private static final String TAG_BLOCK_UNINSTALL_PACKAGES = "block-uninstall-packages";
     private static final String TAG_BLOCK_UNINSTALL = "block-uninstall";
@@ -826,6 +827,7 @@
                 p.getLegacyNativeLibraryPath(), p.getPrimaryCpuAbi(),
                 p.getSecondaryCpuAbi(), p.getCpuAbiOverride(),
                 p.getAppId(), p.getVersionCode(), p.getFlags(), p.getPrivateFlags(),
+                p.getUsesSdkLibraries(), p.getUsesSdkLibrariesVersionsMajor(),
                 p.getUsesStaticLibraries(), p.getUsesStaticLibrariesVersions(), p.getMimeGroups(),
                 mDomainVerificationManager.generateNewId());
         if (ret != null) {
@@ -849,9 +851,10 @@
 
     PackageSetting addPackageLPw(String name, String realName, File codePath,
             String legacyNativeLibraryPathString, String primaryCpuAbiString,
-            String secondaryCpuAbiString, String cpuAbiOverrideString, int uid, long vc, int
-            pkgFlags, int pkgPrivateFlags, String[] usesStaticLibraries,
-            long[] usesStaticLibraryNames, Map<String, Set<String>> mimeGroups,
+            String secondaryCpuAbiString, String cpuAbiOverrideString, int uid, long vc,
+            int pkgFlags, int pkgPrivateFlags, String[] usesSdkLibraries,
+            long[] usesSdkLibrariesVersions, String[] usesStaticLibraries,
+            long[] usesStaticLibrariesVersions, Map<String, Set<String>> mimeGroups,
             @NonNull UUID domainSetId) {
         PackageSetting p = mPackages.get(name);
         if (p != null) {
@@ -864,8 +867,8 @@
         }
         p = new PackageSetting(name, realName, codePath, legacyNativeLibraryPathString,
                 primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString, vc, pkgFlags,
-                pkgPrivateFlags, 0 /*userId*/, usesStaticLibraries, usesStaticLibraryNames,
-                mimeGroups, domainSetId);
+                pkgPrivateFlags, 0 /*userId*/, usesSdkLibraries, usesSdkLibrariesVersions,
+                usesStaticLibraries, usesStaticLibrariesVersions, mimeGroups, domainSetId);
         p.setAppId(uid);
         if (registerExistingAppIdLPw(uid, p, name)) {
             mPackages.put(name, p);
@@ -925,6 +928,7 @@
             String secondaryCpuAbi, long versionCode, int pkgFlags, int pkgPrivateFlags,
             UserHandle installUser, boolean allowInstall, boolean instantApp,
             boolean virtualPreload, UserManagerService userManager,
+            String[] usesSdkLibraries, long[] usesSdkLibrariesVersions,
             String[] usesStaticLibraries, long[] usesStaticLibrariesVersions,
             Set<String> mimeGroupNames, @NonNull UUID domainSetId) {
         final PackageSetting pkgSetting;
@@ -940,6 +944,8 @@
                     // overwrite the signatures in the original package setting.
                     .setSignatures(new PackageSignatures())
                     .setLongVersionCode(versionCode)
+                    .setUsesSdkLibraries(usesSdkLibraries)
+                    .setUsesSdkLibrariesVersionsMajor(usesSdkLibrariesVersions)
                     .setUsesStaticLibraries(usesStaticLibraries)
                     .setUsesStaticLibrariesVersions(usesStaticLibrariesVersions)
                     // Update new package state.
@@ -951,8 +957,9 @@
             pkgSetting = new PackageSetting(pkgName, realPkgName, codePath,
                     legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi,
                     null /*cpuAbiOverrideString*/, versionCode, pkgFlags, pkgPrivateFlags,
-                    0 /*sharedUserId*/, usesStaticLibraries,
-                    usesStaticLibrariesVersions, createMimeGroups(mimeGroupNames), domainSetId);
+                    0 /*sharedUserId*/, usesSdkLibraries, usesSdkLibrariesVersions,
+                    usesStaticLibraries, usesStaticLibrariesVersions,
+                    createMimeGroups(mimeGroupNames), domainSetId);
             pkgSetting.setLastModifiedTime(codePath.lastModified());
             pkgSetting.setSharedUser(sharedUser);
             // If this is not a system app, it starts out stopped.
@@ -1046,6 +1053,7 @@
             @NonNull File codePath, @Nullable String legacyNativeLibraryPath,
             @Nullable String primaryCpuAbi, @Nullable String secondaryCpuAbi, int pkgFlags,
             int pkgPrivateFlags, @NonNull UserManagerService userManager,
+            @Nullable String[] usesSdkLibraries, @Nullable long[] usesSdkLibrariesVersions,
             @Nullable String[] usesStaticLibraries, @Nullable long[] usesStaticLibrariesVersions,
             @Nullable Set<String> mimeGroupNames, @NonNull UUID domainSetId)
                     throws PackageManagerException {
@@ -1095,7 +1103,17 @@
                 .setSecondaryCpuAbi(secondaryCpuAbi)
                 .updateMimeGroups(mimeGroupNames)
                 .setDomainSetId(domainSetId);
-        // Update static shared library dependencies if needed
+        // Update SDK library dependencies if needed.
+        if (usesSdkLibraries != null && usesSdkLibrariesVersions != null
+                && usesSdkLibraries.length == usesSdkLibrariesVersions.length) {
+            pkgSetting.setUsesSdkLibraries(usesSdkLibraries)
+                    .setUsesSdkLibrariesVersionsMajor(usesSdkLibrariesVersions);
+        } else {
+            pkgSetting.setUsesSdkLibraries(null)
+                    .setUsesSdkLibrariesVersionsMajor(null);
+        }
+
+        // Update static shared library dependencies if needed.
         if (usesStaticLibraries != null && usesStaticLibrariesVersions != null
                 && usesStaticLibraries.length == usesStaticLibrariesVersions.length) {
             pkgSetting.setUsesStaticLibraries(usesStaticLibraries)
@@ -2167,6 +2185,21 @@
         }
     }
 
+    void readUsesSdkLibLPw(TypedXmlPullParser parser, PackageSetting outPs)
+            throws IOException, XmlPullParserException {
+        String libName = parser.getAttributeValue(null, ATTR_NAME);
+        long libVersion = parser.getAttributeLong(null, ATTR_VERSION, -1);
+
+        if (libName != null && libVersion >= 0) {
+            outPs.setUsesSdkLibraries(ArrayUtils.appendElement(String.class,
+                    outPs.getUsesSdkLibraries(), libName));
+            outPs.setUsesSdkLibrariesVersionsMajor(ArrayUtils.appendLong(
+                    outPs.getUsesSdkLibrariesVersionsMajor(), libVersion));
+        }
+
+        XmlUtils.skipCurrentTag(parser);
+    }
+
     void readUsesStaticLibLPw(TypedXmlPullParser parser, PackageSetting outPs)
             throws IOException, XmlPullParserException {
         String libName = parser.getAttributeValue(null, ATTR_NAME);
@@ -2182,6 +2215,23 @@
         XmlUtils.skipCurrentTag(parser);
     }
 
+    void writeUsesSdkLibLPw(TypedXmlSerializer serializer, String[] usesSdkLibraries,
+            long[] usesSdkLibraryVersions) throws IOException {
+        if (ArrayUtils.isEmpty(usesSdkLibraries) || ArrayUtils.isEmpty(usesSdkLibraryVersions)
+                || usesSdkLibraries.length != usesSdkLibraryVersions.length) {
+            return;
+        }
+        final int libCount = usesSdkLibraries.length;
+        for (int i = 0; i < libCount; i++) {
+            final String libName = usesSdkLibraries[i];
+            final long libVersion = usesSdkLibraryVersions[i];
+            serializer.startTag(null, TAG_USES_SDK_LIB);
+            serializer.attribute(null, ATTR_NAME, libName);
+            serializer.attributeLong(null, ATTR_VERSION, libVersion);
+            serializer.endTag(null, TAG_USES_SDK_LIB);
+        }
+    }
+
     void writeUsesStaticLibLPw(TypedXmlSerializer serializer, String[] usesStaticLibraries,
             long[] usesStaticLibraryVersions) throws IOException {
         if (ArrayUtils.isEmpty(usesStaticLibraries) || ArrayUtils.isEmpty(usesStaticLibraryVersions)
@@ -2707,6 +2757,9 @@
         }
         serializer.attributeFloat(null, "loadingProgress", pkg.getLoadingProgress());
 
+        writeUsesSdkLibLPw(serializer, pkg.getUsesSdkLibraries(),
+                pkg.getUsesSdkLibrariesVersionsMajor());
+
         writeUsesStaticLibLPw(serializer, pkg.getUsesStaticLibraries(),
                 pkg.getUsesStaticLibrariesVersions());
 
@@ -2785,6 +2838,9 @@
 
         serializer.attribute(null, "domainSetId", pkg.getDomainSetId().toString());
 
+        writeUsesSdkLibLPw(serializer, pkg.getUsesSdkLibraries(),
+                pkg.getUsesSdkLibrariesVersionsMajor());
+
         writeUsesStaticLibLPw(serializer, pkg.getUsesStaticLibraries(),
                 pkg.getUsesStaticLibrariesVersions());
 
@@ -3455,8 +3511,8 @@
         UUID domainSetId = DomainVerificationManagerInternal.DISABLED_ID;
         PackageSetting ps = new PackageSetting(name, realName, new File(codePathStr),
                 legacyNativeLibraryPathStr, primaryCpuAbiStr, secondaryCpuAbiStr, cpuAbiOverrideStr,
-                versionCode, pkgFlags, pkgPrivateFlags, 0 /*sharedUserId*/, null, null, null,
-                domainSetId);
+                versionCode, pkgFlags, pkgPrivateFlags, 0 /*sharedUserId*/, null, null, null, null,
+                null, domainSetId);
         long timeStamp = parser.getAttributeLongHex(null, "ft", 0);
         if (timeStamp == 0) {
             timeStamp = parser.getAttributeLong(null, "ts", 0);
@@ -3484,6 +3540,8 @@
                 readInstallPermissionsLPr(parser, ps.getLegacyPermissionState(), users);
             } else if (parser.getName().equals(TAG_USES_STATIC_LIB)) {
                 readUsesStaticLibLPw(parser, ps);
+            } else if (parser.getName().equals(TAG_USES_SDK_LIB)) {
+                readUsesSdkLibLPw(parser, ps);
             } else {
                 PackageManagerService.reportSettingsProblem(Log.WARN,
                         "Unknown element under <updated-package>: " + parser.getName());
@@ -3642,8 +3700,9 @@
                 packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
                         legacyNativeLibraryPathStr, primaryCpuAbiString, secondaryCpuAbiString,
                         cpuAbiOverrideString, userId, versionCode, pkgFlags, pkgPrivateFlags,
-                        null /*usesStaticLibraries*/, null /*usesStaticLibraryVersions*/,
-                        null /*mimeGroups*/, domainSetId);
+                        null /* usesSdkLibraries */, null /* usesSdkLibraryVersions */,
+                        null /* usesStaticLibraries */, null /* usesStaticLibraryVersions */,
+                        null /* mimeGroups */, domainSetId);
                 if (PackageManagerService.DEBUG_SETTINGS)
                     Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId="
                             + userId + " pkg=" + packageSetting);
@@ -3662,9 +3721,11 @@
                             new File(codePathStr), legacyNativeLibraryPathStr,
                             primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
                             versionCode, pkgFlags, pkgPrivateFlags, sharedUserId,
-                            null /*usesStaticLibraries*/,
-                            null /*usesStaticLibraryVersions*/,
-                            null /*mimeGroups*/, domainSetId);
+                            null /* usesSdkLibraries */,
+                            null /* usesSdkLibrariesVersions */,
+                            null /* usesStaticLibraries */,
+                            null /* usesStaticLibraryVersions */,
+                            null /* mimeGroups */, domainSetId);
                     packageSetting.setLastModifiedTime(timeStamp);
                     packageSetting.setFirstInstallTime(firstInstallTime);
                     packageSetting.setLastUpdateTime(lastUpdateTime);
@@ -3793,6 +3854,8 @@
                     }
                 } else if (tagName.equals(TAG_USES_STATIC_LIB)) {
                     readUsesStaticLibLPw(parser, packageSetting);
+                } else if (tagName.equals(TAG_USES_SDK_LIB)) {
+                    readUsesSdkLibLPw(parser, packageSetting);
                 } else {
                     PackageManagerService.reportSettingsProblem(Log.WARN,
                             "Unknown element under <package>: " + parser.getName());
@@ -4581,6 +4644,13 @@
                 pw.print(" version:"); pw.println(pkg.getStaticSharedLibVersion());
             }
 
+            if (pkg.getSdkLibName() != null) {
+                pw.print(prefix); pw.println("  SDK library:");
+                pw.print(prefix); pw.print("    ");
+                pw.print("name:"); pw.print(pkg.getSdkLibName());
+                pw.print(" versionMajor:"); pw.println(pkg.getSdkLibVersionMajor());
+            }
+
             List<String> usesLibraries = pkg.getUsesLibraries();
             if (usesLibraries.size() > 0) {
                 pw.print(prefix); pw.println("  usesLibraries:");
@@ -4600,6 +4670,17 @@
                 }
             }
 
+            List<String> usesSdkLibraries = pkg.getUsesSdkLibraries();
+            long[] usesSdkLibrariesVersionsMajor = pkg.getUsesSdkLibrariesVersionsMajor();
+            if (usesSdkLibraries.size() > 0) {
+                pw.print(prefix); pw.println("  usesSdkLibraries:");
+                for (int i = 0, size = usesSdkLibraries.size(); i < size; ++i) {
+                    pw.print(prefix); pw.print("    ");
+                    pw.print(usesSdkLibraries.get(i)); pw.print(" version:");
+                    pw.println(usesSdkLibrariesVersionsMajor[i]);
+                }
+            }
+
             List<String> usesOptionalLibraries = pkg.getUsesOptionalLibraries();
             if (usesOptionalLibraries.size() > 0) {
                 pw.print(prefix); pw.println("  usesOptionalLibraries:");
diff --git a/services/core/java/com/android/server/pm/SharedLibraryHelper.java b/services/core/java/com/android/server/pm/SharedLibraryHelper.java
index 461fca1..dd8fad0 100644
--- a/services/core/java/com/android/server/pm/SharedLibraryHelper.java
+++ b/services/core/java/com/android/server/pm/SharedLibraryHelper.java
@@ -76,12 +76,15 @@
             Map<String, WatchedLongSparseArray<SharedLibraryInfo>> existingSharedLibraries) {
         // Let's used the parsed package as scanResult.pkgSetting may be null
         final ParsedPackage parsedPackage = scanResult.mRequest.mParsedPackage;
-        if (scanResult.mStaticSharedLibraryInfo == null
+        if (scanResult.mSdkSharedLibraryInfo == null && scanResult.mStaticSharedLibraryInfo == null
                 && scanResult.mDynamicSharedLibraryInfos == null) {
             return null;
         }
 
-        // Any app can add new static shared libraries
+        // Any app can add new SDKs and static shared libraries.
+        if (scanResult.mSdkSharedLibraryInfo != null) {
+            return Collections.singletonList(scanResult.mSdkSharedLibraryInfo);
+        }
         if (scanResult.mStaticSharedLibraryInfo != null) {
             return Collections.singletonList(scanResult.mStaticSharedLibraryInfo);
         }
@@ -181,41 +184,49 @@
         ArrayList<SharedLibraryInfo> usesLibraryInfos = null;
         if (!pkg.getUsesLibraries().isEmpty()) {
             usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesLibraries(), null, null,
-                    pkg.getPackageName(), true, pkg.getTargetSdkVersion(), null,
+                    pkg.getPackageName(), "shared", true, pkg.getTargetSdkVersion(), null,
                     availablePackages, existingLibraries, newLibraries);
         }
         if (!pkg.getUsesStaticLibraries().isEmpty()) {
             usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesStaticLibraries(),
                     pkg.getUsesStaticLibrariesVersions(), pkg.getUsesStaticLibrariesCertDigests(),
-                    pkg.getPackageName(), true, pkg.getTargetSdkVersion(), usesLibraryInfos,
-                    availablePackages, existingLibraries, newLibraries);
+                    pkg.getPackageName(), "static shared", true, pkg.getTargetSdkVersion(),
+                    usesLibraryInfos, availablePackages, existingLibraries, newLibraries);
         }
         if (!pkg.getUsesOptionalLibraries().isEmpty()) {
-            usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesOptionalLibraries(),
-                    null, null, pkg.getPackageName(), false, pkg.getTargetSdkVersion(),
+            usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesOptionalLibraries(), null, null,
+                    pkg.getPackageName(), "shared", false, pkg.getTargetSdkVersion(),
                     usesLibraryInfos, availablePackages, existingLibraries, newLibraries);
         }
         if (platformCompat.isChangeEnabledInternal(ENFORCE_NATIVE_SHARED_LIBRARY_DEPENDENCIES,
                 pkg.getPackageName(), pkg.getTargetSdkVersion())) {
             if (!pkg.getUsesNativeLibraries().isEmpty()) {
                 usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesNativeLibraries(), null,
-                        null, pkg.getPackageName(), true, pkg.getTargetSdkVersion(),
-                        usesLibraryInfos, availablePackages, existingLibraries, newLibraries);
+                        null, pkg.getPackageName(), "native shared", true,
+                        pkg.getTargetSdkVersion(), usesLibraryInfos, availablePackages,
+                        existingLibraries, newLibraries);
             }
             if (!pkg.getUsesOptionalNativeLibraries().isEmpty()) {
                 usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesOptionalNativeLibraries(),
-                        null, null, pkg.getPackageName(), false, pkg.getTargetSdkVersion(),
-                        usesLibraryInfos, availablePackages, existingLibraries, newLibraries);
+                        null, null, pkg.getPackageName(), "native shared", false,
+                        pkg.getTargetSdkVersion(), usesLibraryInfos, availablePackages,
+                        existingLibraries, newLibraries);
             }
         }
+        if (!pkg.getUsesSdkLibraries().isEmpty()) {
+            usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesSdkLibraries(),
+                    pkg.getUsesSdkLibrariesVersionsMajor(), pkg.getUsesSdkLibrariesCertDigests(),
+                    pkg.getPackageName(), "sdk", true, pkg.getTargetSdkVersion(), usesLibraryInfos,
+                    availablePackages, existingLibraries, newLibraries);
+        }
         return usesLibraryInfos;
     }
 
     public static ArrayList<SharedLibraryInfo> collectSharedLibraryInfos(
             @NonNull List<String> requestedLibraries,
             @Nullable long[] requiredVersions, @Nullable String[][] requiredCertDigests,
-            @NonNull String packageName, boolean required, int targetSdk,
-            @Nullable ArrayList<SharedLibraryInfo> outUsedLibraries,
+            @NonNull String packageName, @NonNull String libraryType, boolean required,
+            int targetSdk, @Nullable ArrayList<SharedLibraryInfo> outUsedLibraries,
             @NonNull final Map<String, AndroidPackage> availablePackages,
             @NonNull final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> existingLibraries,
             @Nullable final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> newLibraries)
@@ -230,18 +241,17 @@
             if (libraryInfo == null) {
                 if (required) {
                     throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
-                            "Package " + packageName + " requires unavailable shared library "
-                                    + libName + "; failing!");
+                            "Package " + packageName + " requires unavailable " + libraryType
+                                    + " library " + libName + "; failing!");
                 } else if (DEBUG_SHARED_LIBRARIES) {
-                    Slog.i(TAG, "Package " + packageName
-                            + " desires unavailable shared library "
-                            + libName + "; ignoring!");
+                    Slog.i(TAG, "Package " + packageName + " desires unavailable " + libraryType
+                            + " library " + libName + "; ignoring!");
                 }
             } else {
                 if (requiredVersions != null && requiredCertDigests != null) {
                     if (libraryInfo.getLongVersion() != requiredVersions[i]) {
                         throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
-                                "Package " + packageName + " requires unavailable static shared"
+                                "Package " + packageName + " requires unavailable " + libraryType
                                         + " library " + libName + " version "
                                         + libraryInfo.getLongVersion() + "; failing!");
                     }
@@ -249,7 +259,7 @@
                     SigningDetails libPkg = pkg == null ? null : pkg.getSigningDetails();
                     if (libPkg == null) {
                         throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
-                                "Package " + packageName + " requires unavailable static shared"
+                                "Package " + packageName + " requires unavailable " + libraryType
                                         + " library; failing!");
                     }
                     final String[] expectedCertDigests = requiredCertDigests[i];
@@ -267,8 +277,8 @@
                         // Therefore, the size check is safe to make.
                         if (expectedCertDigests.length != libCertDigests.length) {
                             throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
-                                    "Package " + packageName + " requires differently signed"
-                                            + " static shared library; failing!");
+                                    "Package " + packageName + " requires differently signed "
+                                            + libraryType + " library; failing!");
                         }
 
                         // Use a predictable order as signature order may vary
@@ -280,8 +290,8 @@
                             if (!libCertDigests[j].equalsIgnoreCase(expectedCertDigests[j])) {
                                 throw new PackageManagerException(
                                         INSTALL_FAILED_MISSING_SHARED_LIBRARY,
-                                        "Package " + packageName + " requires differently signed"
-                                                + " static shared library; failing!");
+                                        "Package " + packageName + " requires differently signed "
+                                                + libraryType + " library; failing!");
                             }
                         }
                     } else {
@@ -290,10 +300,9 @@
                         byte[] digestBytes = HexEncoding.decode(
                                 expectedCertDigests[0], false /* allowSingleChar */);
                         if (!libPkg.hasSha256Certificate(digestBytes)) {
-                            throw new PackageManagerException(
-                                    INSTALL_FAILED_MISSING_SHARED_LIBRARY,
-                                    "Package " + packageName + " requires differently signed"
-                                            + " static shared library; failing!");
+                            throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
+                                    "Package " + packageName + " requires differently signed "
+                                            + libraryType + " library; failing!");
                         }
                     }
                 }
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
index 32b1e5d..8b2c3a12 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
@@ -87,6 +87,17 @@
         return paths;
     }
 
+    public static SharedLibraryInfo createSharedLibraryForSdk(AndroidPackage pkg) {
+        return new SharedLibraryInfo(null, pkg.getPackageName(),
+                AndroidPackageUtils.getAllCodePaths(pkg),
+                pkg.getSdkLibName(),
+                pkg.getSdkLibVersionMajor(),
+                SharedLibraryInfo.TYPE_SDK,
+                new VersionedPackage(pkg.getManifestPackageName(),
+                        pkg.getLongVersionCode()),
+                null, null, false /* isNative */);
+    }
+
     public static SharedLibraryInfo createSharedLibraryForStatic(AndroidPackage pkg) {
         return new SharedLibraryInfo(null, pkg.getPackageName(),
                 AndroidPackageUtils.getAllCodePaths(pkg),
@@ -218,7 +229,8 @@
 
     public static boolean isLibrary(AndroidPackage pkg) {
         // TODO(b/135203078): Can parsing just enforce these always match?
-        return pkg.getStaticSharedLibName() != null || !pkg.getLibraryNames().isEmpty();
+        return pkg.getSdkLibName() != null || pkg.getStaticSharedLibName() != null
+                || !pkg.getLibraryNames().isEmpty();
     }
 
     public static int getHiddenApiEnforcementPolicy(AndroidPackage pkg,
diff --git a/services/core/java/com/android/server/pm/pkg/PackageState.java b/services/core/java/com/android/server/pm/pkg/PackageState.java
index 82edce6..34575e0 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageState.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageState.java
@@ -27,7 +27,6 @@
 import android.content.pm.SigningInfo;
 import android.util.SparseArray;
 
-import com.android.internal.R;
 import com.android.server.pm.PackageSetting;
 import com.android.server.pm.Settings;
 
@@ -206,6 +205,18 @@
     List<SharedLibraryInfo> getUsesLibraryInfos();
 
     /**
+     * @see R.styleable#AndroidManifestUsesSdkLibrary
+     */
+    @NonNull
+    String[] getUsesSdkLibraries();
+
+    /**
+     * @see R.styleable#AndroidManifestUsesSdkLibrary_versionMajor
+     */
+    @NonNull
+    long[] getUsesSdkLibrariesVersionsMajor();
+
+    /**
      * @see R.styleable#AndroidManifestUsesStaticLibrary
      */
     @NonNull
diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java b/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
index 46d32b9..f5e498d 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
@@ -130,6 +130,10 @@
     @Nullable
     private final Integer mSharedUserId;
     @NonNull
+    private final String[] mUsesSdkLibraries;
+    @NonNull
+    private final long[] mUsesSdkLibrariesVersionsMajor;
+    @NonNull
     private final String[] mUsesStaticLibraries;
     @NonNull
     private final long[] mUsesStaticLibrariesVersions;
@@ -171,6 +175,8 @@
         mPrimaryCpuAbi = pkgState.getPrimaryCpuAbi();
         mSecondaryCpuAbi = pkgState.getSecondaryCpuAbi();
         mSharedUserId = pkgState.getSharedUserId();
+        mUsesSdkLibraries = pkgState.getUsesSdkLibraries();
+        mUsesSdkLibrariesVersionsMajor = pkgState.getUsesSdkLibrariesVersionsMajor();
         mUsesStaticLibraries = pkgState.getUsesStaticLibraries();
         mUsesStaticLibrariesVersions = pkgState.getUsesStaticLibrariesVersions();
         mUsesLibraryInfos = pkgState.getUsesLibraryInfos();
@@ -262,6 +268,11 @@
         return getBoolean(Booleans.VENDOR);
     }
 
+    @Override
+    public long getVersionCode() {
+        return mLongVersionCode;
+    }
+
     /**
      * @hide
      */
@@ -500,10 +511,10 @@
         }
 
         @DataClass.Generated(
-                time = 1633375703010L,
+                time = 1637977288540L,
                 codegenVersion = "1.0.23",
                 sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java",
-                inputSignatures = "private  int mBooleans\nprivate final  long mCeDataInode\nprivate final @android.annotation.NonNull java.util.Set<java.lang.String> mDisabledComponents\nprivate final @android.content.pm.PackageManager.DistractionRestriction int mDistractionFlags\nprivate final @android.annotation.NonNull java.util.Set<java.lang.String> mEnabledComponents\nprivate final  int mEnabledState\nprivate final @android.annotation.Nullable java.lang.String mHarmfulAppWarning\nprivate final @android.content.pm.PackageManager.InstallReason int mInstallReason\nprivate final @android.annotation.Nullable java.lang.String mLastDisableAppCaller\nprivate final @android.annotation.NonNull android.content.pm.overlay.OverlayPaths mOverlayPaths\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,android.content.pm.overlay.OverlayPaths> mSharedLibraryOverlayPaths\nprivate final @android.content.pm.PackageManager.UninstallReason int mUninstallReason\nprivate final @android.annotation.Nullable java.lang.String mSplashScreenTheme\npublic static  android.content.pm.pkg.PackageUserState copy(android.content.pm.pkg.PackageUserState)\nprivate  void setBoolean(int,boolean)\nprivate  boolean getBoolean(int)\npublic @java.lang.Override boolean isHidden()\npublic @java.lang.Override boolean isInstalled()\npublic @java.lang.Override boolean isInstantApp()\npublic @java.lang.Override boolean isNotLaunched()\npublic @java.lang.Override boolean isStopped()\npublic @java.lang.Override boolean isSuspended()\npublic @java.lang.Override boolean isVirtualPreload()\npublic @java.lang.Override boolean isComponentEnabled(java.lang.String)\npublic @java.lang.Override boolean isComponentDisabled(java.lang.String)\npublic @java.lang.Override android.content.pm.overlay.OverlayPaths getAllOverlayPaths()\nclass UserStateImpl extends java.lang.Object implements [android.content.pm.pkg.PackageUserState]\nprivate static final  int HIDDEN\nprivate static final  int INSTALLED\nprivate static final  int INSTANT_APP\nprivate static final  int NOT_LAUNCHED\nprivate static final  int STOPPED\nprivate static final  int SUSPENDED\nprivate static final  int VIRTUAL_PRELOAD\nclass Booleans extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false)")
+                inputSignatures = "private  int mBooleans\nprivate final  long mCeDataInode\nprivate final @android.annotation.NonNull java.util.Set<java.lang.String> mDisabledComponents\nprivate final @android.content.pm.PackageManager.DistractionRestriction int mDistractionFlags\nprivate final @android.annotation.NonNull java.util.Set<java.lang.String> mEnabledComponents\nprivate final  int mEnabledState\nprivate final @android.annotation.Nullable java.lang.String mHarmfulAppWarning\nprivate final @android.content.pm.PackageManager.InstallReason int mInstallReason\nprivate final @android.annotation.Nullable java.lang.String mLastDisableAppCaller\nprivate final @android.annotation.NonNull android.content.pm.overlay.OverlayPaths mOverlayPaths\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,android.content.pm.overlay.OverlayPaths> mSharedLibraryOverlayPaths\nprivate final @android.content.pm.PackageManager.UninstallReason int mUninstallReason\nprivate final @android.annotation.Nullable java.lang.String mSplashScreenTheme\npublic static  com.android.server.pm.pkg.PackageUserState copy(com.android.server.pm.pkg.PackageUserState)\nprivate  void setBoolean(int,boolean)\nprivate  boolean getBoolean(int)\npublic @java.lang.Override boolean isHidden()\npublic @java.lang.Override boolean isInstalled()\npublic @java.lang.Override boolean isInstantApp()\npublic @java.lang.Override boolean isNotLaunched()\npublic @java.lang.Override boolean isStopped()\npublic @java.lang.Override boolean isSuspended()\npublic @java.lang.Override boolean isVirtualPreload()\npublic @java.lang.Override boolean isComponentEnabled(java.lang.String)\npublic @java.lang.Override boolean isComponentDisabled(java.lang.String)\npublic @java.lang.Override android.content.pm.overlay.OverlayPaths getAllOverlayPaths()\nclass UserStateImpl extends java.lang.Object implements [com.android.server.pm.pkg.PackageUserState]\nprivate static final  int HIDDEN\nprivate static final  int INSTALLED\nprivate static final  int INSTANT_APP\nprivate static final  int NOT_LAUNCHED\nprivate static final  int STOPPED\nprivate static final  int SUSPENDED\nprivate static final  int VIRTUAL_PRELOAD\nclass Booleans extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false)")
         @Deprecated
         private void __metadata() {}
 
@@ -579,7 +590,7 @@
     }
 
     @DataClass.Generated.Member
-    public long getVersionCode() {
+    public long getLongVersionCode() {
         return mLongVersionCode;
     }
 
@@ -609,6 +620,16 @@
     }
 
     @DataClass.Generated.Member
+    public @NonNull String[] getUsesSdkLibraries() {
+        return mUsesSdkLibraries;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull long[] getUsesSdkLibrariesVersionsMajor() {
+        return mUsesSdkLibrariesVersionsMajor;
+    }
+
+    @DataClass.Generated.Member
     public @NonNull String[] getUsesStaticLibraries() {
         return mUsesStaticLibraries;
     }
@@ -650,10 +671,10 @@
     }
 
     @DataClass.Generated(
-            time = 1633375703038L,
+            time = 1637977288579L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java",
-            inputSignatures = "private  int mBooleans\nprivate final @android.annotation.Nullable com.android.server.pm.pkg.AndroidPackageApi mAndroidPackage\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mVolumeUuid\nprivate final  int mAppId\nprivate final  int mCategoryOverride\nprivate final @android.annotation.Nullable java.lang.String mCpuAbiOverride\nprivate final  long mFirstInstallTime\nprivate final  long mLastModifiedTime\nprivate final  long mLastUpdateTime\nprivate final  long mLongVersionCode\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,java.util.Set<java.lang.String>> mMimeGroups\nprivate final @android.annotation.NonNull java.io.File mPath\nprivate final @android.annotation.Nullable java.lang.String mPrimaryCpuAbi\nprivate final @android.annotation.Nullable java.lang.String mSecondaryCpuAbi\nprivate final @android.annotation.Nullable java.lang.Integer mSharedUserId\nprivate final @android.annotation.NonNull java.lang.String[] mUsesStaticLibraries\nprivate final @android.annotation.NonNull long[] mUsesStaticLibrariesVersions\nprivate final @android.annotation.NonNull java.util.List<android.content.pm.SharedLibraryInfo> mUsesLibraryInfos\nprivate final @android.annotation.NonNull java.util.List<java.lang.String> mUsesLibraryFiles\nprivate final @android.annotation.NonNull long[] mLastPackageUsageTime\nprivate final @android.annotation.NonNull android.content.pm.SigningInfo mSigningInfo\nprivate final @android.annotation.NonNull android.util.SparseArray<android.content.pm.pkg.PackageUserState> mUserStates\npublic static  com.android.server.pm.pkg.PackageState copy(com.android.server.pm.PackageSetting)\nprivate  void setBoolean(int,boolean)\nprivate  boolean getBoolean(int)\npublic @java.lang.Override boolean isExternalStorage()\npublic @java.lang.Override boolean isForceQueryableOverride()\npublic @java.lang.Override boolean isHiddenUntilInstalled()\npublic @java.lang.Override boolean isInstallPermissionsFixed()\npublic @java.lang.Override boolean isOdm()\npublic @java.lang.Override boolean isOem()\npublic @java.lang.Override boolean isPrivileged()\npublic @java.lang.Override boolean isProduct()\npublic @java.lang.Override boolean isRequiredForSystemUser()\npublic @java.lang.Override boolean isSystem()\npublic @java.lang.Override boolean isSystemExt()\npublic @java.lang.Override boolean isUpdateAvailable()\npublic @java.lang.Override boolean isUpdatedSystemApp()\npublic @java.lang.Override boolean isVendor()\nclass PackageStateImpl extends java.lang.Object implements [com.android.server.pm.pkg.PackageState]\nprivate static final  int SYSTEM\nprivate static final  int EXTERNAL_STORAGE\nprivate static final  int PRIVILEGED\nprivate static final  int OEM\nprivate static final  int VENDOR\nprivate static final  int PRODUCT\nprivate static final  int SYSTEM_EXT\nprivate static final  int REQUIRED_FOR_SYSTEM_USER\nprivate static final  int ODM\nprivate static final  int FORCE_QUERYABLE_OVERRIDE\nprivate static final  int HIDDEN_UNTIL_INSTALLED\nprivate static final  int INSTALL_PERMISSIONS_FIXED\nprivate static final  int UPDATE_AVAILABLE\nprivate static final  int UPDATED_SYSTEM_APP\nclass Booleans extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false)")
+            inputSignatures = "private  int mBooleans\nprivate final @android.annotation.Nullable com.android.server.pm.pkg.AndroidPackageApi mAndroidPackage\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mVolumeUuid\nprivate final  int mAppId\nprivate final  int mCategoryOverride\nprivate final @android.annotation.Nullable java.lang.String mCpuAbiOverride\nprivate final  long mFirstInstallTime\nprivate final  long mLastModifiedTime\nprivate final  long mLastUpdateTime\nprivate final  long mLongVersionCode\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,java.util.Set<java.lang.String>> mMimeGroups\nprivate final @android.annotation.NonNull java.io.File mPath\nprivate final @android.annotation.Nullable java.lang.String mPrimaryCpuAbi\nprivate final @android.annotation.Nullable java.lang.String mSecondaryCpuAbi\nprivate final @android.annotation.Nullable java.lang.Integer mSharedUserId\nprivate final @android.annotation.NonNull java.lang.String[] mUsesSdkLibraries\nprivate final @android.annotation.NonNull long[] mUsesSdkLibrariesVersionsMajor\nprivate final @android.annotation.NonNull java.lang.String[] mUsesStaticLibraries\nprivate final @android.annotation.NonNull long[] mUsesStaticLibrariesVersions\nprivate final @android.annotation.NonNull java.util.List<android.content.pm.SharedLibraryInfo> mUsesLibraryInfos\nprivate final @android.annotation.NonNull java.util.List<java.lang.String> mUsesLibraryFiles\nprivate final @android.annotation.NonNull long[] mLastPackageUsageTime\nprivate final @android.annotation.NonNull android.content.pm.SigningInfo mSigningInfo\nprivate final @android.annotation.NonNull android.util.SparseArray<com.android.server.pm.pkg.PackageUserState> mUserStates\npublic static  com.android.server.pm.pkg.PackageState copy(com.android.server.pm.pkg.PackageStateInternal)\nprivate  void setBoolean(int,boolean)\nprivate  boolean getBoolean(int)\npublic @java.lang.Override boolean isExternalStorage()\npublic @java.lang.Override boolean isForceQueryableOverride()\npublic @java.lang.Override boolean isHiddenUntilInstalled()\npublic @java.lang.Override boolean isInstallPermissionsFixed()\npublic @java.lang.Override boolean isOdm()\npublic @java.lang.Override boolean isOem()\npublic @java.lang.Override boolean isPrivileged()\npublic @java.lang.Override boolean isProduct()\npublic @java.lang.Override boolean isRequiredForSystemUser()\npublic @java.lang.Override boolean isSystem()\npublic @java.lang.Override boolean isSystemExt()\npublic @java.lang.Override boolean isUpdateAvailable()\npublic @java.lang.Override boolean isUpdatedSystemApp()\npublic @java.lang.Override boolean isVendor()\npublic @java.lang.Override long getVersionCode()\nclass PackageStateImpl extends java.lang.Object implements [com.android.server.pm.pkg.PackageState]\nprivate static final  int SYSTEM\nprivate static final  int EXTERNAL_STORAGE\nprivate static final  int PRIVILEGED\nprivate static final  int OEM\nprivate static final  int VENDOR\nprivate static final  int PRODUCT\nprivate static final  int SYSTEM_EXT\nprivate static final  int REQUIRED_FOR_SYSTEM_USER\nprivate static final  int ODM\nprivate static final  int FORCE_QUERYABLE_OVERRIDE\nprivate static final  int HIDDEN_UNTIL_INSTALLED\nprivate static final  int INSTALL_PERMISSIONS_FIXED\nprivate static final  int UPDATE_AVAILABLE\nprivate static final  int UPDATED_SYSTEM_APP\nclass Booleans extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
index 9d86081..4b12fd4 100644
--- a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
+++ b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
@@ -274,7 +274,7 @@
     private fun makePkgSetting(pkgName: String) = spy(
         PackageSetting(
             pkgName, null, File("/test"),
-            null, null, null, null, 0, 0, 0, 0, null, null, null,
+            null, null, null, null, 0, 0, 0, 0, null, null, null, null, null,
             UUID.fromString("3f9d52b7-d7b4-406a-a1da-d9f19984c72c")
         )
     ) {
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
index dc93e53..4a35fdf 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
@@ -106,6 +106,16 @@
         "setSplitCodePaths",
         "setSplitClassLoaderName",
         "setSplitHasCode",
+        // Tested through addUsesSdkLibrary
+        "addUsesSdkLibrary",
+        "getUsesSdkLibraries",
+        "getUsesSdkLibrariesVersionsMajor",
+        "getUsesSdkLibrariesCertDigests",
+        // Tested through addUsesStaticLibrary
+        "addUsesStaticLibrary",
+        "getUsesStaticLibraries",
+        "getUsesStaticLibrariesVersions",
+        "getUsesStaticLibrariesCertDigests"
     )
 
     override val baseParams = listOf(
@@ -157,6 +167,8 @@
         AndroidPackage::getSecondaryNativeLibraryDir,
         AndroidPackage::getSharedUserId,
         AndroidPackage::getSharedUserLabel,
+        AndroidPackage::getSdkLibName,
+        AndroidPackage::getSdkLibVersionMajor,
         AndroidPackage::getStaticSharedLibName,
         AndroidPackage::getStaticSharedLibVersion,
         AndroidPackage::getTargetSandboxVersion,
@@ -210,6 +222,7 @@
         AndroidPackage::isResizeableActivityViaSdkVersion,
         AndroidPackage::isRestoreAnyVersion,
         AndroidPackage::isSignedWithPlatformKey,
+        AndroidPackage::isSdkLibrary,
         AndroidPackage::isStaticSharedLibrary,
         AndroidPackage::isStub,
         AndroidPackage::isSupportsRtl,
@@ -228,7 +241,7 @@
         AndroidPackage::getMinAspectRatio,
         AndroidPackage::hasPreserveLegacyExternalStorage,
         AndroidPackage::hasRequestForegroundServiceExemption,
-        AndroidPackage::hasRequestRawExternalStorageAccess,
+        AndroidPackage::hasRequestRawExternalStorageAccess
     )
 
     override fun extraParams() = listOf(
@@ -254,13 +267,6 @@
         adder(AndroidPackage::getUsesNativeLibraries, "testUsesNativeLibrary"),
         adder(AndroidPackage::getUsesOptionalLibraries, "testUsesOptionalLibrary"),
         adder(AndroidPackage::getUsesOptionalNativeLibraries, "testUsesOptionalNativeLibrary"),
-        adder(AndroidPackage::getUsesStaticLibraries, "testUsesStaticLibrary"),
-        getSetByValue(
-            AndroidPackage::getUsesStaticLibrariesVersions,
-            PackageImpl::addUsesStaticLibraryVersion,
-            (testCounter++).toLong(),
-            transformGet = { it?.singleOrNull() }
-        ),
         getSetByValue(
             AndroidPackage::areAttributionsUserVisible,
             ParsingPackage::setAttributionsAreUserVisible,
@@ -290,7 +296,7 @@
             AndroidPackage::getKeySetMapping,
             PackageImpl::addKeySet,
             "testKeySetName" to testKey(),
-            transformGet = { "testKeySetName" to it["testKeySetName"]?.singleOrNull() },
+            transformGet = { "testKeySetName" to it["testKeySetName"]?.singleOrNull() }
         ),
         getSetByValue(
             AndroidPackage::getPermissionGroups,
@@ -315,7 +321,7 @@
                     { it.first },
                     { it.second.intentFilter.schemesIterator().asSequence().singleOrNull() },
                     { it.second.intentFilter.authoritiesIterator().asSequence()
-                        .singleOrNull()?.host },
+                        .singleOrNull()?.host }
                 )
             }
         ),
@@ -324,7 +330,7 @@
             PackageImpl::addQueriesIntent,
             Intent(Intent.ACTION_VIEW, Uri.parse("https://test.pm.server.android.com")),
             transformGet = { it.singleOrNull() },
-            compare = { first, second -> first?.filterEquals(second) },
+            compare = { first, second -> first?.filterEquals(second) }
         ),
         getSetByValue(
             AndroidPackage::getRestrictUpdateHash,
@@ -347,13 +353,6 @@
             }
         ),
         getSetByValue(
-            AndroidPackage::getUsesStaticLibrariesCertDigests,
-            PackageImpl::addUsesStaticLibraryCertDigests,
-            arrayOf("testCertDigest"),
-            transformGet = { it?.singleOrNull() },
-            compare = Array<String?>?::contentEquals
-        ),
-        getSetByValue(
             AndroidPackage::getActivities,
             PackageImpl::addActivity,
             "TestActivityName",
@@ -440,7 +439,7 @@
                     first, second,
                     { it.size() },
                     { it.keyAt(0) },
-                    { it.valueAt(0) },
+                    { it.valueAt(0) }
                 )
             }
         ),
@@ -451,7 +450,7 @@
             compare = { first, second ->
                 equalBy(
                     first, second,
-                    { it["testProcess"]?.name },
+                    { it["testProcess"]?.name }
                 )
             }
         ),
@@ -471,10 +470,10 @@
                     PackageManager.Property::getName,
                     PackageManager.Property::getClassName,
                     PackageManager.Property::getPackageName,
-                    PackageManager.Property::getString,
+                    PackageManager.Property::getString
                 )
             }
-        ),
+        )
     )
 
     override fun initialObject() = PackageImpl.forParsing(
@@ -518,6 +517,9 @@
         .setSplitClassLoaderName(0, "testSplitClassLoaderNameZero")
         .setSplitClassLoaderName(1, "testSplitClassLoaderNameOne")
 
+        .addUsesSdkLibrary("testSdk", 2L, arrayOf("testCertDigest1"))
+        .addUsesStaticLibrary("testStatic", 3L, arrayOf("testCertDigest2"))
+
     override fun extraAssertions(before: Parcelable, after: Parcelable) {
         super.extraAssertions(before, after)
         after as PackageImpl
@@ -558,6 +560,18 @@
             expect.that(it.get(0)).asList().containsExactly(-1)
             expect.that(it.get(1)).asList().containsExactly(0)
         }
+
+        expect.that(after.usesSdkLibraries).containsExactly("testSdk")
+        expect.that(after.usesSdkLibrariesVersionsMajor).asList().containsExactly(2L)
+        expect.that(after.usesSdkLibrariesCertDigests!!.size).isEqualTo(1)
+        expect.that(after.usesSdkLibrariesCertDigests!![0]).asList()
+                .containsExactly("testCertDigest1")
+
+        expect.that(after.usesStaticLibraries).containsExactly("testStatic")
+        expect.that(after.usesStaticLibrariesVersions).asList().containsExactly(3L)
+        expect.that(after.usesStaticLibrariesCertDigests!!.size).isEqualTo(1)
+        expect.that(after.usesStaticLibrariesCertDigests!![0]).asList()
+                .containsExactly("testCertDigest2")
     }
 
     private fun testKey() = KeyPairGenerator.getInstance("RSA")
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
index 0e5640a..ae5984a41 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -150,7 +150,7 @@
         }
         whenever(mocks.settings.addPackageLPw(nullable(), nullable(), nullable(), nullable(),
                 nullable(), nullable(), nullable(), nullable(), nullable(), nullable(), nullable(),
-                nullable(), nullable(), nullable(), nullable())) {
+                nullable(), nullable(), nullable(), nullable(), nullable(), nullable())) {
             val name: String = getArgument(0)
             val pendingAdd = mPendingPackageAdds.firstOrNull { it.first == name }
                     ?: return@whenever null
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index a9a3469..6c9f8fe 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -498,6 +498,71 @@
     }
 
     @Test
+    public void testWriteReadUsesSdkLibraries() {
+        final Settings settingsUnderTest = makeSettings();
+        final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
+        ps1.setAppId(Process.FIRST_APPLICATION_UID);
+        ps1.setPkg(((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME_1).hideAsParsed())
+                .setUid(ps1.getAppId())
+                .setSystem(true)
+                .hideAsFinal());
+        final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
+        ps2.setAppId(Process.FIRST_APPLICATION_UID + 1);
+        ps2.setPkg(((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME_2).hideAsParsed())
+                .setUid(ps2.getAppId())
+                .hideAsFinal());
+
+        ps1.setUsesSdkLibraries(new String[] { "com.example.sdk.one" });
+        ps1.setUsesSdkLibrariesVersionsMajor(new long[] { 12 });
+        ps1.setFlags(ps1.getFlags() | ApplicationInfo.FLAG_SYSTEM);
+        settingsUnderTest.mPackages.put(PACKAGE_NAME_1, ps1);
+        assertThat(settingsUnderTest.disableSystemPackageLPw(PACKAGE_NAME_1, false), is(true));
+
+        ps2.setUsesSdkLibraries(new String[] { "com.example.sdk.two" });
+        ps2.setUsesSdkLibrariesVersionsMajor(new long[] { 34 });
+        settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
+
+        settingsUnderTest.writeLPr();
+
+        settingsUnderTest.mPackages.clear();
+        settingsUnderTest.mDisabledSysPackages.clear();
+
+        assertThat(settingsUnderTest.readLPw(createFakeUsers()), is(true));
+
+        PackageSetting readPs1 = settingsUnderTest.getPackageLPr(PACKAGE_NAME_1);
+        PackageSetting readPs2 = settingsUnderTest.getPackageLPr(PACKAGE_NAME_2);
+
+        Truth.assertThat(readPs1).isNotNull();
+        Truth.assertThat(readPs1.getUsesSdkLibraries()).isNotNull();
+        Truth.assertThat(readPs1.getUsesSdkLibrariesVersionsMajor()).isNotNull();
+        Truth.assertThat(readPs2).isNotNull();
+        Truth.assertThat(readPs2.getUsesSdkLibraries()).isNotNull();
+        Truth.assertThat(readPs2.getUsesSdkLibrariesVersionsMajor()).isNotNull();
+
+        List<Long> ps1VersionsAsList = new ArrayList<>();
+        for (long version : ps1.getUsesSdkLibrariesVersionsMajor()) {
+            ps1VersionsAsList.add(version);
+        }
+
+        List<Long> ps2VersionsAsList = new ArrayList<>();
+        for (long version : ps2.getUsesSdkLibrariesVersionsMajor()) {
+            ps2VersionsAsList.add(version);
+        }
+
+        Truth.assertThat(readPs1.getUsesSdkLibraries()).asList()
+                .containsExactlyElementsIn(ps1.getUsesSdkLibraries()).inOrder();
+
+        Truth.assertThat(readPs1.getUsesSdkLibrariesVersionsMajor()).asList()
+                .containsExactlyElementsIn(ps1VersionsAsList).inOrder();
+
+        Truth.assertThat(readPs2.getUsesSdkLibraries()).asList()
+                .containsExactlyElementsIn(ps2.getUsesSdkLibraries()).inOrder();
+
+        Truth.assertThat(readPs2.getUsesSdkLibrariesVersionsMajor()).asList()
+                .containsExactlyElementsIn(ps2VersionsAsList).inOrder();
+    }
+
+    @Test
     public void testPackageRestrictionsDistractionFlagsDefault() {
         final PackageSetting defaultSetting = createPackageSetting(PACKAGE_NAME_1);
         assertThat(defaultSetting.getDistractionFlags(0), is(PackageManager.RESTRICTION_NONE));
@@ -571,6 +636,8 @@
                 ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_HAS_CODE,
                 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED|ApplicationInfo.PRIVATE_FLAG_HIDDEN,
                 0,
+                null /*usesSdkLibraries*/,
+                null /*usesSdkLibrariesVersions*/,
                 null /*usesStaticLibraries*/,
                 null /*usesStaticLibrariesVersions*/,
                 null /*mimeGroups*/,
@@ -593,6 +660,8 @@
                 ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_HAS_CODE,
                 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED|ApplicationInfo.PRIVATE_FLAG_HIDDEN,
                 0,
+                null /*usesSdkLibraries*/,
+                null /*usesSdkLibrariesVersions*/,
                 null /*usesStaticLibraries*/,
                 null /*usesStaticLibrariesVersions*/,
                 null /*mimeGroups*/,
@@ -609,6 +678,8 @@
                 0 /*pkgFlags*/,
                 0 /*pkgPrivateFlags*/,
                 0,
+                null /*usesSdkLibraries*/,
+                null /*usesSdkLibrariesVersions*/,
                 null /*usesStaticLibraries*/,
                 null /*usesStaticLibrariesVersions*/,
                 null /*mimeGroups*/,
@@ -637,6 +708,8 @@
                 0 /*pkgFlags*/,
                 0 /*pkgPrivateFlags*/,
                 UserManagerService.getInstance(),
+                null /*usesSdkLibraries*/,
+                null /*usesSdkLibrariesVersions*/,
                 null /*usesStaticLibraries*/,
                 null /*usesStaticLibrariesVersions*/,
                 null /*mimeGroups*/,
@@ -671,6 +744,8 @@
                 ApplicationInfo.FLAG_SYSTEM /*pkgFlags*/,
                 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED /*pkgPrivateFlags*/,
                 UserManagerService.getInstance(),
+                null /*usesSdkLibraries*/,
+                null /*usesSdkLibrariesVersions*/,
                 null /*usesStaticLibraries*/,
                 null /*usesStaticLibrariesVersions*/,
                 null /*mimeGroups*/,
@@ -708,6 +783,8 @@
                     0 /*pkgFlags*/,
                     0 /*pkgPrivateFlags*/,
                     UserManagerService.getInstance(),
+                    null /*usesSdkLibraries*/,
+                    null /*usesSdkLibrariesVersions*/,
                     null /*usesStaticLibraries*/,
                     null /*usesStaticLibrariesVersions*/,
                     null /*mimeGroups*/,
@@ -741,6 +818,8 @@
                 false /*instantApp*/,
                 false /*virtualPreload*/,
                 UserManagerService.getInstance(),
+                null /*usesSdkLibraries*/,
+                null /*usesSdkLibrariesVersions*/,
                 null /*usesStaticLibraries*/,
                 null /*usesStaticLibrariesVersions*/,
                 null /*mimeGroups*/,
@@ -780,6 +859,8 @@
                 false /*instantApp*/,
                 false /*virtualPreload*/,
                 UserManagerService.getInstance(),
+                null /*usesSdkLibraries*/,
+                null /*usesSdkLibrariesVersions*/,
                 null /*usesStaticLibraries*/,
                 null /*usesStaticLibrariesVersions*/,
                 null /*mimeGroups*/,
@@ -822,6 +903,8 @@
                 false /*instantApp*/,
                 false /*virtualPreload*/,
                 UserManagerService.getInstance(),
+                null /*usesSdkLibraries*/,
+                null /*usesSdkLibrariesVersions*/,
                 null /*usesStaticLibraries*/,
                 null /*usesStaticLibrariesVersions*/,
                 null /*mimeGroups*/,
@@ -864,6 +947,8 @@
                 false /*instantApp*/,
                 false /*virtualPreload*/,
                 UserManagerService.getInstance(),
+                null /*usesSdkLibraries*/,
+                null /*usesSdkLibrariesVersions*/,
                 null /*usesStaticLibraries*/,
                 null /*usesStaticLibrariesVersions*/,
                 null /*mimeGroups*/,
@@ -971,6 +1056,25 @@
         assertThat(countDownLatch.getCount(), is(1L));
     }
 
+    @Test
+    public void testSetPkgStateLibraryFiles_addNewSdks() {
+        final PackageSetting packageSetting = createPackageSetting("com.foo");
+        final CountDownLatch countDownLatch = new CountDownLatch(1);
+        packageSetting.registerObserver(new Watcher() {
+            @Override
+            public void onChange(Watchable what) {
+                countDownLatch.countDown();
+            }
+        });
+
+        final List<String> files = new ArrayList<>();
+        files.add("com.sdk1_123");
+        files.add("com.sdk9_876");
+        packageSetting.setUsesSdkLibraries(files.toArray(new String[files.size()]));
+
+        assertThat(countDownLatch.getCount(), is(0L));
+    }
+
     private <T> void assertArrayEquals(T[] a, T[] b) {
         assertTrue("Expected: " + Arrays.toString(a) + ", actual: " + Arrays.toString(b),
                 Arrays.equals(a, b));
@@ -1090,6 +1194,8 @@
                 pkgFlags,
                 0 /*privateFlags*/,
                 sharedUserId,
+                null /*usesSdkLibraries*/,
+                null /*usesSdkLibrariesVersions*/,
                 null /*usesStaticLibraries*/,
                 null /*usesStaticLibrariesVersions*/,
                 null /*mimeGroups*/,
@@ -1109,6 +1215,8 @@
                 0,
                 0 /*privateFlags*/,
                 0,
+                null /*usesSdkLibraries*/,
+                null /*usesSdkLibrariesVersions*/,
                 null /*usesStaticLibraries*/,
                 null /*usesStaticLibrariesVersions*/,
                 null /*mimeGroups*/,
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index fb092d2..11bac45 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -932,11 +932,12 @@
                 .addUsesPermission(new ParsedUsesPermissionImpl("foo7", 0))
                 .addImplicitPermission("foo25")
                 .addProtectedBroadcast("foo8")
+                .setSdkLibName("sdk12")
+                .setSdkLibVersionMajor(42)
+                .addUsesSdkLibrary("sdk23", 200, new String[]{"digest2"})
                 .setStaticSharedLibName("foo23")
                 .setStaticSharedLibVersion(100)
-                .addUsesStaticLibrary("foo23")
-                .addUsesStaticLibraryCertDigests(new String[]{"digest"})
-                .addUsesStaticLibraryVersion(100)
+                .addUsesStaticLibrary("foo23", 100, new String[]{"digest"})
                 .addLibraryName("foo10")
                 .addUsesLibrary("foo11")
                 .addUsesOptionalLibrary("foo12")
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
index 2146070..94d8358 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
@@ -44,8 +44,6 @@
     private SparseArray<PackageUserStateImpl> mUserStates = new SparseArray<>();
     private AndroidPackage mPkg;
     private InstallSource mInstallSource;
-    private String[] mUsesStaticLibraries;
-    private long[] mUsesStaticLibrariesVersions;
     private Map<String, Set<String>> mMimeGroups;
     private SigningDetails mSigningDetails;
     private UUID mDomainSetId = UUID.randomUUID();
@@ -116,17 +114,6 @@
         return this;
     }
 
-    public PackageSettingBuilder setUsesStaticLibraries(String[] usesStaticLibraries) {
-        this.mUsesStaticLibraries = usesStaticLibraries;
-        return this;
-    }
-
-    public PackageSettingBuilder setUsesStaticLibrariesVersions(
-            long[] usesStaticLibrariesVersions) {
-        this.mUsesStaticLibrariesVersions = usesStaticLibrariesVersions;
-        return this;
-    }
-
     public PackageSettingBuilder setMimeGroups(Map<String, Set<String>> mimeGroups) {
         this.mMimeGroups = mimeGroups;
         return this;
@@ -173,8 +160,9 @@
         final PackageSetting packageSetting = new PackageSetting(mName, mRealName,
                 new File(mCodePath), mLegacyNativeLibraryPathString, mPrimaryCpuAbiString,
                 mSecondaryCpuAbiString, mCpuAbiOverrideString, mPVersionCode, mPkgFlags,
-                mPrivateFlags, mSharedUserId, mUsesStaticLibraries, mUsesStaticLibrariesVersions,
-                mMimeGroups, mDomainSetId);
+                mPrivateFlags, mSharedUserId, null /* usesSdkLibraries */,
+                null /* usesSdkLibrariesVersions */, null /* usesStaticLibraries */,
+                null  /* usesStaticLibrariesVersions */, mMimeGroups, mDomainSetId);
         packageSetting.setSignatures(mSigningDetails != null
                 ? new PackageSignatures(mSigningDetails)
                 : new PackageSignatures());
diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
index cfdbb5b7..71d5b77 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
@@ -17,6 +17,7 @@
 package com.android.server.pm;
 
 import static android.content.pm.SharedLibraryInfo.TYPE_DYNAMIC;
+import static android.content.pm.SharedLibraryInfo.TYPE_SDK;
 import static android.content.pm.SharedLibraryInfo.TYPE_STATIC;
 import static android.content.pm.SharedLibraryInfo.VERSION_UNDEFINED;
 
@@ -238,6 +239,37 @@
     }
 
     @Test
+    public void installSdkLibrary() throws Exception {
+        final ParsedPackage pkg = ((ParsedPackage) createBasicPackage("ogl.sdk_123")
+                .setSdkLibName("ogl.sdk")
+                .setSdkLibVersionMajor(123)
+                .hideAsParsed())
+                .setPackageName("ogl.sdk_123")
+                .setVersionCodeMajor(5)
+                .setVersionCode(678)
+                .setBaseApkPath("/some/path.apk")
+                .setSplitCodePaths(new String[] {"/some/other/path.apk"});
+
+        final ScanRequest scanRequest = new ScanRequestBuilder(pkg)
+                .setUser(UserHandle.of(0)).build();
+
+        final ScanResult scanResult = executeScan(scanRequest);
+
+        assertThat(scanResult.mSdkSharedLibraryInfo.getPackageName(), is("ogl.sdk_123"));
+        assertThat(scanResult.mSdkSharedLibraryInfo.getName(), is("ogl.sdk"));
+        assertThat(scanResult.mSdkSharedLibraryInfo.getLongVersion(), is(123L));
+        assertThat(scanResult.mSdkSharedLibraryInfo.getType(), is(TYPE_SDK));
+        assertThat(scanResult.mSdkSharedLibraryInfo.getDeclaringPackage().getPackageName(),
+                is("ogl.sdk_123"));
+        assertThat(scanResult.mSdkSharedLibraryInfo.getDeclaringPackage().getLongVersionCode(),
+                is(pkg.getLongVersionCode()));
+        assertThat(scanResult.mSdkSharedLibraryInfo.getAllCodePaths(),
+                hasItems("/some/path.apk", "/some/other/path.apk"));
+        assertThat(scanResult.mSdkSharedLibraryInfo.getDependencies(), nullValue());
+        assertThat(scanResult.mSdkSharedLibraryInfo.getDependentPackages(), empty());
+    }
+
+    @Test
     public void installStaticSharedLibrary() throws Exception {
         final ParsedPackage pkg = ((ParsedPackage) createBasicPackage("static.lib.pkg")
                 .setStaticSharedLibName("static.lib")
@@ -528,10 +560,10 @@
                 "/data/tmp/randompath/base.apk", createCodePath(packageName),
                 mock(TypedArray.class), false)
                 .setVolumeUuid(UUID_ONE.toString())
-                .addUsesStaticLibrary("some.static.library")
-                .addUsesStaticLibraryVersion(234L)
-                .addUsesStaticLibrary("some.other.static.library")
-                .addUsesStaticLibraryVersion(456L)
+                .addUsesStaticLibrary("some.static.library", 234L, new String[]{"testCert1"})
+                .addUsesStaticLibrary("some.other.static.library", 456L, new String[]{"testCert2"})
+                .addUsesSdkLibrary("some.sdk.library", 123L, new String[]{"testCert3"})
+                .addUsesSdkLibrary("some.other.sdk.library", 789L, new String[]{"testCert4"})
                 .hideAsParsed())
                 .setNativeLibraryRootDir("/data/tmp/randompath/base.apk:/lib")
                 .setVersionCodeMajor(1)
@@ -557,6 +589,9 @@
         assertThat(pkgSetting.getUsesStaticLibraries(),
                 arrayContaining("some.static.library", "some.other.static.library"));
         assertThat(pkgSetting.getUsesStaticLibrariesVersions(), is(new long[]{234L, 456L}));
+        assertThat(pkgSetting.getUsesSdkLibraries(),
+                arrayContaining("some.sdk.library", "some.other.sdk.library"));
+        assertThat(pkgSetting.getUsesSdkLibrariesVersionsMajor(), is(new long[]{123L, 789L}));
         assertThat(pkgSetting.getPkg(), is(scanResult.mRequest.mParsedPackage));
         assertThat(pkgSetting.getPath(), is(new File(createCodePath(packageName))));
         assertThat(pkgSetting.getVersionCode(),
diff --git a/tools/aapt2/dump/DumpManifest.cpp b/tools/aapt2/dump/DumpManifest.cpp
index 40bbb36..9828b97 100644
--- a/tools/aapt2/dump/DumpManifest.cpp
+++ b/tools/aapt2/dump/DumpManifest.cpp
@@ -1461,6 +1461,64 @@
   }
 };
 
+/** Represents <sdk-library> elements. **/
+class SdkLibrary : public ManifestExtractor::Element {
+ public:
+  SdkLibrary() = default;
+  std::string name;
+  int versionMajor;
+
+  void Extract(xml::Element* element) override {
+    auto parent_stack = extractor()->parent_stack();
+    if (parent_stack.size() > 0 && ElementCast<Application>(parent_stack[0])) {
+      name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
+      versionMajor = GetAttributeIntegerDefault(FindAttribute(element, VERSION_MAJOR_ATTR), 0);
+    }
+  }
+
+  void Print(text::Printer* printer) override {
+    printer->Print(
+        StringPrintf("sdk-library: name='%s' versionMajor='%d'\n", name.data(), versionMajor));
+  }
+};
+
+/** Represents <uses-sdk-library> elements. **/
+class UsesSdkLibrary : public ManifestExtractor::Element {
+ public:
+  UsesSdkLibrary() = default;
+  std::string name;
+  int versionMajor;
+  std::vector<std::string> certDigests;
+
+  void Extract(xml::Element* element) override {
+    auto parent_stack = extractor()->parent_stack();
+    if (parent_stack.size() > 0 && ElementCast<Application>(parent_stack[0])) {
+      name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
+      versionMajor = GetAttributeIntegerDefault(FindAttribute(element, VERSION_MAJOR_ATTR), 0);
+      AddCertDigest(element);
+    }
+  }
+
+  void AddCertDigest(xml::Element* element) {
+    std::string digest = GetAttributeStringDefault(FindAttribute(element, CERT_DIGEST_ATTR), "");
+    // We allow ":" delimiters in the SHA declaration as this is the format
+    // emitted by the certtool making it easy for developers to copy/paste.
+    digest.erase(std::remove(digest.begin(), digest.end(), ':'), digest.end());
+    if (!digest.empty()) {
+      certDigests.push_back(digest);
+    }
+  }
+
+  void Print(text::Printer* printer) override {
+    printer->Print(
+        StringPrintf("uses-sdk-library: name='%s' versionMajor='%d'", name.data(), versionMajor));
+    for (size_t i = 0; i < certDigests.size(); i++) {
+      printer->Print(StringPrintf(" certDigest='%s'", certDigests[i].data()));
+    }
+    printer->Print("\n");
+  }
+};
+
 /** Represents <uses-native-library> elements. **/
 class UsesNativeLibrary : public ManifestExtractor::Element {
  public:
@@ -2367,6 +2425,7 @@
       {"required-not-feature", std::is_base_of<RequiredNotFeature, T>::value},
       {"screen", std::is_base_of<Screen, T>::value},
       {"service", std::is_base_of<Service, T>::value},
+      {"sdk-library", std::is_base_of<SdkLibrary, T>::value},
       {"static-library", std::is_base_of<StaticLibrary, T>::value},
       {"supports-gl-texture", std::is_base_of<SupportsGlTexture, T>::value},
       {"supports-input", std::is_base_of<SupportsInput, T>::value},
@@ -2379,6 +2438,7 @@
       {"uses-permission", std::is_base_of<UsesPermission, T>::value},
       {"uses-permission-sdk-23", std::is_base_of<UsesPermissionSdk23, T>::value},
       {"uses-sdk", std::is_base_of<UsesSdkBadging, T>::value},
+      {"uses-sdk-library", std::is_base_of<UsesSdkLibrary, T>::value},
       {"uses-static-library", std::is_base_of<UsesStaticLibrary, T>::value},
   };
 
@@ -2421,6 +2481,7 @@
           {"required-not-feature", &CreateType<RequiredNotFeature>},
           {"screen", &CreateType<Screen>},
           {"service", &CreateType<Service>},
+          {"sdk-library", &CreateType<SdkLibrary>},
           {"static-library", &CreateType<StaticLibrary>},
           {"supports-gl-texture", &CreateType<SupportsGlTexture>},
           {"supports-input", &CreateType<SupportsInput>},
@@ -2433,6 +2494,7 @@
           {"uses-permission", &CreateType<UsesPermission>},
           {"uses-permission-sdk-23", &CreateType<UsesPermissionSdk23>},
           {"uses-sdk", &CreateType<UsesSdkBadging>},
+          {"uses-sdk-library", &CreateType<UsesSdkLibrary>},
           {"uses-static-library", &CreateType<UsesStaticLibrary>},
       };
 
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 63b2fcd..b46a125 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -508,6 +508,16 @@
   uses_static_library_action.Action(RequiredAndroidAttribute("certDigest"));
   uses_static_library_action["additional-certificate"];
 
+  xml::XmlNodeAction& sdk_library_action = application_action["sdk-library"];
+  sdk_library_action.Action(RequiredNameIsJavaPackage);
+  sdk_library_action.Action(RequiredAndroidAttribute("versionMajor"));
+
+  xml::XmlNodeAction& uses_sdk_library_action = application_action["uses-sdk-library"];
+  uses_sdk_library_action.Action(RequiredNameIsJavaPackage);
+  uses_sdk_library_action.Action(RequiredAndroidAttribute("versionMajor"));
+  uses_sdk_library_action.Action(RequiredAndroidAttribute("certDigest"));
+  uses_sdk_library_action["additional-certificate"];
+
   xml::XmlNodeAction& uses_package_action = application_action["uses-package"];
   uses_package_action.Action(RequiredNameIsJavaPackage);
   uses_package_action["additional-certificate"];