Platform support for static shared libraries

This change adds support for static shared libraries that
emulate static linking allowing apps that statically link
against the same library version to share a common
implementation. A library is hosed by a package in a standard
APK.

Static shared libraries have a name and a version declared
by a dedicated manifest tag. A client uses also a new tag
to refer to the static library it uses by specifying the
lib name, version, and the hash of the signing certificate.
This allows two apps to rely on two different library versions
and prevents impersonation of the shared library by a side-loaded
app with the same package name.

Internally apps providing static libs use synthetic package
name generated from the manifest package name and the library
version. This allows having different "versions" of the same
package installed at the same time.

An application cannot be installed if a static shared lib it
depends on is missing. A used shared library cannot be uninstalled.
Shared libraries can rotate certificates like normal apps. The
versions of these libs should be ordered similarly to the version
codes of the hosting package. Such libs cannot use shared user
id, cannot be ephemeral, cannot declare other libraries, cannot
rename their package, cannot declare child-packages. They must
target O SDK. Also they cannot be suspended or hidden or their
uninstall blocked. Generally, speaking policy regarding code in
static shared libs should be applied to the packages using the
library as it could have just statically linked the code.

We now have APIs to query information about the shared libraries
on the device in general. To clients static shared libraries are
presented as multiple versions of the same package which is how
they are declared and published. Therefore, one can have two
versions of the same package which means we need way to query
for and uninstall a specific version of a package. Also static
shared libs can depend on other static shared libs which are
versioned packages. To ease representation we add the concept
of a versioned package which should be used in the case of
static shared libs.

A client can see only the static shared libs it depends on and
more specifically only the versions it depends would be retrieved
by using the standard package manager APIs. There is a new
dedicated API to get info about all shared libraries which
would provide data about all static shared lib versions. Also
these libraries must use v2 signing scheme.

Test: CTS tests pass

bug:30974070

Change-Id: I4f3d537ee7a81f880950377b996e1d9d4813da5c
diff --git a/api/current.txt b/api/current.txt
index 725f1f0..5795575 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -114,6 +114,7 @@
     field public static final java.lang.String RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH";
     field public static final java.lang.String RECORD_AUDIO = "android.permission.RECORD_AUDIO";
     field public static final java.lang.String REORDER_TASKS = "android.permission.REORDER_TASKS";
+    field public static final java.lang.String REQUEST_DELETE_PACKAGES = "android.permission.REQUEST_DELETE_PACKAGES";
     field public static final java.lang.String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
     field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
     field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
@@ -362,6 +363,7 @@
     field public static final int centerMedium = 16842959; // 0x10100cf
     field public static final int centerX = 16843170; // 0x10101a2
     field public static final int centerY = 16843171; // 0x10101a3
+    field public static final int certDigest = 16844106; // 0x101054a
     field public static final int checkBoxPreferenceStyle = 16842895; // 0x101008f
     field public static final int checkMark = 16843016; // 0x1010108
     field public static final int checkMarkTint = 16843943; // 0x10104a7
@@ -9935,6 +9937,7 @@
     method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
     method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback, android.os.Handler);
     method public void uninstall(java.lang.String, android.content.IntentSender);
+    method public void uninstall(android.content.pm.VersionedPackage, android.content.IntentSender);
     method public void unregisterSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
     method public void updateSessionAppIcon(int, android.graphics.Bitmap);
     method public void updateSessionAppLabel(int, java.lang.CharSequence);
@@ -10081,6 +10084,7 @@
     method public abstract int[] getPackageGids(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract int[] getPackageGids(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.pm.PackageInfo getPackageInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.pm.PackageInfo getPackageInfo(android.content.pm.VersionedPackage, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.pm.PackageInstaller getPackageInstaller();
     method public abstract int getPackageUid(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract java.lang.String[] getPackagesForUid(int);
@@ -10095,6 +10099,7 @@
     method public abstract android.content.res.Resources getResourcesForApplication(android.content.pm.ApplicationInfo) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.res.Resources getResourcesForApplication(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.pm.ServiceInfo getServiceInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(int);
     method public abstract android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
     method public abstract java.lang.String[] getSystemSharedLibraryNames();
     method public abstract java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
@@ -10253,6 +10258,7 @@
     field public static final int SIGNATURE_UNKNOWN_PACKAGE = -4; // 0xfffffffc
     field public static final int VERIFICATION_ALLOW = 1; // 0x1
     field public static final int VERIFICATION_REJECT = -1; // 0xffffffff
+    field public static final int VERSION_CODE_HIGHEST = -1; // 0xffffffff
   }
 
   public static class PackageManager.NameNotFoundException extends android.util.AndroidException {
@@ -10392,6 +10398,20 @@
     field public java.lang.String permission;
   }
 
+  public final class SharedLibraryInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.content.pm.VersionedPackage getDeclaringPackage();
+    method public java.util.List<android.content.pm.VersionedPackage> getDependentPackages();
+    method public java.lang.String getName();
+    method public int getVersion();
+    method public boolean isBuiltin();
+    method public boolean isDynamic();
+    method public boolean isStatic();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.SharedLibraryInfo> CREATOR;
+    field public static final int VERSION_UNDEFINED = -1; // 0xffffffff
+  }
+
   public final class ShortcutInfo implements android.os.Parcelable {
     method public int describeContents();
     method public android.content.ComponentName getActivity();
@@ -10467,6 +10487,15 @@
     field public static final android.os.Parcelable.Creator<android.content.pm.Signature> CREATOR;
   }
 
+  public final class VersionedPackage implements android.os.Parcelable {
+    ctor public VersionedPackage(java.lang.String, int);
+    method public int describeContents();
+    method public java.lang.String getPackageName();
+    method public long getVersionCode();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.VersionedPackage> CREATOR;
+  }
+
 }
 
 package android.content.res {
@@ -39175,6 +39204,7 @@
     method public int[] getPackageGids(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public int[] getPackageGids(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public android.content.pm.PackageInfo getPackageInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.PackageInfo getPackageInfo(android.content.pm.VersionedPackage, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public android.content.pm.PackageInstaller getPackageInstaller();
     method public int getPackageUid(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] getPackagesForUid(int);
@@ -39189,6 +39219,7 @@
     method public android.content.res.Resources getResourcesForApplication(android.content.pm.ApplicationInfo);
     method public android.content.res.Resources getResourcesForApplication(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public android.content.pm.ServiceInfo getServiceInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(int);
     method public android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
     method public java.lang.String[] getSystemSharedLibraryNames();
     method public java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
diff --git a/api/system-current.txt b/api/system-current.txt
index 0b5040a..37fca36 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -200,6 +200,7 @@
     field public static final java.lang.String REGISTER_SIM_SUBSCRIPTION = "android.permission.REGISTER_SIM_SUBSCRIPTION";
     field public static final java.lang.String REMOVE_DRM_CERTIFICATES = "android.permission.REMOVE_DRM_CERTIFICATES";
     field public static final java.lang.String REORDER_TASKS = "android.permission.REORDER_TASKS";
+    field public static final java.lang.String REQUEST_DELETE_PACKAGES = "android.permission.REQUEST_DELETE_PACKAGES";
     field public static final java.lang.String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
     field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
     field public static final java.lang.String REQUEST_NETWORK_SCORES = "android.permission.REQUEST_NETWORK_SCORES";
@@ -471,6 +472,7 @@
     field public static final int centerMedium = 16842959; // 0x10100cf
     field public static final int centerX = 16843170; // 0x10101a2
     field public static final int centerY = 16843171; // 0x10101a3
+    field public static final int certDigest = 16844106; // 0x101054a
     field public static final int checkBoxPreferenceStyle = 16842895; // 0x101008f
     field public static final int checkMark = 16843016; // 0x1010108
     field public static final int checkMarkTint = 16843943; // 0x10104a7
@@ -10369,6 +10371,7 @@
     method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
     method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback, android.os.Handler);
     method public void uninstall(java.lang.String, android.content.IntentSender);
+    method public void uninstall(android.content.pm.VersionedPackage, android.content.IntentSender);
     method public void unregisterSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
     method public void updateSessionAppIcon(int, android.graphics.Bitmap);
     method public void updateSessionAppLabel(int, java.lang.CharSequence);
@@ -10522,6 +10525,7 @@
     method public abstract int[] getPackageGids(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract int[] getPackageGids(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.pm.PackageInfo getPackageInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.pm.PackageInfo getPackageInfo(android.content.pm.VersionedPackage, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.pm.PackageInstaller getPackageInstaller();
     method public abstract int getPackageUid(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract java.lang.String[] getPackagesForUid(int);
@@ -10537,6 +10541,7 @@
     method public abstract android.content.res.Resources getResourcesForApplication(android.content.pm.ApplicationInfo) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.res.Resources getResourcesForApplication(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.pm.ServiceInfo getServiceInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(int);
     method public abstract android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
     method public abstract java.lang.String[] getSystemSharedLibraryNames();
     method public abstract java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
@@ -10752,6 +10757,7 @@
     field public static final int SIGNATURE_UNKNOWN_PACKAGE = -4; // 0xfffffffc
     field public static final int VERIFICATION_ALLOW = 1; // 0x1
     field public static final int VERIFICATION_REJECT = -1; // 0xffffffff
+    field public static final int VERSION_CODE_HIGHEST = -1; // 0xffffffff
   }
 
   public static class PackageManager.NameNotFoundException extends android.util.AndroidException {
@@ -10900,6 +10906,20 @@
     field public java.lang.String permission;
   }
 
+  public final class SharedLibraryInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.content.pm.VersionedPackage getDeclaringPackage();
+    method public java.util.List<android.content.pm.VersionedPackage> getDependentPackages();
+    method public java.lang.String getName();
+    method public int getVersion();
+    method public boolean isBuiltin();
+    method public boolean isDynamic();
+    method public boolean isStatic();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.SharedLibraryInfo> CREATOR;
+    field public static final int VERSION_UNDEFINED = -1; // 0xffffffff
+  }
+
   public final class ShortcutInfo implements android.os.Parcelable {
     method public int describeContents();
     method public android.content.ComponentName getActivity();
@@ -10975,6 +10995,15 @@
     field public static final android.os.Parcelable.Creator<android.content.pm.Signature> CREATOR;
   }
 
+  public final class VersionedPackage implements android.os.Parcelable {
+    ctor public VersionedPackage(java.lang.String, int);
+    method public int describeContents();
+    method public java.lang.String getPackageName();
+    method public long getVersionCode();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.VersionedPackage> CREATOR;
+  }
+
 }
 
 package android.content.pm.permission {
@@ -42444,6 +42473,7 @@
     method public int[] getPackageGids(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public int[] getPackageGids(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public android.content.pm.PackageInfo getPackageInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.PackageInfo getPackageInfo(android.content.pm.VersionedPackage, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public android.content.pm.PackageInstaller getPackageInstaller();
     method public int getPackageUid(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] getPackagesForUid(int);
@@ -42459,6 +42489,7 @@
     method public android.content.res.Resources getResourcesForApplication(android.content.pm.ApplicationInfo);
     method public android.content.res.Resources getResourcesForApplication(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public android.content.pm.ServiceInfo getServiceInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(int);
     method public android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
     method public java.lang.String[] getSystemSharedLibraryNames();
     method public java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
diff --git a/api/test-current.txt b/api/test-current.txt
index f521232..66071a2 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -114,6 +114,7 @@
     field public static final java.lang.String RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH";
     field public static final java.lang.String RECORD_AUDIO = "android.permission.RECORD_AUDIO";
     field public static final java.lang.String REORDER_TASKS = "android.permission.REORDER_TASKS";
+    field public static final java.lang.String REQUEST_DELETE_PACKAGES = "android.permission.REQUEST_DELETE_PACKAGES";
     field public static final java.lang.String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
     field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
     field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
@@ -362,6 +363,7 @@
     field public static final int centerMedium = 16842959; // 0x10100cf
     field public static final int centerX = 16843170; // 0x10101a2
     field public static final int centerY = 16843171; // 0x10101a3
+    field public static final int certDigest = 16844106; // 0x101054a
     field public static final int checkBoxPreferenceStyle = 16842895; // 0x101008f
     field public static final int checkMark = 16843016; // 0x1010108
     field public static final int checkMarkTint = 16843943; // 0x10104a7
@@ -9963,6 +9965,7 @@
     method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
     method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback, android.os.Handler);
     method public void uninstall(java.lang.String, android.content.IntentSender);
+    method public void uninstall(android.content.pm.VersionedPackage, android.content.IntentSender);
     method public void unregisterSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
     method public void updateSessionAppIcon(int, android.graphics.Bitmap);
     method public void updateSessionAppLabel(int, java.lang.CharSequence);
@@ -10111,6 +10114,7 @@
     method public abstract int[] getPackageGids(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract int[] getPackageGids(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.pm.PackageInfo getPackageInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.pm.PackageInfo getPackageInfo(android.content.pm.VersionedPackage, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.pm.PackageInstaller getPackageInstaller();
     method public abstract int getPackageUid(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract java.lang.String[] getPackagesForUid(int);
@@ -10125,6 +10129,7 @@
     method public abstract android.content.res.Resources getResourcesForApplication(android.content.pm.ApplicationInfo) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.res.Resources getResourcesForApplication(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.pm.ServiceInfo getServiceInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(int);
     method public abstract android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
     method public abstract java.lang.String[] getSystemSharedLibraryNames();
     method public abstract java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
@@ -10283,6 +10288,7 @@
     field public static final int SIGNATURE_UNKNOWN_PACKAGE = -4; // 0xfffffffc
     field public static final int VERIFICATION_ALLOW = 1; // 0x1
     field public static final int VERIFICATION_REJECT = -1; // 0xffffffff
+    field public static final int VERSION_CODE_HIGHEST = -1; // 0xffffffff
   }
 
   public static class PackageManager.NameNotFoundException extends android.util.AndroidException {
@@ -10423,6 +10429,20 @@
     field public java.lang.String permission;
   }
 
+  public final class SharedLibraryInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.content.pm.VersionedPackage getDeclaringPackage();
+    method public java.util.List<android.content.pm.VersionedPackage> getDependentPackages();
+    method public java.lang.String getName();
+    method public int getVersion();
+    method public boolean isBuiltin();
+    method public boolean isDynamic();
+    method public boolean isStatic();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.SharedLibraryInfo> CREATOR;
+    field public static final int VERSION_UNDEFINED = -1; // 0xffffffff
+  }
+
   public final class ShortcutInfo implements android.os.Parcelable {
     method public int describeContents();
     method public android.content.ComponentName getActivity();
@@ -10499,6 +10519,15 @@
     field public static final android.os.Parcelable.Creator<android.content.pm.Signature> CREATOR;
   }
 
+  public final class VersionedPackage implements android.os.Parcelable {
+    ctor public VersionedPackage(java.lang.String, int);
+    method public int describeContents();
+    method public java.lang.String getPackageName();
+    method public long getVersionCode();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.content.pm.VersionedPackage> CREATOR;
+  }
+
 }
 
 package android.content.res {
@@ -39299,6 +39328,7 @@
     method public int[] getPackageGids(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public int[] getPackageGids(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public android.content.pm.PackageInfo getPackageInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public android.content.pm.PackageInfo getPackageInfo(android.content.pm.VersionedPackage, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public android.content.pm.PackageInstaller getPackageInstaller();
     method public int getPackageUid(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public java.lang.String[] getPackagesForUid(int);
@@ -39313,6 +39343,7 @@
     method public android.content.res.Resources getResourcesForApplication(android.content.pm.ApplicationInfo);
     method public android.content.res.Resources getResourcesForApplication(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public android.content.pm.ServiceInfo getServiceInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(int);
     method public android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
     method public java.lang.String[] getSystemSharedLibraryNames();
     method public java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 810d201..ac5fea3 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -1556,7 +1556,7 @@
         System.err.println("       pm install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH]");
         System.err.println("       pm install-commit SESSION_ID");
         System.err.println("       pm install-abandon SESSION_ID");
-        System.err.println("       pm uninstall [-k] [--user USER_ID] PACKAGE");
+        System.err.println("       pm uninstall [-k] [--user USER_ID] [--versionCode VERSION_CODE] PACKAGE");
         System.err.println("       pm set-installer PACKAGE INSTALLER");
         System.err.println("       pm move-package PACKAGE [internal|UUID]");
         System.err.println("       pm move-primary-storage [internal|UUID]");
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 20f7e63..f790542 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -17,11 +17,11 @@
 package android.app;
 
 import android.annotation.DrawableRes;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StringRes;
 import android.annotation.XmlRes;
-import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -53,13 +53,13 @@
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.content.pm.UserInfo;
+import android.content.pm.SharedLibraryInfo;
 import android.content.pm.VerifierDeviceIdentity;
+import android.content.pm.VersionedPackage;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
@@ -137,6 +137,21 @@
     }
 
     @Override
+    public PackageInfo getPackageInfo(VersionedPackage versionedPackage, int flags)
+            throws NameNotFoundException {
+        try {
+            PackageInfo pi = mPM.getPackageInfoVersioned(versionedPackage, flags,
+                    mContext.getUserId());
+            if (pi != null) {
+                return pi;
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+        throw new NameNotFoundException(versionedPackage.toString());
+    }
+
+    @Override
     public PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId)
             throws NameNotFoundException {
         try {
@@ -147,7 +162,6 @@
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
-
         throw new NameNotFoundException(packageName);
     }
 
@@ -445,6 +459,28 @@
 
     /** @hide */
     @Override
+    public @NonNull List<SharedLibraryInfo> getSharedLibraries(int flags) {
+        return getSharedLibrariesAsUser(flags, mContext.getUserId());
+    }
+
+    /** @hide */
+    @Override
+    @SuppressWarnings("unchecked")
+    public @NonNull List<SharedLibraryInfo> getSharedLibrariesAsUser(int flags, int userId) {
+        try {
+            ParceledListSlice<SharedLibraryInfo> sharedLibs = mPM.getSharedLibraries(
+                    flags, userId);
+            if (sharedLibs == null) {
+                return Collections.emptyList();
+            }
+            return sharedLibs.getList();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** @hide */
+    @Override
     public @NonNull String getServicesSystemSharedLibraryPackageName() {
         try {
             return mPM.getServicesSystemSharedLibraryPackageName();
@@ -1977,10 +2013,11 @@
     }
 
     @Override
-    public void deletePackageAsUser(String packageName, IPackageDeleteObserver observer, int flags,
-            int userId) {
+    public void deletePackageAsUser(String packageName, IPackageDeleteObserver observer,
+            int flags, int userId) {
         try {
-            mPM.deletePackageAsUser(packageName, observer, userId, flags);
+            mPM.deletePackageAsUser(packageName, PackageManager.VERSION_CODE_HIGHEST,
+                    observer, userId, flags);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -2303,7 +2340,7 @@
         synchronized (mLock) {
             if (mInstaller == null) {
                 try {
-                    mInstaller = new PackageInstaller(mContext, this, mPM.getPackageInstaller(),
+                    mInstaller = new PackageInstaller(mPM.getPackageInstaller(),
                             mContext.getPackageName(), mContext.getUserId());
                 } catch (RemoteException e) {
                     throw e.rethrowFromSystemServer();
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 71071e1..04ab239 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -551,6 +551,13 @@
     public static final int PRIVATE_FLAG_BACKUP_IN_FOREGROUND = 1 << 12;
 
     /**
+     * Value for {@link #privateFlags}: {@code true} means this application
+     * contains a static shared library. Defaults to {@code false} if unspecified.
+     * @hide
+     */
+    public static final int PRIVATE_FLAG_STATIC_SHARED_LIBRARY = 1 << 13;
+
+    /**
      * Private/hidden flags. See {@code PRIVATE_FLAG_...} constants.
      * {@hide}
      */
@@ -1358,6 +1365,13 @@
     /**
      * @hide
      */
+    public boolean isStaticSharedLibrary() {
+        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY) != 0;
+    }
+
+    /**
+     * @hide
+     */
     @Override protected ApplicationInfo getApplicationInfo() {
         return this;
     }
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index 154ff85..ecc8cd6 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -21,6 +21,7 @@
 import android.content.pm.IPackageInstallerSession;
 import android.content.pm.PackageInstaller;
 import android.content.pm.ParceledListSlice;
+import android.content.pm.VersionedPackage;
 import android.content.IntentSender;
 
 import android.graphics.Bitmap;
@@ -44,7 +45,7 @@
     void registerCallback(IPackageInstallerCallback callback, int userId);
     void unregisterCallback(IPackageInstallerCallback callback);
 
-    void uninstall(String packageName, String callerPackageName, int flags,
+    void uninstall(in VersionedPackage versionedPackage, String callerPackageName, int flags,
             in IntentSender statusReceiver, int userId);
 
     void setPermissionsResult(int sessionId, boolean accepted);
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 01f4e00..ab9af5a 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -47,6 +47,7 @@
 import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
 import android.content.pm.VerifierDeviceIdentity;
+import android.content.pm.VersionedPackage;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Bundle;
@@ -63,6 +64,8 @@
     void checkPackageStartable(String packageName, int userId);
     boolean isPackageAvailable(String packageName, int userId);
     PackageInfo getPackageInfo(String packageName, int flags, int userId);
+    PackageInfo getPackageInfoVersioned(in VersionedPackage versionedPackage,
+            int flags, int userId);
     int getPackageUid(String packageName, int flags, int userId);
     int[] getPackageGids(String packageName, int flags, int userId);
 
@@ -231,18 +234,19 @@
     void setApplicationCategoryHint(String packageName, int categoryHint, String callerPackageName);
 
     /** @deprecated rawr, don't call AIDL methods directly! */
-    void deletePackageAsUser(in String packageName, IPackageDeleteObserver observer,
-            int userId, int flags);
+    void deletePackageAsUser(in String packageName, int versionCode,
+            IPackageDeleteObserver observer, int userId, int flags);
 
     /**
      * Delete a package for a specific user.
      *
-     * @param packageName The fully qualified name of the package to delete.
+     * @param versionedPackage The package to delete.
      * @param observer a callback to use to notify when the package deletion in finished.
      * @param userId the id of the user for whom to delete the package
      * @param flags - possible values: {@link #DONT_DELETE_DATA}
      */
-    void deletePackage(in String packageName, IPackageDeleteObserver2 observer, int userId, int flags);
+    void deletePackageVersioned(in VersionedPackage versionedPackage,
+            IPackageDeleteObserver2 observer, int userId, int flags);
 
     String getInstallerPackageName(in String packageName);
 
@@ -588,4 +592,6 @@
     List<String> getPreviousCodePaths(in String packageName);
 
     int getInstallReason(String packageName, int userId);
+
+    ParceledListSlice getSharedLibraries(int flags, int userId);
 }
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index d40bab5..5d5696b 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -142,7 +142,7 @@
      * {@link PackageManager#GET_INSTRUMENTATION} was set.
      */
     public InstrumentationInfo[] instrumentation;
-    
+
     /**
      * Array of all {@link android.R.styleable#AndroidManifestPermission
      * &lt;permission&gt;} tags included under &lt;manifest&gt;,
@@ -150,7 +150,7 @@
      * {@link PackageManager#GET_PERMISSIONS} was set.
      */
     public PermissionInfo[] permissions;
-    
+
     /**
      * Array of all {@link android.R.styleable#AndroidManifestUsesPermission
      * &lt;uses-permission&gt;} tags included under &lt;manifest&gt;,
@@ -160,7 +160,7 @@
      * by the system at install time.
      */
     public String[] requestedPermissions;
-    
+
     /**
      * Array of flags of all {@link android.R.styleable#AndroidManifestUsesPermission
      * &lt;uses-permission&gt;} tags included under &lt;manifest&gt;,
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index db3f637..4de967c 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -23,7 +24,6 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
 import android.app.ActivityManager;
-import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
 import android.graphics.Bitmap;
@@ -36,9 +36,11 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
 import android.os.RemoteException;
+import android.annotation.IntRange;
 import android.util.ExceptionUtils;
 
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.Preconditions;
 
 import java.io.Closeable;
 import java.io.IOException;
@@ -256,8 +258,6 @@
      */
     public static final int STATUS_FAILURE_INCOMPATIBLE = 7;
 
-    private final Context mContext;
-    private final PackageManager mPm;
     private final IPackageInstaller mInstaller;
     private final int mUserId;
     private final String mInstallerPackageName;
@@ -265,10 +265,8 @@
     private final ArrayList<SessionCallbackDelegate> mDelegates = new ArrayList<>();
 
     /** {@hide} */
-    public PackageInstaller(Context context, PackageManager pm, IPackageInstaller installer,
+    public PackageInstaller(IPackageInstaller installer,
             String installerPackageName, int userId) {
-        mContext = context;
-        mPm = pm;
         mInstaller = installer;
         mInstallerPackageName = installerPackageName;
         mUserId = userId;
@@ -413,10 +411,35 @@
      * Uninstall the given package, removing it completely from the device. This
      * method is only available to the current "installer of record" for the
      * package.
+     *
+     * @param packageName The package to uninstall.
+     * @param statusReceiver Where to deliver the result.
      */
     public void uninstall(@NonNull String packageName, @NonNull IntentSender statusReceiver) {
+       uninstall(new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST),
+               statusReceiver);
+    }
+
+    /**
+     * Uninstall the given package with a specific version code, removing it
+     * completely from the device. This method is only available to the current
+     * "installer of record" for the package. If the version code of the package
+     * does not match the one passed in the versioned package argument this
+     * method is a no-op. Use {@link PackageManager#VERSION_CODE_HIGHEST} to
+     * uninstall the latest version of the package.
+     *
+     * @param versionedPackage The versioned package to uninstall.
+     * @param statusReceiver Where to deliver the result.
+     */
+    @RequiresPermission(anyOf = {
+            Manifest.permission.DELETE_PACKAGES,
+            Manifest.permission.REQUEST_DELETE_PACKAGES})
+    public void uninstall(@NonNull VersionedPackage versionedPackage,
+            @NonNull IntentSender statusReceiver) {
+        Preconditions.checkNotNull(versionedPackage, "versionedPackage cannot be null");
         try {
-            mInstaller.uninstall(packageName, mInstallerPackageName, 0, statusReceiver, mUserId);
+            mInstaller.uninstall(versionedPackage, mInstallerPackageName,
+                    0, statusReceiver, mUserId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index bc79f41..11830c2 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -24,14 +24,10 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.UserHandle;
-import android.text.BidiFormatter;
 import android.text.Html;
 import android.text.TextPaint;
 import android.text.TextUtils;
 import android.util.Printer;
-import android.text.BidiFormatter;
-import android.text.TextPaint;
-import android.text.Html;
 import java.text.Collator;
 import java.util.Comparator;
 
@@ -50,31 +46,31 @@
      * Public name of this item. From the "android:name" attribute.
      */
     public String name;
-    
+
     /**
      * Name of the package that this item is in.
      */
     public String packageName;
-    
+
     /**
      * A string resource identifier (in the package's resources) of this
      * component's label.  From the "label" attribute or, if not set, 0.
      */
     public int labelRes;
-    
+
     /**
      * The string provided in the AndroidManifest file, if any.  You
      * probably don't want to use this.  You probably want
      * {@link PackageManager#getApplicationLabel}
      */
     public CharSequence nonLocalizedLabel;
-    
+
     /**
      * A drawable resource identifier (in the package's resources) of this
      * component's icon.  From the "icon" attribute or, if not set, 0.
      */
     public int icon;
-    
+
     /**
      * A drawable resource identifier (in the package's resources) of this
      * component's banner.  From the "banner" attribute or, if not set, 0.
@@ -85,10 +81,10 @@
      * A drawable resource identifier (in the package's resources) of this
      * component's logo. Logos may be larger/wider than icons and are
      * displayed by certain UI elements in place of a name or name/icon
-     * combination. From the "logo" attribute or, if not set, 0. 
+     * combination. From the "logo" attribute or, if not set, 0.
      */
     public int logo;
-    
+
     /**
      * Additional meta-data associated with this component.  This field
      * will only be filled in if you set the
@@ -124,10 +120,10 @@
      * Retrieve the current textual label associated with this item.  This
      * will call back on the given PackageManager to load the label from
      * the application.
-     * 
+     *
      * @param pm A PackageManager from which the label can be loaded; usually
      * the PackageManager from which you originally retrieved this item.
-     * 
+     *
      * @return Returns a CharSequence containing the item's label.  If the
      * item does not have a label, its name is returned.
      */
@@ -146,7 +142,7 @@
         }
         return packageName;
     }
- 
+
     /**
      * Same as {@link #loadLabel(PackageManager)} with the addition that
      * the returned label is safe for being presented in the UI since it
@@ -207,10 +203,10 @@
      * Retrieve the current graphical icon associated with this item.  This
      * will call back on the given PackageManager to load the icon from
      * the application.
-     * 
+     *
      * @param pm A PackageManager from which the icon can be loaded; usually
      * the PackageManager from which you originally retrieved this item.
-     * 
+     *
      * @return Returns a Drawable containing the item's icon.  If the
      * item does not have an icon, the item's default icon is returned
      * such as the default activity icon.
@@ -259,13 +255,13 @@
 
     /**
      * Retrieve the default graphical icon associated with this item.
-     * 
+     *
      * @param pm A PackageManager from which the icon can be loaded; usually
      * the PackageManager from which you originally retrieved this item.
-     * 
+     *
      * @return Returns a Drawable containing the item's default icon
      * such as the default activity icon.
-     * 
+     *
      * @hide
      */
     public Drawable loadDefaultIcon(PackageManager pm) {
@@ -291,10 +287,10 @@
      * Retrieve the current graphical logo associated with this item. This
      * will call back on the given PackageManager to load the logo from
      * the application.
-     * 
+     *
      * @param pm A PackageManager from which the logo can be loaded; usually
      * the PackageManager from which you originally retrieved this item.
-     * 
+     *
      * @return Returns a Drawable containing the item's logo. If the item
      * does not have a logo, this method will return null.
      */
@@ -307,31 +303,31 @@
         }
         return loadDefaultLogo(pm);
     }
-    
+
     /**
      * Retrieve the default graphical logo associated with this item.
-     * 
+     *
      * @param pm A PackageManager from which the logo can be loaded; usually
      * the PackageManager from which you originally retrieved this item.
-     * 
+     *
      * @return Returns a Drawable containing the item's default logo
      * or null if no default logo is available.
-     * 
+     *
      * @hide
      */
     protected Drawable loadDefaultLogo(PackageManager pm) {
         return null;
     }
-    
+
     /**
      * Load an XML resource attached to the meta-data of this item.  This will
      * retrieved the name meta-data entry, and if defined call back on the
      * given PackageManager to load its XML file from the application.
-     * 
+     *
      * @param pm A PackageManager from which the XML can be loaded; usually
      * the PackageManager from which you originally retrieved this item.
      * @param name Name of the meta-date you would like to load.
-     * 
+     *
      * @return Returns an XmlPullParser you can use to parse the XML file
      * assigned as the given meta-data.  If the meta-data name is not defined
      * or the XML resource could not be found, null is returned.
@@ -373,11 +369,11 @@
                     + " banner=0x" + Integer.toHexString(banner));
         }
     }
-    
+
     protected void dumpBack(Printer pw, String prefix) {
         // no back here
     }
-    
+
     public void writeToParcel(Parcel dest, int parcelableFlags) {
         dest.writeString(name);
         dest.writeString(packageName);
@@ -389,7 +385,7 @@
         dest.writeInt(banner);
         dest.writeInt(showUserIcon);
     }
-    
+
     protected PackageItemInfo(Parcel source) {
         name = source.readString();
         packageName = source.readString();
@@ -406,9 +402,9 @@
     /**
      * Get the ApplicationInfo for the application to which this item belongs,
      * if available, otherwise returns null.
-     * 
+     *
      * @return Returns the ApplicationInfo of this item, or null if not known.
-     * 
+     *
      * @hide
      */
     protected ApplicationInfo getApplicationInfo() {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 507608a..7bdc56d 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -20,6 +20,7 @@
 import android.annotation.CheckResult;
 import android.annotation.DrawableRes;
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -1287,6 +1288,13 @@
     public static final int DELETE_FAILED_ABORTED = -5;
 
     /**
+     * Deletion failed return code: this is passed to the
+     * {@link IPackageDeleteObserver} if the system failed to delete the package
+     * because the packge is a shared library used by other installed packages.
+     * {@hide} */
+    public static final int DELETE_FAILED_USED_SHARED_LIBRARY = -6;
+
+    /**
      * Return code that is passed to the {@link IPackageMoveObserver} when the
      * package has been successfully moved by the system.
      *
@@ -2624,6 +2632,11 @@
     public static final int NOTIFY_PACKAGE_USE_REASONS_COUNT = 8;
 
     /**
+     * Constant for specifying the highest installed package version code.
+     */
+    public static final int VERSION_CODE_HIGHEST = -1;
+
+    /**
      * Retrieve overall information about an application package that is
      * installed on the system.
      *
@@ -2671,7 +2684,58 @@
             throws NameNotFoundException;
 
     /**
-     * @hide
+     * Retrieve overall information about an application package that is
+     * installed on the system. This method can be used for retrieving
+     * information about packages for which multiple versions can be
+     * installed at the time. Currently only packages hosting static shared
+     * libraries can have multiple installed versions. The method can also
+     * be used to get info for a package that has a single version installed
+     * by passing {@link #VERSION_CODE_HIGHEST} in the {@link VersionedPackage}
+     * constructor.
+     *
+     * @param versionedPackage The versioned packages for which to query.
+     * @param flags Additional option flags. Use any combination of
+     *         {@link #GET_ACTIVITIES}, {@link #GET_CONFIGURATIONS},
+     *         {@link #GET_GIDS}, {@link #GET_INSTRUMENTATION},
+     *         {@link #GET_INTENT_FILTERS}, {@link #GET_META_DATA},
+     *         {@link #GET_PERMISSIONS}, {@link #GET_PROVIDERS},
+     *         {@link #GET_RECEIVERS}, {@link #GET_SERVICES},
+     *         {@link #GET_SHARED_LIBRARY_FILES}, {@link #GET_SIGNATURES},
+     *         {@link #GET_URI_PERMISSION_PATTERNS}, {@link #GET_UNINSTALLED_PACKAGES},
+     *         {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS},
+     *         {@link #MATCH_UNINSTALLED_PACKAGES}
+     *         to modify the data returned.
+     *
+     * @return A PackageInfo object containing information about the
+     *         package. If flag {@code MATCH_UNINSTALLED_PACKAGES} is set and if the
+     *         package is not found in the list of installed applications, the
+     *         package information is retrieved from the list of uninstalled
+     *         applications (which includes installed applications as well as
+     *         applications with data directory i.e. applications which had been
+     *         deleted with {@code DONT_DELETE_DATA} flag set).
+     * @throws NameNotFoundException if a package with the given name cannot be
+     *             found on the system.
+     * @see #GET_ACTIVITIES
+     * @see #GET_CONFIGURATIONS
+     * @see #GET_GIDS
+     * @see #GET_INSTRUMENTATION
+     * @see #GET_INTENT_FILTERS
+     * @see #GET_META_DATA
+     * @see #GET_PERMISSIONS
+     * @see #GET_PROVIDERS
+     * @see #GET_RECEIVERS
+     * @see #GET_SERVICES
+     * @see #GET_SHARED_LIBRARY_FILES
+     * @see #GET_SIGNATURES
+     * @see #GET_URI_PERMISSION_PATTERNS
+     * @see #MATCH_DISABLED_COMPONENTS
+     * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
+     * @see #MATCH_UNINSTALLED_PACKAGES
+     */
+    public abstract PackageInfo getPackageInfo(VersionedPackage versionedPackage,
+            @PackageInfoFlags int flags) throws NameNotFoundException;
+
+    /**
      * Retrieve overall information about an application package that is
      * installed on the system.
      *
@@ -2715,6 +2779,8 @@
      * @see #MATCH_DISABLED_COMPONENTS
      * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
      * @see #MATCH_UNINSTALLED_PACKAGES
+     *
+     * @hide
      */
     @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract PackageInfo getPackageInfoAsUser(String packageName,
@@ -3705,6 +3771,37 @@
     public abstract String[] getSystemSharedLibraryNames();
 
     /**
+     * Get a list of shared libraries on the device.
+     *
+     * @param flags To filter the libraries to return.
+     * @return The shared library list.
+     *
+     * @see #MATCH_FACTORY_ONLY
+     * @see #MATCH_KNOWN_PACKAGES
+     * @see #MATCH_ANY_USER
+     * @see #MATCH_UNINSTALLED_PACKAGES
+     */
+    public abstract @NonNull List<SharedLibraryInfo> getSharedLibraries(
+            @InstallFlags int flags);
+
+    /**
+     * Get a list of shared libraries on the device.
+     *
+     * @param flags To filter the libraries to return.
+     * @param userId The user to query for.
+     * @return The shared library list.
+     *
+     * @see #MATCH_FACTORY_ONLY
+     * @see #MATCH_KNOWN_PACKAGES
+     * @see #MATCH_ANY_USER
+     * @see #MATCH_UNINSTALLED_PACKAGES
+     *
+     * @hide
+     */
+    public abstract @NonNull List<SharedLibraryInfo> getSharedLibrariesAsUser(
+            @InstallFlags int flags, @UserIdInt int userId);
+
+    /**
      * Get the name of the package hosting the services shared library.
      *
      * @return The library host package.
@@ -5088,6 +5185,7 @@
      *            indicate that no callback is desired.
      * @hide
      */
+    @RequiresPermission(Manifest.permission.DELETE_PACKAGES)
     public abstract void deletePackage(String packageName, IPackageDeleteObserver observer,
             @DeleteFlags int flags);
 
@@ -5106,11 +5204,11 @@
      * @param userId The user Id
      * @hide
      */
-     @RequiresPermission(anyOf = {
+    @RequiresPermission(anyOf = {
             Manifest.permission.DELETE_PACKAGES,
             Manifest.permission.INTERACT_ACROSS_USERS_FULL})
-    public abstract void deletePackageAsUser(String packageName, IPackageDeleteObserver observer,
-            @DeleteFlags int flags, @UserIdInt int userId);
+    public abstract void deletePackageAsUser(@NonNull String packageName,
+            IPackageDeleteObserver observer, @DeleteFlags int flags, @UserIdInt int userId);
 
     /**
      * Retrieve the package name of the application that installed a package. This identifies
@@ -5851,6 +5949,7 @@
             case DELETE_FAILED_USER_RESTRICTED: return "DELETE_FAILED_USER_RESTRICTED";
             case DELETE_FAILED_OWNER_BLOCKED: return "DELETE_FAILED_OWNER_BLOCKED";
             case DELETE_FAILED_ABORTED: return "DELETE_FAILED_ABORTED";
+            case DELETE_FAILED_USED_SHARED_LIBRARY: return "DELETE_FAILED_USED_SHARED_LIBRARY";
             default: return Integer.toString(status);
         }
     }
@@ -5864,6 +5963,7 @@
             case DELETE_FAILED_USER_RESTRICTED: return PackageInstaller.STATUS_FAILURE_BLOCKED;
             case DELETE_FAILED_OWNER_BLOCKED: return PackageInstaller.STATUS_FAILURE_BLOCKED;
             case DELETE_FAILED_ABORTED: return PackageInstaller.STATUS_FAILURE_ABORTED;
+            case DELETE_FAILED_USED_SHARED_LIBRARY: return PackageInstaller.STATUS_FAILURE_CONFLICT;
             default: return PackageInstaller.STATUS_FAILURE;
         }
     }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 5dd77ee..d8d7abe 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1373,6 +1373,11 @@
                         "No APK Signature Scheme v2 signature in ephemeral package " + apkPath,
                         e);
                 }
+                // Static shared libraries must use only the V2 signing scheme
+                if (pkg.applicationInfo.isStaticSharedLibrary()) {
+                    throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
+                            "Static shared libs must use v2 signature scheme " + apkPath);
+                }
             } catch (Exception e) {
                 // APK Signature Scheme v2 signature was found but did not verify
                 throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
@@ -2568,6 +2573,52 @@
         return fi;
     }
 
+    private boolean parseUsesStaticLibrary(Package pkg, Resources res, XmlResourceParser parser,
+            String[] outError) throws XmlPullParserException, IOException {
+        TypedArray sa = res.obtainAttributes(parser,
+                com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary);
+
+        // Note: don't allow this value to be a reference to a resource that may change.
+        String lname = sa.getNonResourceString(
+                com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
+        final int version = sa.getInt(
+                com.android.internal.R.styleable.AndroidManifestUsesStaticLibrary_version, -1);
+        String certSha256 = sa.getNonResourceString(com.android.internal.R.styleable
+                .AndroidManifestUsesStaticLibrary_certDigest);
+        sa.recycle();
+
+        // Since an APK providing a static shared lib can only provide the lib - fail if malformed
+        if (lname == null || version < 0 || certSha256 == null) {
+            outError[0] = "Bad uses-static-library declaration name: " + lname + " version: "
+                    + version + " certDigest" + certSha256;
+            mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+            XmlUtils.skipCurrentTag(parser);
+            return false;
+        }
+
+        // Can depend only on one version of the same library
+        if (pkg.usesStaticLibraries != null && pkg.usesStaticLibraries.contains(lname)) {
+            outError[0] = "Depending on multiple versions of static library " + lname;
+            mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+            XmlUtils.skipCurrentTag(parser);
+            return false;
+        }
+
+        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.
+        certSha256 = certSha256.replace(":", "").toLowerCase();
+        pkg.usesStaticLibraries = ArrayUtils.add(pkg.usesStaticLibraries, lname);
+        pkg.usesStaticLibrariesVersions = ArrayUtils.appendInt(
+                pkg.usesStaticLibrariesVersions, version);
+        pkg.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String.class,
+                pkg.usesStaticLibrariesCertDigests, certSha256);
+
+        XmlUtils.skipCurrentTag(parser);
+
+        return true;
+    }
+
     private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
             throws XmlPullParserException, IOException {
         TypedArray sa = res.obtainAttributes(parser,
@@ -3416,6 +3467,47 @@
                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                     return false;
                 }
+            } else if (tagName.equals("static-library")) {
+                sa = res.obtainAttributes(parser,
+                        com.android.internal.R.styleable.AndroidManifestStaticLibrary);
+
+                // Note: don't allow this value to be a reference to a resource
+                // that may change.
+                final String lname = sa.getNonResourceString(
+                        com.android.internal.R.styleable.AndroidManifestStaticLibrary_name);
+                final int version = sa.getInt(
+                        com.android.internal.R.styleable.AndroidManifestStaticLibrary_version, -1);
+
+                sa.recycle();
+
+                // Since the app canot run without a static lib - fail if malformed
+                if (lname == null || version < 0) {
+                    outError[0] = "Bad static-library declaration name: " + lname
+                            + " version: " + version;
+                    mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+                    XmlUtils.skipCurrentTag(parser);
+                    return false;
+                }
+
+                if (owner.mSharedUserId != null) {
+                    outError[0] = "sharedUserId not allowed in static shared library";
+                    mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
+                    XmlUtils.skipCurrentTag(parser);
+                    return false;
+                }
+
+                if (owner.staticSharedLibName != null) {
+                    outError[0] = "Multiple static-shared libs for package " + pkgName;
+                    mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+                    XmlUtils.skipCurrentTag(parser);
+                    return false;
+                }
+
+                owner.staticSharedLibName = lname.intern();
+                owner.staticSharedLibVersion = version;
+                ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY;
+
+                XmlUtils.skipCurrentTag(parser);
 
             } else if (tagName.equals("library")) {
                 sa = res.obtainAttributes(parser,
@@ -3431,12 +3523,18 @@
                 if (lname != null) {
                     lname = lname.intern();
                     if (!ArrayUtils.contains(owner.libraryNames, lname)) {
-                        owner.libraryNames = ArrayUtils.add(owner.libraryNames, lname);
+                        owner.libraryNames = ArrayUtils.add(
+                                owner.libraryNames, lname);
                     }
                 }
 
                 XmlUtils.skipCurrentTag(parser);
 
+            } else if (tagName.equals("uses-static-library")) {
+                if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
+                    return false;
+                }
+
             } else if (tagName.equals("uses-library")) {
                 sa = res.obtainAttributes(parser,
                         com.android.internal.R.styleable.AndroidManifestUsesLibrary);
@@ -3615,6 +3713,11 @@
                     return false;
                 }
 
+            } else if (tagName.equals("uses-static-library")) {
+                if (!parseUsesStaticLibrary(owner, res, parser, outError)) {
+                    return false;
+                }
+
             } else if (tagName.equals("uses-library")) {
                 sa = res.obtainAttributes(parser,
                         com.android.internal.R.styleable.AndroidManifestUsesLibrary);
@@ -5187,6 +5290,10 @@
 
         public String packageName;
 
+        // The package name declared in the manifest as the package can be
+        // renamed, for example static shared libs use synthetic package names.
+        public String manifestPackageName;
+
         /** Names of any split APKs, ordered by parsed splitName */
         public String[] splitNames;
 
@@ -5241,8 +5348,13 @@
         public Package parentPackage;
         public ArrayList<Package> childPackages;
 
+        public String staticSharedLibName = null;
+        public int staticSharedLibVersion = 0;
         public ArrayList<String> libraryNames = null;
         public ArrayList<String> usesLibraries = null;
+        public ArrayList<String> usesStaticLibraries = null;
+        public int[] usesStaticLibrariesVersions = null;
+        public String[] usesStaticLibrariesCertDigests = null;
         public ArrayList<String> usesOptionalLibraries = null;
         public String[] usesLibraryFiles = null;
 
@@ -5341,6 +5453,7 @@
 
         public Package(String packageName) {
             this.packageName = packageName;
+            this.manifestPackageName = packageName;
             applicationInfo.packageName = packageName;
             applicationInfo.uid = -1;
         }
@@ -5659,6 +5772,7 @@
             final ClassLoader boot = Object.class.getClassLoader();
 
             packageName = dest.readString();
+            manifestPackageName = dest.readString();
             splitNames = dest.readStringArray();
             volumeUuid = dest.readString();
             codePath = dest.readString();
@@ -5699,11 +5813,23 @@
                 childPackages = null;
             }
 
+            staticSharedLibName = dest.readString();
+            staticSharedLibVersion = dest.readInt();
             libraryNames = dest.createStringArrayList();
             usesLibraries = dest.createStringArrayList();
             usesOptionalLibraries = dest.createStringArrayList();
             usesLibraryFiles = dest.readStringArray();
 
+            final int libCount = dest.readInt();
+            if (libCount > 0) {
+                usesStaticLibraries = new ArrayList<>(libCount);
+                dest.readStringList(usesStaticLibraries);
+                usesStaticLibrariesVersions = new int[libCount];
+                dest.readIntArray(usesStaticLibrariesVersions);
+                usesStaticLibrariesCertDigests = new String[libCount];
+                dest.readStringArray(usesStaticLibrariesCertDigests);
+            }
+
             preferredActivityFilters = new ArrayList<>();
             dest.readParcelableList(preferredActivityFilters, boot);
             if (preferredActivityFilters.size() == 0) {
@@ -5789,6 +5915,7 @@
         @Override
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeString(packageName);
+            dest.writeString(manifestPackageName);
             dest.writeStringArray(splitNames);
             dest.writeString(volumeUuid);
             dest.writeString(codePath);
@@ -5813,11 +5940,22 @@
             dest.writeStringList(protectedBroadcasts);
             dest.writeParcelable(parentPackage, flags);
             dest.writeParcelableList(childPackages, flags);
+            dest.writeString(staticSharedLibName);
+            dest.writeInt(staticSharedLibVersion);
             dest.writeStringList(libraryNames);
             dest.writeStringList(usesLibraries);
             dest.writeStringList(usesOptionalLibraries);
             dest.writeStringArray(usesLibraryFiles);
 
+            if (ArrayUtils.isEmpty(usesStaticLibraries)) {
+                dest.writeInt(-1);
+            } else {
+                dest.writeInt(usesStaticLibraries.size());
+                dest.writeStringList(usesStaticLibraries);
+                dest.writeIntArray(usesStaticLibrariesVersions);
+                dest.writeStringArray(usesStaticLibrariesCertDigests);
+            }
+
             dest.writeParcelableList(preferredActivityFilters, flags);
 
             dest.writeStringList(mOriginalPackages);
@@ -6239,6 +6377,9 @@
                 && p.usesLibraryFiles != null) {
             return true;
         }
+        if (p.staticSharedLibName != null) {
+            return true;
+        }
         return false;
     }
 
diff --git a/core/java/android/content/pm/SharedLibraryInfo.aidl b/core/java/android/content/pm/SharedLibraryInfo.aidl
new file mode 100644
index 0000000..56d7c832
--- /dev/null
+++ b/core/java/android/content/pm/SharedLibraryInfo.aidl
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.pm;
+
+parcelable SharedLibraryInfo;
diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java
new file mode 100644
index 0000000..d79deb2
--- /dev/null
+++ b/core/java/android/content/pm/SharedLibraryInfo.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * This class provides information for a shared library. There are
+ * three types of shared libraries: builtin - non-updatable part of
+ * the OS; dynamic - updatable backwards-compatible dynamically linked;
+ * static - updatable non backwards-compatible emulating static linking.
+ */
+public final class SharedLibraryInfo implements Parcelable {
+    /**
+     * Shared library type: this library is a part of the OS
+     * and cannot be updated or uninstalled.
+     * @hide
+     */
+    public static final int TYPE_BUILTIN = 0x1<<0;
+
+    /**
+     * Shared library type: this library is backwards-compatible, can
+     * be updated, and updates can be uninstalled. Clients link against
+     * the latest version of the library.
+     * @hide
+     */
+    public static final int TYPE_DYNAMIC = 0x1<<1;
+
+    /**
+     * Shared library type: this library is <strong>not</strong> backwards
+     * -compatible, can be updated and updates can be uninstalled. Clients
+     * link against a specific version of the library.
+     * @hide
+     */
+    public static final int TYPE_STATIC = 0x1<<2;
+
+    /**
+     * Constant for referring to an undefined version.
+     */
+    public static final int VERSION_UNDEFINED = -1;
+
+    private final String mName;
+    private final int mVersion;
+    private final int mType;
+    private final VersionedPackage mDeclaringPackage;
+    private final List<VersionedPackage> mDependentPackages;
+
+    /**
+     * Creates a new instance.
+     *
+     * @param name The lib name.
+     * @param version The lib version if not builtin.
+     * @param type The lib type.
+     * @param declaringPackage The package that declares the library.
+     * @param dependentPackages The packages that depend on the library.
+     *
+     * @hide
+     */
+    public SharedLibraryInfo(String name, int version, int type,
+            VersionedPackage declaringPackage, List<VersionedPackage> dependentPackages) {
+        mName = name;
+        mVersion = version;
+        mType = type;
+        mDeclaringPackage = declaringPackage;
+        mDependentPackages = dependentPackages;
+    }
+
+    private SharedLibraryInfo(Parcel parcel) {
+        this(parcel.readString(), parcel.readInt(), parcel.readInt(),
+                parcel.readParcelable(null), parcel.readArrayList(null));
+    }
+
+    /** @hide */
+    public int getType() {
+        return mType;
+    }
+
+    /**
+     * Gets the library name.
+     *
+     * @return The name.
+     */
+    public String getName() {
+        return mName;
+    }
+
+    /**
+     * Gets the version of the library. For {@link #isStatic()}  static} libraries
+     * this is the declared version and for {@link #isDynamic()} dynamic} and
+     * {@link #isBuiltin()} builtin} it is {@link #VERSION_UNDEFINED} as these
+     * are not versioned.
+     *
+     * @return The version.
+     */
+    public @IntRange(from = -1) int getVersion() {
+        return mVersion;
+    }
+
+    /**
+     * @return whether this library is builtin which means that it
+     * is a part of the OS and cannot be updated or uninstalled.
+     */
+    public boolean isBuiltin() {
+        return mType == TYPE_BUILTIN;
+    }
+
+    /**
+     * @return whether this library is dynamic which means that it
+     * is backwards-compatible, can be updated, and updates can be
+     * uninstalled. Clients link against the latest version of the
+     * library.
+     */
+    public boolean isDynamic() {
+        return mType == TYPE_DYNAMIC;
+    }
+
+    /**
+     * @return whether this library is dynamic which means that it
+     * is <strong>not</strong> backwards-compatible, can be updated
+     * and updates can be uninstalled. Clients link against a specific
+     * version of the library.
+     */
+    public boolean isStatic() {
+        return mType == TYPE_STATIC;
+    }
+
+    /**
+     * Gets the package that declares the library.
+     *
+     * @return The package declaring the library.
+     */
+    public @NonNull VersionedPackage getDeclaringPackage() {
+        return mDeclaringPackage;
+    }
+
+    /**
+     * Gets the packages that depend on the library.
+     *
+     * @return The dependent packages.
+     */
+    public @NonNull List<VersionedPackage> getDependentPackages() {
+        if (mDependentPackages == null) {
+            return Collections.emptyList();
+        }
+        return mDependentPackages;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public String toString() {
+        return "SharedLibraryInfo[name:" + mName + ", type:" + typeToString(mType)
+                + ", version:" + mVersion + (!getDependentPackages().isEmpty()
+                ? " has dependents" : "");
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeString(mName);
+        parcel.writeInt(mVersion);
+        parcel.writeInt(mType);
+        parcel.writeParcelable(mDeclaringPackage, flags);
+        parcel.writeList(mDependentPackages);
+    }
+
+    private static String typeToString(int type) {
+        switch (type) {
+            case TYPE_BUILTIN: {
+                return "builtin";
+            }
+            case TYPE_DYNAMIC: {
+                return "dynamic";
+            }
+            case TYPE_STATIC: {
+                return "static";
+            }
+            default: {
+                return "unknown";
+            }
+        }
+    }
+
+    public static final Parcelable.Creator<SharedLibraryInfo> CREATOR =
+            new Parcelable.Creator<SharedLibraryInfo>() {
+        public SharedLibraryInfo createFromParcel(Parcel source) {
+            return new SharedLibraryInfo(source);
+        }
+
+        public SharedLibraryInfo[] newArray(int size) {
+            return new SharedLibraryInfo[size];
+        }
+    };
+}
diff --git a/core/java/android/content/pm/VersionedPackage.aidl b/core/java/android/content/pm/VersionedPackage.aidl
new file mode 100644
index 0000000..43412a4
--- /dev/null
+++ b/core/java/android/content/pm/VersionedPackage.aidl
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.pm;
+
+parcelable VersionedPackage;
diff --git a/core/java/android/content/pm/VersionedPackage.java b/core/java/android/content/pm/VersionedPackage.java
new file mode 100644
index 0000000..83e7815
--- /dev/null
+++ b/core/java/android/content/pm/VersionedPackage.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.pm;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Encapsulates a package and its version code.
+ */
+public final class VersionedPackage implements Parcelable {
+    private final String mPackageName;
+    private final long mVersionCode;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntRange(from = PackageManager.VERSION_CODE_HIGHEST)
+    public @interface VersionCode{}
+
+    /**
+     * Creates a new instance. Use {@link PackageManager#VERSION_CODE_HIGHEST}
+     * to refer to the highest version code of this package.
+     * @param packageName The package name.
+     * @param versionCode The version code.
+     */
+    public VersionedPackage(@NonNull String packageName,
+            @VersionCode int versionCode) {
+        mPackageName = packageName;
+        mVersionCode = versionCode;
+    }
+
+    private VersionedPackage(Parcel parcel) {
+        mPackageName = parcel.readString();
+        mVersionCode = parcel.readLong();
+    }
+
+    /**
+     * Gets the package name.
+     *
+     * @return The package name.
+     */
+    public @NonNull String getPackageName() {
+        return mPackageName;
+    }
+
+    /**
+     * Gets the version code.
+     *
+     * @return The version code.
+     */
+    public @VersionCode long getVersionCode() {
+        return mVersionCode;
+    }
+
+    @Override
+    public String toString() {
+        return "VersionedPackage[" + mPackageName + "/" + mVersionCode + "]";
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeString(mPackageName);
+        parcel.writeLong(mVersionCode);
+    }
+
+    public static final Creator<VersionedPackage> CREATOR = new Creator<VersionedPackage>() {
+        @Override
+        public VersionedPackage createFromParcel(Parcel source) {
+            return new VersionedPackage(source);
+        }
+
+        @Override
+        public VersionedPackage[] newArray(int size) {
+            return new VersionedPackage[size];
+        }
+    };
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index db846c8..2692bf2 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2489,6 +2489,16 @@
         android:description="@string/permdesc_requestInstallPackages"
         android:protectionLevel="signature|appop" />
 
+    <!-- Allows an application to request deleting packages. Apps
+         targeting APIs greater than 25 must hold this permission in
+         order to use {@link android.content.Intent#ACTION_UNINSTALL_PACKAGE}.
+         <p>Protection level: normal
+    -->
+    <permission android:name="android.permission.REQUEST_DELETE_PACKAGES"
+        android:label="@string/permlab_requestDeletePackages"
+        android:description="@string/permdesc_requestDeletePackages"
+        android:protectionLevel="normal" />
+
     <!-- @SystemApi Allows an application to install packages.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.INSTALL_PACKAGES"
@@ -3127,7 +3137,7 @@
     <uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
 
 
-    <!-- Allows the holder to access the ephemeral applications on the device.
+    <!-- Allows the holder to access the instant applications on the device.
     @hide -->
     <permission android:name="android.permission.ACCESS_EPHEMERAL_APPS"
             android:protectionLevel="signature" />
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 9b5603d..5235116 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1621,6 +1621,27 @@
         <attr name="name" />
     </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
+       a library and there can be only one static shared library per package. These libraries
+       are updatable, multiple versions can be installed at the same time, and an app links
+       against a specific version simulating static linking while allowing code sharing.
+       Other apks can link to it with the {@link #AndroidManifestUsesLibrary uses-static-library}
+       tag.
+
+     <p>This appears as a child tag of the
+     {@link #AndroidManifestApplication application} tag. -->
+    <declare-styleable name="AndroidManifestStaticLibrary" parent="AndroidManifestApplication">
+        <!-- Required public name of the library, which other components and
+        packages will use when referring to this library.  This is a string using
+        Java-style scoping to ensure it is unique.  The name should typically
+        be the same as the apk's package name. -->
+        <attr name="name" />
+        <!-- Required specific library version. -->
+        <attr name="version" />
+    </declare-styleable>
+
     <!-- The <code>uses-libraries</code> specifies a shared library that this
          package requires to be linked against.  Specifying this flag tells the
          system to include this library's code in your class loader.
@@ -1640,6 +1661,24 @@
         <attr name="required" />
     </declare-styleable>
 
+    <!-- The <code>uses-static-library</code> specifies a shared <strong>static</strong>
+         library that this package requires to be statically linked against. Specifying
+         this tag tells the system to include this library's code in your class loader.
+         Depending on a static shared library is equivalent to statically linking with
+         the library at build time while it offers apps to share code defined in such
+         libraries. Hence, static libraries are strictly required.
+
+         <p>This appears as a child tag of the
+         {@link #AndroidManifestApplication application} tag. -->
+    <declare-styleable name="AndroidManifestUsesStaticLibrary" parent="AndroidManifestApplication">
+        <!-- Required name of the library you use. -->
+        <attr name="name" />
+        <!-- Specify which version of the shared library should be statically linked. -->
+        <attr name="version" />
+        <!-- The SHA-256 digest of the library signing certificate. -->
+        <attr name="certDigest" format="string" />
+    </declare-styleable>
+
     <!-- The <code>supports-screens</code> specifies the screen dimensions an
          application supports.  By default a modern application supports all
          screen sizes and must explicitly disable certain screen sizes here;
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 44cd338..060c59e 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2786,6 +2786,7 @@
         <public name="autoSizeMaxTextSize" />
         <public name="supportsDismissingWindow" />
         <public name="restartOnConfigChanges" />
+        <public name="certDigest" />
     </public-group>
 
     <public-group type="style" first-id="0x010302e0">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3d497cc..d09b190 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3190,6 +3190,11 @@
     <!-- Description of an application permission that lets it read install sessions. -->
     <string name="permdesc_requestInstallPackages">Allows an application to request installation of packages.</string>
 
+    <!-- Title of an application permission that lets it read install sessions. -->
+    <string name="permlab_requestDeletePackages">request delete packages</string>
+    <!-- Description of an application permission that lets it read install sessions. -->
+    <string name="permdesc_requestDeletePackages">Allows an application to request deletion of packages.</string>
+
     <!-- Title of an application permission that lets it ask user to ignore battery optimizations for that app. -->
     <string name="permlab_requestIgnoreBatteryOptimizations">ask to ignore battery optimizations</string>
     <!-- Description of an application permission that lets it ask user to ignore battery optimizations for that app-->
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index d516acf..da6a67e 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -52,6 +52,7 @@
 import android.content.pm.PackageInstaller.SessionParams;
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
+import android.content.pm.VersionedPackage;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.CompressFormat;
 import android.graphics.BitmapFactory;
@@ -869,8 +870,8 @@
     }
 
     @Override
-    public void uninstall(String packageName, String callerPackageName, int flags,
-                IntentSender statusReceiver, int userId) {
+    public void uninstall(VersionedPackage versionedPackage, String callerPackageName, int flags,
+                IntentSender statusReceiver, int userId) throws RemoteException {
         final int callingUid = Binder.getCallingUid();
         mPm.enforceCrossUserPermission(callingUid, userId, true, true, "uninstall");
         if ((callingUid != Process.SHELL_UID) && (callingUid != Process.ROOT_UID)) {
@@ -884,24 +885,24 @@
                 callerPackageName);
 
         final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
-                statusReceiver, packageName, isDeviceOwner, userId);
+                statusReceiver, versionedPackage.getPackageName(), isDeviceOwner, userId);
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES)
                     == PackageManager.PERMISSION_GRANTED) {
             // Sweet, call straight through!
-            mPm.deletePackage(packageName, adapter.getBinder(), userId, flags);
+            mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags);
         } else if (isDeviceOwner) {
             // Allow the DeviceOwner to silently delete packages
             // Need to clear the calling identity to get DELETE_PACKAGES permission
             long ident = Binder.clearCallingIdentity();
             try {
-                mPm.deletePackage(packageName, adapter.getBinder(), userId, flags);
+                mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
         } else {
             // Take a short detour to confirm with user
             final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
-            intent.setData(Uri.fromParts("package", packageName, null));
+            intent.setData(Uri.fromParts("package", versionedPackage.getPackageName(), null));
             intent.putExtra(PackageInstaller.EXTRA_CALLBACK, adapter.getBinder().asBinder());
             adapter.onUserActionRequired(intent);
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e3fa0c4..e40b30f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -16,7 +16,11 @@
 
 package com.android.server.pm;
 
+import static android.Manifest.permission.DELETE_PACKAGES;
+import static android.Manifest.permission.INSTALL_PACKAGES;
 import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
+import static android.Manifest.permission.REQUEST_DELETE_PACKAGES;
+import static android.Manifest.permission.REQUEST_INSTALL_PACKAGES;
 import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
 import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
@@ -160,10 +164,12 @@
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.content.pm.SharedLibraryInfo;
 import android.content.pm.Signature;
 import android.content.pm.UserInfo;
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.pm.VerifierInfo;
+import android.content.pm.VersionedPackage;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.hardware.display.DisplayManager;
@@ -218,6 +224,7 @@
 import android.util.Log;
 import android.util.LogPrinter;
 import android.util.MathUtils;
+import android.util.PackageUtils;
 import android.util.Pair;
 import android.util.PrintStreamPrinter;
 import android.util.Slog;
@@ -415,6 +422,8 @@
     static final int REMOVE_CHATTY = 1<<16;
     static final int SCAN_FIRST_BOOT_OR_UPGRADE = 1<<17;
 
+    private static final String STATIC_SHARED_LIB_DELIMITER = "_";
+
     private static final int[] EMPTY_INT_ARRAY = new int[0];
 
     /**
@@ -710,16 +719,21 @@
     public static final class SharedLibraryEntry {
         public final String path;
         public final String apk;
+        public final SharedLibraryInfo info;
 
-        SharedLibraryEntry(String _path, String _apk) {
+        SharedLibraryEntry(String _path, String _apk, String name, int version, int type,
+                String declaringPackageName, int declaringPackageVersionCode) {
             path = _path;
             apk = _apk;
+            info = new SharedLibraryInfo(name, version, type, new VersionedPackage(
+                    declaringPackageName, declaringPackageVersionCode), null);
         }
     }
 
     // Currently known shared libraries.
-    final ArrayMap<String, SharedLibraryEntry> mSharedLibraries =
-            new ArrayMap<String, SharedLibraryEntry>();
+    final ArrayMap<String, SparseArray<SharedLibraryEntry>> mSharedLibraries = new ArrayMap<>();
+    final ArrayMap<String, SparseArray<SharedLibraryEntry>> mStaticLibsByDeclaringPackage =
+            new ArrayMap<>();
 
     // All available activities, for your resolving pleasure.
     final ActivityIntentResolver mActivities =
@@ -1763,7 +1777,8 @@
             }
 
             // Send installed broadcasts if the install/update is not ephemeral
-            if (!isEphemeral(res.pkg)) {
+            // and the package is not a static shared lib.
+            if (!isEphemeral(res.pkg) && res.pkg.staticSharedLibName == null) {
                 mProcessLoggingHandler.invalidateProcessLoggingBaseApkHash(res.pkg.baseCodePath);
 
                 // Send added for users that see the package for the first time
@@ -1940,9 +1955,10 @@
                 final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(fsUuid);
                 for (PackageSetting ps : packages) {
                     Slog.d(TAG, "Destroying " + ps.name + " because volume was forgotten");
-                    deletePackage(ps.name, new LegacyPackageDeleteObserver(null).getBinder(),
+                    deletePackageVersioned(new VersionedPackage(ps.name,
+                            PackageManager.VERSION_CODE_HIGHEST),
+                            new LegacyPackageDeleteObserver(null).getBinder(),
                             UserHandle.USER_SYSTEM, PackageManager.DELETE_ALL_USERS);
-
                     // Try very hard to release any references to this package
                     // so we don't risk the system server being killed due to
                     // open FDs
@@ -2251,9 +2267,12 @@
             }
 
             ArrayMap<String, String> libConfig = systemConfig.getSharedLibraries();
-            for (int i=0; i<libConfig.size(); i++) {
-                mSharedLibraries.put(libConfig.keyAt(i),
-                        new SharedLibraryEntry(libConfig.valueAt(i), null));
+            final int builtInLibCount = libConfig.size();
+            for (int i = 0; i < builtInLibCount; i++) {
+                String name = libConfig.keyAt(i);
+                String path = libConfig.valueAt(i);
+                addSharedLibraryLPw(path, null, name, SharedLibraryInfo.VERSION_UNDEFINED,
+                        SharedLibraryInfo.TYPE_BUILTIN, PLATFORM_PACKAGE_NAME, 0);
             }
 
             mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();
@@ -2318,32 +2337,38 @@
                 // to compile them only when we come across an app that uses them (there's
                 // already logic for that in scanPackageLI) but that adds some complexity.
                 for (String dexCodeInstructionSet : dexCodeInstructionSets) {
-                    for (SharedLibraryEntry libEntry : mSharedLibraries.values()) {
-                        final String lib = libEntry.path;
-                        if (lib == null) {
-                            continue;
-                        }
-
-                        try {
-                            // Shared libraries do not have profiles so we perform a full
-                            // AOT compilation (if needed).
-                            int dexoptNeeded = DexFile.getDexOptNeeded(
-                                    lib, dexCodeInstructionSet,
-                                    getCompilerFilterForReason(REASON_SHARED_APK),
-                                    false /* newProfile */);
-                            if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
-                                mInstaller.dexopt(lib, Process.SYSTEM_UID, "*",
-                                        dexCodeInstructionSet, dexoptNeeded, null,
-                                        DEXOPT_PUBLIC,
-                                        getCompilerFilterForReason(REASON_SHARED_APK),
-                                        StorageManager.UUID_PRIVATE_INTERNAL,
-                                        SKIP_SHARED_LIBRARY_CHECK);
+                    final int libCount = mSharedLibraries.size();
+                    for (int i = 0; i < libCount; i++) {
+                        SparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.valueAt(i);
+                        final int versionCount = versionedLib.size();
+                        for (int j = 0; j < versionCount; j++) {
+                            SharedLibraryEntry libEntry = versionedLib.valueAt(j);
+                            final String libPath = libEntry.path != null
+                                    ? libEntry.path : libEntry.apk;
+                            if (libPath == null) {
+                                continue;
                             }
-                        } catch (FileNotFoundException e) {
-                            Slog.w(TAG, "Library not found: " + lib);
-                        } catch (IOException | InstallerException e) {
-                            Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
-                                    + e.getMessage());
+                            try {
+                                // Shared libraries do not have profiles so we perform a full
+                                // AOT compilation (if needed).
+                                int dexoptNeeded = DexFile.getDexOptNeeded(
+                                        libPath, dexCodeInstructionSet,
+                                        getCompilerFilterForReason(REASON_SHARED_APK),
+                                        false /* newProfile */);
+                                if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
+                                    mInstaller.dexopt(libPath, Process.SYSTEM_UID, "*",
+                                            dexCodeInstructionSet, dexoptNeeded, null,
+                                            DEXOPT_PUBLIC,
+                                            getCompilerFilterForReason(REASON_SHARED_APK),
+                                            StorageManager.UUID_PRIVATE_INTERNAL,
+                                            SKIP_SHARED_LIBRARY_CHECK);
+                                }
+                            } catch (FileNotFoundException e) {
+                                Slog.w(TAG, "Library not found: " + libPath);
+                            } catch (IOException | InstallerException e) {
+                                Slog.w(TAG, "Cannot dexopt " + libPath + "; is it an APK or JAR? "
+                                        + e.getMessage());
+                            }
                         }
                     }
                 }
@@ -2637,7 +2662,7 @@
 
             // Now that we know all of the shared libraries, update all clients to have
             // the correct library paths.
-            updateAllSharedLibrariesLPw();
+            updateAllSharedLibrariesLPw(null);
 
             for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
                 // NOTE: We ignore potential failures here during a system scan (like
@@ -2774,9 +2799,11 @@
                 mIntentFilterVerifier = new IntentVerifierProxy(mContext,
                         mIntentFilterVerifierComponent);
                 mServicesSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
-                        PackageManager.SYSTEM_SHARED_LIBRARY_SERVICES);
+                        PackageManager.SYSTEM_SHARED_LIBRARY_SERVICES,
+                        SharedLibraryInfo.VERSION_UNDEFINED);
                 mSharedSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
-                        PackageManager.SYSTEM_SHARED_LIBRARY_SHARED);
+                        PackageManager.SYSTEM_SHARED_LIBRARY_SHARED,
+                        SharedLibraryInfo.VERSION_UNDEFINED);
             } else {
                 mRequiredVerifierPackage = null;
                 mRequiredInstallerPackage = null;
@@ -2933,11 +2960,11 @@
         throw new RuntimeException("There must be exactly one verifier; found " + matches);
     }
 
-    private @NonNull String getRequiredSharedLibraryLPr(String libraryName) {
+    private @NonNull String getRequiredSharedLibraryLPr(String name, int version) {
         synchronized (mPackages) {
-            SharedLibraryEntry libraryEntry = mSharedLibraries.get(libraryName);
+            SharedLibraryEntry libraryEntry = getSharedLibraryEntryLPr(name, version);
             if (libraryEntry == null) {
-                throw new IllegalStateException("Missing required shared library:" + libraryName);
+                throw new IllegalStateException("Missing required shared library:" + name);
             }
             return libraryEntry.apk;
         }
@@ -3297,8 +3324,17 @@
             flags |= MATCH_ANY_USER;
         }
 
-        return PackageParser.generatePackageInfo(p, gids, flags,
+        PackageInfo packageInfo = PackageParser.generatePackageInfo(p, gids, flags,
                 ps.firstInstallTime, ps.lastUpdateTime, permissions, state, userId);
+
+        if (packageInfo == null) {
+            return null;
+        }
+
+        packageInfo.packageName = packageInfo.applicationInfo.packageName =
+                resolveExternalPackageNameLPr(p);
+
+        return packageInfo;
     }
 
     @Override
@@ -3353,6 +3389,20 @@
 
     @Override
     public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
+        return getPackageInfoInternal(packageName, PackageManager.VERSION_CODE_HIGHEST,
+                flags, userId);
+    }
+
+    @Override
+    public PackageInfo getPackageInfoVersioned(VersionedPackage versionedPackage,
+            int flags, int userId) {
+        return getPackageInfoInternal(versionedPackage.getPackageName(),
+                // TODO: We will change version code to long, so in the new API it is long
+                (int) versionedPackage.getVersionCode(), flags, userId);
+    }
+
+    private PackageInfo getPackageInfoInternal(String packageName, int versionCode,
+            int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
         flags = updateFlagsForPackage(flags, userId, packageName);
         enforceCrossUserPermission(Binder.getCallingUid(), userId,
@@ -3360,16 +3410,20 @@
 
         // reader
         synchronized (mPackages) {
-            // Normalize package name to handle renamed packages
-            packageName = normalizePackageNameLPr(packageName);
+            // Normalize package name to handle renamed packages and static libs
+            packageName = resolveInternalPackageNameLPr(packageName, versionCode);
 
             final boolean matchFactoryOnly = (flags & MATCH_FACTORY_ONLY) != 0;
             if (matchFactoryOnly) {
                 final PackageSetting ps = mSettings.getDisabledSystemPkgLPr(packageName);
                 if (ps != null) {
+                    if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId)) {
+                        return null;
+                    }
                     return generatePackageInfo(ps, flags, userId);
                 }
             }
+
             PackageParser.Package p = mPackages.get(packageName);
             if (matchFactoryOnly && p != null && !isSystemApp(p)) {
                 return null;
@@ -3377,16 +3431,68 @@
             if (DEBUG_PACKAGE_INFO)
                 Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
             if (p != null) {
+                if (filterSharedLibPackageLPr((PackageSetting) p.mExtras,
+                        Binder.getCallingUid(), userId)) {
+                    return null;
+                }
                 return generatePackageInfo((PackageSetting)p.mExtras, flags, userId);
             }
             if (!matchFactoryOnly && (flags & MATCH_KNOWN_PACKAGES) != 0) {
                 final PackageSetting ps = mSettings.mPackages.get(packageName);
+                if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId)) {
+                    return null;
+                }
                 return generatePackageInfo(ps, flags, userId);
             }
         }
         return null;
     }
 
+
+    private boolean filterSharedLibPackageLPr(PackageSetting ps, int uid, int userId) {
+        // System/shell/root get to see all static libs
+        final int appId = UserHandle.getAppId(uid);
+        if (appId == Process.SYSTEM_UID || appId == Process.SHELL_UID
+                || appId == Process.ROOT_UID) {
+            return false;
+        }
+
+        // No package means no static lib as it is always on internal storage
+        if (ps.pkg == null || !ps.pkg.applicationInfo.isStaticSharedLibrary()) {
+            return false;
+        }
+
+        final SharedLibraryEntry libEntry = getSharedLibraryEntryLPr(ps.pkg.staticSharedLibName,
+                ps.pkg.staticSharedLibVersion);
+        if (libEntry == 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.name.equals(uidPackageName)) {
+                return false;
+            }
+            PackageSetting uidPs = mSettings.getPackageLPr(uidPackageName);
+            if (uidPs != null) {
+                final int index = ArrayUtils.indexOf(uidPs.usesStaticLibraries,
+                        libEntry.info.getName());
+                if (index < 0) {
+                    continue;
+                }
+                if (uidPs.pkg.usesStaticLibrariesVersions[index] == libEntry.info.getVersion()) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
     @Override
     public String[] currentToCanonicalPackageNames(String[] names) {
         String[] out = new String[names.length];
@@ -3539,10 +3645,13 @@
     }
 
     private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags,
-            int userId) {
+            int uid, int userId) {
         if (!sUserManager.exists(userId)) return null;
         PackageSetting ps = mSettings.mPackages.get(packageName);
         if (ps != null) {
+            if (filterSharedLibPackageLPr(ps, uid, userId)) {
+                return null;
+            }
             if (ps.pkg == null) {
                 final PackageInfo pInfo = generatePackageInfo(ps, flags, userId);
                 if (pInfo != null) {
@@ -3550,8 +3659,12 @@
                 }
                 return null;
             }
-            return PackageParser.generateApplicationInfo(ps.pkg, flags,
+            ApplicationInfo ai = PackageParser.generateApplicationInfo(ps.pkg, flags,
                     ps.readUserState(userId), userId);
+            if (ai != null) {
+                ai.packageName = resolveExternalPackageNameLPr(ps.pkg);
+            }
+            return ai;
         }
         return null;
     }
@@ -3565,8 +3678,9 @@
 
         // writer
         synchronized (mPackages) {
-            // Normalize package name to hanlde renamed packages
-            packageName = normalizePackageNameLPr(packageName);
+            // Normalize package name to handle renamed packages and static libs
+            packageName = resolveInternalPackageNameLPr(packageName,
+                    PackageManager.VERSION_CODE_HIGHEST);
 
             PackageParser.Package p = mPackages.get(packageName);
             if (DEBUG_PACKAGE_INFO) Log.v(
@@ -3575,15 +3689,24 @@
             if (p != null) {
                 PackageSetting ps = mSettings.mPackages.get(packageName);
                 if (ps == null) return null;
+                if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId)) {
+                    return null;
+                }
                 // Note: isEnabledLP() does not apply here - always return info
-                return PackageParser.generateApplicationInfo(
+                ApplicationInfo ai = PackageParser.generateApplicationInfo(
                         p, flags, ps.readUserState(userId), userId);
+                if (ai != null) {
+                    ai.packageName = resolveExternalPackageNameLPr(p);
+                }
+                return ai;
             }
             if ("android".equals(packageName)||"system".equals(packageName)) {
                 return mAndroidApplication;
             }
             if ((flags & MATCH_KNOWN_PACKAGES) != 0) {
-                return generateApplicationInfoFromSettingsLPw(packageName, flags, userId);
+                // Already generates the external package name
+                return generateApplicationInfoFromSettingsLPw(packageName,
+                        Binder.getCallingUid(), flags, userId);
             }
         }
         return null;
@@ -3869,6 +3992,113 @@
     }
 
     @Override
+    public ParceledListSlice<SharedLibraryInfo> getSharedLibraries(int flags, int userId) {
+        if (!sUserManager.exists(userId)) return null;
+        Preconditions.checkArgumentNonnegative(userId, "userId must be >= 0");
+
+        flags = updateFlagsForPackage(flags, userId, null);
+
+        final boolean canSeeStaticLibraries =
+                mContext.checkCallingOrSelfPermission(INSTALL_PACKAGES)
+                        == PERMISSION_GRANTED
+                || mContext.checkCallingOrSelfPermission(DELETE_PACKAGES)
+                        == PERMISSION_GRANTED
+                || mContext.checkCallingOrSelfPermission(REQUEST_INSTALL_PACKAGES)
+                        == PERMISSION_GRANTED
+                || mContext.checkCallingOrSelfPermission(REQUEST_DELETE_PACKAGES)
+                        == PERMISSION_GRANTED;
+
+        synchronized (mPackages) {
+            List<SharedLibraryInfo> result = null;
+
+            final int libCount = mSharedLibraries.size();
+            for (int i = 0; i < libCount; i++) {
+                SparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.valueAt(i);
+                if (versionedLib == null) {
+                    continue;
+                }
+
+                final int versionCount = versionedLib.size();
+                for (int j = 0; j < versionCount; j++) {
+                    SharedLibraryInfo libInfo = versionedLib.valueAt(j).info;
+                    if (!canSeeStaticLibraries && libInfo.isStatic()) {
+                        break;
+                    }
+                    final long identity = Binder.clearCallingIdentity();
+                    try {
+                        // TODO: We will change version code to long, so in the new API it is long
+                        PackageInfo packageInfo = getPackageInfoVersioned(
+                                libInfo.getDeclaringPackage(), flags, userId);
+                        if (packageInfo == null) {
+                            continue;
+                        }
+                    } finally {
+                        Binder.restoreCallingIdentity(identity);
+                    }
+
+                    SharedLibraryInfo resLibInfo = new SharedLibraryInfo(libInfo.getName(),
+                            libInfo.getVersion(), libInfo.getType(), libInfo.getDeclaringPackage(),
+                            getPackagesUsingSharedLibraryLPr(libInfo, flags, userId));
+
+                    if (result == null) {
+                        result = new ArrayList<>();
+                    }
+                    result.add(resLibInfo);
+                }
+            }
+
+            return result != null ? new ParceledListSlice<>(result) : null;
+        }
+    }
+
+    private List<VersionedPackage> getPackagesUsingSharedLibraryLPr(
+            SharedLibraryInfo libInfo, int flags, int userId) {
+        List<VersionedPackage> versionedPackages = null;
+        final int packageCount = mSettings.mPackages.size();
+        for (int i = 0; i < packageCount; i++) {
+            PackageSetting ps = mSettings.mPackages.valueAt(i);
+
+            if (ps == null) {
+                continue;
+            }
+
+            if (!ps.getUserState().get(userId).isAvailable(flags)) {
+                continue;
+            }
+
+            final String libName = libInfo.getName();
+            if (libInfo.isStatic()) {
+                final int libIdx = ArrayUtils.indexOf(ps.usesStaticLibraries, libName);
+                if (libIdx < 0) {
+                    continue;
+                }
+                if (ps.usesStaticLibrariesVersions[libIdx] != libInfo.getVersion()) {
+                    continue;
+                }
+                if (versionedPackages == null) {
+                    versionedPackages = new ArrayList<>();
+                }
+                // If the dependent is a static shared lib, use the public package name
+                String dependentPackageName = ps.name;
+                if (ps.pkg != null && ps.pkg.applicationInfo.isStaticSharedLibrary()) {
+                    dependentPackageName = ps.pkg.manifestPackageName;
+                }
+                versionedPackages.add(new VersionedPackage(dependentPackageName, ps.versionCode));
+            } else if (ps.pkg != null) {
+                if (ArrayUtils.contains(ps.pkg.usesLibraries, libName)
+                        || ArrayUtils.contains(ps.pkg.usesOptionalLibraries, libName)) {
+                    if (versionedPackages == null) {
+                        versionedPackages = new ArrayList<>();
+                    }
+                    versionedPackages.add(new VersionedPackage(ps.name, ps.versionCode));
+                }
+            }
+        }
+
+        return versionedPackages;
+    }
+
+    @Override
     public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
         flags = updateFlagsForComponent(flags, userId, component);
@@ -3910,17 +4140,44 @@
 
     @Override
     public String[] getSystemSharedLibraryNames() {
-        Set<String> libSet;
         synchronized (mPackages) {
-            libSet = mSharedLibraries.keySet();
-            int size = libSet.size();
-            if (size > 0) {
-                String[] libs = new String[size];
-                libSet.toArray(libs);
-                return libs;
+            Set<String> libs = null;
+            final int libCount = mSharedLibraries.size();
+            for (int i = 0; i < libCount; i++) {
+                SparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.valueAt(i);
+                if (versionedLib == null) {
+                    continue;
+                }
+                final int versionCount = versionedLib.size();
+                for (int j = 0; j < versionCount; j++) {
+                    SharedLibraryEntry libEntry = versionedLib.valueAt(j);
+                    if (!libEntry.info.isStatic()) {
+                        if (libs == null) {
+                            libs = new ArraySet<>();
+                        }
+                        libs.add(libEntry.info.getName());
+                        break;
+                    }
+                    PackageSetting ps = mSettings.getPackageLPr(libEntry.apk);
+                    if (ps != null && !filterSharedLibPackageLPr(ps, Binder.getCallingUid(),
+                            UserHandle.getUserId(Binder.getCallingUid()))) {
+                        if (libs == null) {
+                            libs = new ArraySet<>();
+                        }
+                        libs.add(libEntry.info.getName());
+                        break;
+                    }
+                }
             }
+
+            if (libs != null) {
+                String[] libsArray = new String[libs.size()];
+                libs.toArray(libsArray);
+                return libsArray;
+            }
+
+            return null;
         }
-        return null;
     }
 
     @Override
@@ -5032,7 +5289,9 @@
                 return res;
             } else if (obj instanceof PackageSetting) {
                 final PackageSetting ps = (PackageSetting) obj;
-                return new String[] { ps.name };
+                if (ps.getInstalled(userId)) {
+                    return new String[]{ps.name};
+                }
             }
         }
         return null;
@@ -6600,30 +6859,32 @@
         synchronized (mPackages) {
             ArrayList<PackageInfo> list;
             if (listUninstalled) {
-                list = new ArrayList<PackageInfo>(mSettings.mPackages.size());
+                list = new ArrayList<>(mSettings.mPackages.size());
                 for (PackageSetting ps : mSettings.mPackages.values()) {
-                    final PackageInfo pi;
-                    if (ps.pkg != null) {
-                        pi = generatePackageInfo(ps, flags, userId);
-                    } else {
-                        pi = generatePackageInfo(ps, flags, userId);
+                    if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId)) {
+                        continue;
                     }
+                    final PackageInfo pi = generatePackageInfo(ps, flags, userId);
                     if (pi != null) {
                         list.add(pi);
                     }
                 }
             } else {
-                list = new ArrayList<PackageInfo>(mPackages.size());
+                list = new ArrayList<>(mPackages.size());
                 for (PackageParser.Package p : mPackages.values()) {
-                    final PackageInfo pi =
-                            generatePackageInfo((PackageSetting)p.mExtras, flags, userId);
+                    if (filterSharedLibPackageLPr((PackageSetting) p.mExtras,
+                            Binder.getCallingUid(), userId)) {
+                        continue;
+                    }
+                    final PackageInfo pi = generatePackageInfo((PackageSetting)
+                            p.mExtras, flags, userId);
                     if (pi != null) {
                         list.add(pi);
                     }
                 }
             }
 
-            return new ParceledListSlice<PackageInfo>(list);
+            return new ParceledListSlice<>(list);
         }
     }
 
@@ -6643,12 +6904,8 @@
         if (numMatch == 0) {
             return;
         }
-        final PackageInfo pi;
-        if (ps.pkg != null) {
-            pi = generatePackageInfo(ps, flags, userId);
-        } else {
-            pi = generatePackageInfo(ps, flags, userId);
-        }
+        final PackageInfo pi = generatePackageInfo(ps, flags, userId);
+
         // The above might return null in cases of uninstalled apps or install-state
         // skew across users/profiles.
         if (pi != null) {
@@ -6713,7 +6970,7 @@
         synchronized (mPackages) {
             ArrayList<ApplicationInfo> list;
             if (listUninstalled) {
-                list = new ArrayList<ApplicationInfo>(mSettings.mPackages.size());
+                list = new ArrayList<>(mSettings.mPackages.size());
                 for (PackageSetting ps : mSettings.mPackages.values()) {
                     ApplicationInfo ai;
                     int effectiveFlags = flags;
@@ -6721,30 +6978,43 @@
                         effectiveFlags |= PackageManager.MATCH_ANY_USER;
                     }
                     if (ps.pkg != null) {
+                        if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId)) {
+                            continue;
+                        }
                         ai = PackageParser.generateApplicationInfo(ps.pkg, effectiveFlags,
                                 ps.readUserState(userId), userId);
+                        if (ai != null) {
+                            ai.packageName = resolveExternalPackageNameLPr(ps.pkg);
+                        }
                     } else {
-                        ai = generateApplicationInfoFromSettingsLPw(ps.name, effectiveFlags,
-                                userId);
+                        // Shared lib filtering done in generateApplicationInfoFromSettingsLPw
+                        // and already converts to externally visible package name
+                        ai = generateApplicationInfoFromSettingsLPw(ps.name,
+                                Binder.getCallingUid(), effectiveFlags, userId);
                     }
                     if (ai != null) {
                         list.add(ai);
                     }
                 }
             } else {
-                list = new ArrayList<ApplicationInfo>(mPackages.size());
+                list = new ArrayList<>(mPackages.size());
                 for (PackageParser.Package p : mPackages.values()) {
                     if (p.mExtras != null) {
+                        PackageSetting ps = (PackageSetting) p.mExtras;
+                        if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId)) {
+                            continue;
+                        }
                         ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
-                                ((PackageSetting)p.mExtras).readUserState(userId), userId);
+                                ps.readUserState(userId), userId);
                         if (ai != null) {
+                            ai.packageName = resolveExternalPackageNameLPr(p);
                             list.add(ai);
                         }
                     }
                 }
             }
 
-            return new ParceledListSlice<ApplicationInfo>(list);
+            return new ParceledListSlice<>(list);
         }
     }
 
@@ -6834,6 +7104,7 @@
 
         mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_EPHEMERAL_APPS,
                 "getEphemeralApplicationIcon");
+
         enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 true /* requireFullPermission */, false /* checkShell */,
                 "getEphemeralApplicationIcon");
@@ -7110,9 +7381,15 @@
             int errorCode = PackageManager.INSTALL_SUCCEEDED;
 
             if (throwable == null) {
+                // Static shared libraries have synthetic package names
+                if (parseResult.pkg.applicationInfo.isStaticSharedLibrary()) {
+                    renameStaticSharedLibraryPackage(parseResult.pkg);
+                }
                 try {
-                    scanPackageLI(parseResult.pkg, parseResult.scanFile, parseFlags, scanFlags,
-                            currentTime, null);
+                    if (errorCode == PackageManager.INSTALL_SUCCEEDED) {
+                        scanPackageLI(parseResult.pkg, parseResult.scanFile, parseFlags, scanFlags,
+                                currentTime, null);
+                    }
                 } catch (PackageManagerException e) {
                     errorCode = e.error;
                     Slog.w(TAG, "Failed to scan " + parseResult.scanFile + ": " + e.getMessage());
@@ -7266,6 +7543,11 @@
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
 
+        // Static shared libraries have synthetic package names
+        if (pkg.applicationInfo.isStaticSharedLibrary()) {
+            renameStaticSharedLibraryPackage(pkg);
+        }
+
         return scanPackageLI(pkg, scanFile, parseFlags, scanFlags, currentTime, user);
     }
 
@@ -7568,6 +7850,12 @@
         return scannedPkg;
     }
 
+    private void renameStaticSharedLibraryPackage(PackageParser.Package pkg) {
+        // Derive the new package synthetic package name
+        pkg.setPackageName(pkg.packageName + STATIC_SHARED_LIB_DELIMITER
+                + pkg.staticSharedLibVersion);
+    }
+
     private static String fixProcessName(String defProcessName,
             String processName) {
         if (processName == null) {
@@ -7923,8 +8211,9 @@
                 targetCompilerFilter, getOrCreateCompilerPackageStats(p));
     }
 
-    Collection<PackageParser.Package> findSharedNonSystemLibraries(PackageParser.Package p) {
-        if (p.usesLibraries != null || p.usesOptionalLibraries != null) {
+    List<PackageParser.Package> findSharedNonSystemLibraries(PackageParser.Package p) {
+        if (p.usesLibraries != null || p.usesOptionalLibraries != null
+                || p.usesStaticLibraries != null) {
             ArrayList<PackageParser.Package> retValue = new ArrayList<>();
             Set<String> collectedNames = new HashSet<>();
             findSharedNonSystemLibrariesRecursive(p, retValue, collectedNames);
@@ -7938,37 +8227,74 @@
     }
 
     private void findSharedNonSystemLibrariesRecursive(PackageParser.Package p,
-            Collection<PackageParser.Package> collected, Set<String> collectedNames) {
+            ArrayList<PackageParser.Package> collected, Set<String> collectedNames) {
         if (!collectedNames.contains(p.packageName)) {
             collectedNames.add(p.packageName);
             collected.add(p);
 
             if (p.usesLibraries != null) {
-                findSharedNonSystemLibrariesRecursive(p.usesLibraries, collected, collectedNames);
+                findSharedNonSystemLibrariesRecursive(p.usesLibraries,
+                        null, collected, collectedNames);
             }
             if (p.usesOptionalLibraries != null) {
-                findSharedNonSystemLibrariesRecursive(p.usesOptionalLibraries, collected,
-                        collectedNames);
+                findSharedNonSystemLibrariesRecursive(p.usesOptionalLibraries,
+                        null, collected, collectedNames);
+            }
+            if (p.usesStaticLibraries != null) {
+                findSharedNonSystemLibrariesRecursive(p.usesStaticLibraries,
+                        p.usesStaticLibrariesVersions, collected, collectedNames);
             }
         }
     }
 
-    private void findSharedNonSystemLibrariesRecursive(Collection<String> libs,
-            Collection<PackageParser.Package> collected, Set<String> collectedNames) {
-        for (String libName : libs) {
-            PackageParser.Package libPkg = findSharedNonSystemLibrary(libName);
+    private void findSharedNonSystemLibrariesRecursive(ArrayList<String> libs, int[] versions,
+            ArrayList<PackageParser.Package> collected, Set<String> collectedNames) {
+        final int libNameCount = libs.size();
+        for (int i = 0; i < libNameCount; i++) {
+            String libName = libs.get(i);
+            int version = (versions != null && versions.length == libNameCount)
+                    ? versions[i] : PackageManager.VERSION_CODE_HIGHEST;
+            PackageParser.Package libPkg = findSharedNonSystemLibrary(libName, version);
             if (libPkg != null) {
                 findSharedNonSystemLibrariesRecursive(libPkg, collected, collectedNames);
             }
         }
     }
 
-    private PackageParser.Package findSharedNonSystemLibrary(String libName) {
+    private PackageParser.Package findSharedNonSystemLibrary(String name, int version) {
         synchronized (mPackages) {
-            PackageManagerService.SharedLibraryEntry lib = mSharedLibraries.get(libName);
-            if (lib != null && lib.apk != null) {
-                return mPackages.get(lib.apk);
+            SharedLibraryEntry libEntry = getSharedLibraryEntryLPr(name, version);
+            if (libEntry != null) {
+                return mPackages.get(libEntry.apk);
             }
+            return null;
+        }
+    }
+
+    private SharedLibraryEntry getSharedLibraryEntryLPr(String name, int version) {
+        SparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(name);
+        if (versionedLib == null) {
+            return null;
+        }
+        return versionedLib.get(version);
+    }
+
+    private SharedLibraryEntry getLatestSharedLibraVersionLPr(PackageParser.Package pkg) {
+        SparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(
+                pkg.staticSharedLibName);
+        if (versionedLib == null) {
+            return null;
+        }
+        int previousLibVersion = -1;
+        final int versionCount = versionedLib.size();
+        for (int i = 0; i < versionCount; i++) {
+            final int libVersion = versionedLib.keyAt(i);
+            if (libVersion < pkg.staticSharedLibVersion) {
+                previousLibVersion = Math.max(previousLibVersion, libVersion);
+            }
+        }
+        if (previousLibVersion >= 0) {
+            return versionedLib.get(previousLibVersion);
         }
         return null;
     }
@@ -8262,36 +8588,84 @@
 
     private void updateSharedLibrariesLPr(PackageParser.Package pkg,
             PackageParser.Package changingLib) throws PackageManagerException {
-        if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
-            final ArraySet<String> usesLibraryFiles = new ArraySet<>();
-            int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0;
-            for (int i=0; i<N; i++) {
-                final SharedLibraryEntry file = mSharedLibraries.get(pkg.usesLibraries.get(i));
-                if (file == null) {
+        if (pkg == null) {
+            return;
+        }
+        ArraySet<String> usesLibraryFiles = null;
+        if (pkg.usesLibraries != null) {
+            usesLibraryFiles = addSharedLibrariesLPw(pkg.usesLibraries,
+                    null, null, pkg.packageName, changingLib, true, null);
+        }
+        if (pkg.usesStaticLibraries != null) {
+            usesLibraryFiles = addSharedLibrariesLPw(pkg.usesStaticLibraries,
+                    pkg.usesStaticLibrariesVersions, pkg.usesStaticLibrariesCertDigests,
+                    pkg.packageName, changingLib, true, usesLibraryFiles);
+        }
+        if (pkg.usesOptionalLibraries != null) {
+            usesLibraryFiles = addSharedLibrariesLPw(pkg.usesOptionalLibraries,
+                    null, null, pkg.packageName, changingLib, false, usesLibraryFiles);
+        }
+        if (!ArrayUtils.isEmpty(usesLibraryFiles)) {
+            pkg.usesLibraryFiles = usesLibraryFiles.toArray(new String[usesLibraryFiles.size()]);
+        } else {
+            pkg.usesLibraryFiles = null;
+        }
+    }
+
+    private ArraySet<String> addSharedLibrariesLPw(@NonNull List<String> requestedLibraries,
+            @Nullable int[] requiredVersions, @Nullable String[] requiredCertDigests,
+            @NonNull String packageName, @Nullable PackageParser.Package changingLib,
+            boolean required, @Nullable ArraySet<String> outUsedLibraries)
+            throws PackageManagerException {
+        final int libCount = requestedLibraries.size();
+        for (int i = 0; i < libCount; i++) {
+            final String libName = requestedLibraries.get(i);
+            final int libVersion = requiredVersions != null ? requiredVersions[i]
+                    : SharedLibraryInfo.VERSION_UNDEFINED;
+            final SharedLibraryEntry libEntry = getSharedLibraryEntryLPr(libName, libVersion);
+            if (libEntry == null) {
+                if (required) {
                     throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
-                            "Package " + pkg.packageName + " requires unavailable shared library "
-                            + pkg.usesLibraries.get(i) + "; failing!");
-                }
-                addSharedLibraryLPr(usesLibraryFiles, file, changingLib);
-            }
-            N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0;
-            for (int i=0; i<N; i++) {
-                final SharedLibraryEntry file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i));
-                if (file == null) {
-                    Slog.w(TAG, "Package " + pkg.packageName
-                            + " desires unavailable shared library "
-                            + pkg.usesOptionalLibraries.get(i) + "; ignoring!");
+                            "Package " + packageName + " requires unavailable shared library "
+                                    + libName + "; failing!");
                 } else {
-                    addSharedLibraryLPr(usesLibraryFiles, file, changingLib);
+                    Slog.w(TAG, "Package " + packageName
+                            + " desires unavailable shared library "
+                            + libName + "; ignoring!");
                 }
-            }
-            N = usesLibraryFiles.size();
-            if (N > 0) {
-                pkg.usesLibraryFiles = usesLibraryFiles.toArray(new String[N]);
             } else {
-                pkg.usesLibraryFiles = null;
+                if (requiredVersions != null && requiredCertDigests != null) {
+                    if (libEntry.info.getVersion() != requiredVersions[i]) {
+                        throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
+                            "Package " + packageName + " requires unavailable static shared"
+                                    + " library " + libName + " version "
+                                    + libEntry.info.getVersion() + "; failing!");
+                    }
+
+                    PackageParser.Package libPkg = mPackages.get(libEntry.apk);
+                    if (libPkg == null) {
+                        throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
+                                "Package " + packageName + " requires unavailable static shared"
+                                        + " library; failing!");
+                    }
+
+                    String expectedCertDigest = requiredCertDigests[i];
+                    String libCertDigest = PackageUtils.computeCertSha256Digest(
+                                libPkg.mSignatures[0]);
+                    if (!libCertDigest.equalsIgnoreCase(expectedCertDigest)) {
+                        throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
+                                "Package " + packageName + " requires differently signed" +
+                                        " static shared library; failing!");
+                    }
+                }
+
+                if (outUsedLibraries == null) {
+                    outUsedLibraries = new ArraySet<>();
+                }
+                addSharedLibraryLPr(outUsedLibraries, libEntry, changingLib);
             }
         }
+        return outUsedLibraries;
     }
 
     private static boolean hasString(List<String> list, List<String> which) {
@@ -8308,31 +8682,36 @@
         return false;
     }
 
-    private void updateAllSharedLibrariesLPw() {
-        for (PackageParser.Package pkg : mPackages.values()) {
-            try {
-                updateSharedLibrariesLPr(pkg, null);
-            } catch (PackageManagerException e) {
-                Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
-            }
-        }
-    }
-
     private ArrayList<PackageParser.Package> updateAllSharedLibrariesLPw(
             PackageParser.Package changingPkg) {
         ArrayList<PackageParser.Package> res = null;
         for (PackageParser.Package pkg : mPackages.values()) {
-            if (hasString(pkg.usesLibraries, changingPkg.libraryNames)
-                    || hasString(pkg.usesOptionalLibraries, changingPkg.libraryNames)) {
-                if (res == null) {
-                    res = new ArrayList<PackageParser.Package>();
+            if (changingPkg != null
+                    && !hasString(pkg.usesLibraries, changingPkg.libraryNames)
+                    && !hasString(pkg.usesOptionalLibraries, changingPkg.libraryNames)
+                    && !ArrayUtils.contains(pkg.usesStaticLibraries,
+                            changingPkg.staticSharedLibName)) {
+                return null;
+            }
+            if (res == null) {
+                res = new ArrayList<>();
+            }
+            res.add(pkg);
+            try {
+                updateSharedLibrariesLPr(pkg, changingPkg);
+            } catch (PackageManagerException e) {
+                // If a system app update or an app and a required lib missing we
+                // delete the package and for updated system apps keep the data as
+                // it is better for the user to reinstall than to be in an limbo
+                // state. Also libs disappearing under an app should never happen
+                // - just in case.
+                if (!pkg.isSystemApp() || pkg.isUpdatedSystemApp()) {
+                    final int flags = pkg.isUpdatedSystemApp()
+                            ? PackageManager.DELETE_KEEP_DATA : 0;
+                    deletePackageLIF(pkg.packageName, null, true, sUserManager.getUserIds(),
+                            flags , null, true, null);
                 }
-                res.add(pkg);
-                try {
-                    updateSharedLibrariesLPr(pkg, changingPkg);
-                } catch (PackageManagerException e) {
-                    Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
-                }
+                Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
             }
         }
         return res;
@@ -8590,9 +8969,17 @@
                     pkgSetting == null ? null : new PackageSetting(pkgSetting);
             final PackageSetting disabledPkgSetting =
                     mSettings.getDisabledSystemPkgLPr(pkg.packageName);
+
+            String[] usesStaticLibraries = null;
+            if (pkg.usesStaticLibraries != null) {
+                usesStaticLibraries = new String[pkg.usesStaticLibraries.size()];
+                pkg.usesStaticLibraries.toArray(usesStaticLibraries);
+            }
+
             if (pkgSetting == null) {
                 final String parentPackageName = (pkg.parentPackage != null)
                         ? pkg.parentPackage.packageName : null;
+
                 // REMOVE SharedUserSetting from method; update in a separate call
                 pkgSetting = Settings.createNewSetting(pkg.packageName, origPackage,
                         disabledPkgSetting, realName, suid, destCodeFile, destResourceFile,
@@ -8600,7 +8987,8 @@
                         pkg.applicationInfo.secondaryCpuAbi, pkg.mVersionCode,
                         pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags, user,
                         true /*allowInstall*/, parentPackageName, pkg.getChildPackageNames(),
-                        UserManagerService.getInstance());
+                        UserManagerService.getInstance(), usesStaticLibraries,
+                        pkg.usesStaticLibrariesVersions);
                 // SIDE EFFECTS; updates system state; move elsewhere
                 if (origPackage != null) {
                     mSettings.addRenamedPackageLPw(pkg.packageName, origPackage.name);
@@ -8616,7 +9004,8 @@
                         pkg.applicationInfo.nativeLibraryDir, pkg.applicationInfo.primaryCpuAbi,
                         pkg.applicationInfo.secondaryCpuAbi, pkg.applicationInfo.flags,
                         pkg.applicationInfo.privateFlags, pkg.getChildPackageNames(),
-                        UserManagerService.getInstance());
+                        UserManagerService.getInstance(), usesStaticLibraries,
+                        pkg.usesStaticLibrariesVersions);
             }
             // SIDE EFFECTS; persists system state to files on disk; move elsewhere
             mSettings.writeUserRestrictionsLPw(pkgSetting, oldPkgSetting);
@@ -8653,12 +9042,15 @@
                 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
             }
 
-            if ((policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+            if ((scanFlags & SCAN_BOOTING) == 0
+                    && (policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
                 // Check all shared libraries and map to their actual file path.
                 // We only do this here for apps not on a system dir, because those
                 // are the only ones that can fail an install due to this.  We
                 // will take care of the system apps by updating all of their
-                // library paths after the scan is done.
+                // library paths after the scan is done. Also during the initial
+                // scan don't update any libs as we do this wholesale after all
+                // apps are scanned to avoid dependency based scanning.
                 updateSharedLibrariesLPr(pkg, null);
             }
 
@@ -8668,8 +9060,22 @@
 
             pkg.applicationInfo.uid = pkgSetting.appId;
             pkg.mExtras = pkgSetting;
-            if (shouldCheckUpgradeKeySetLP(pkgSetting, scanFlags)) {
-                if (checkUpgradeKeySetLP(pkgSetting, pkg)) {
+
+
+            // Static shared libs have same package with different versions where
+            // we internally use a synthetic package name to allow multiple versions
+            // of the same package, therefore we need to compare signatures against
+            // the package setting for the latest library version.
+            PackageSetting signatureCheckPs = pkgSetting;
+            if (pkg.applicationInfo.isStaticSharedLibrary()) {
+                SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg);
+                if (libraryEntry != null) {
+                    signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk);
+                }
+            }
+
+            if (shouldCheckUpgradeKeySetLP(signatureCheckPs, scanFlags)) {
+                if (checkUpgradeKeySetLP(signatureCheckPs, pkg)) {
                     // We just determined the app is signed correctly, so bring
                     // over the latest parsed certs.
                     pkgSetting.signatures.mSignatures = pkg.mSignatures;
@@ -8688,7 +9094,7 @@
             } else {
                 try {
                     // SIDE EFFECTS; compareSignaturesCompat() changes KeysetManagerService
-                    verifySignaturesLP(pkgSetting, pkg);
+                    verifySignaturesLP(signatureCheckPs, pkg);
                     // We just determined the app is signed correctly, so bring
                     // over the latest parsed certs.
                     pkgSetting.signatures.mSignatures = pkg.mSignatures;
@@ -8704,8 +9110,8 @@
                     // What this means is that you can't change the signatures
                     // associated with an overall shared user, which doesn't seem all
                     // that unreasonable.
-                    if (pkgSetting.sharedUser != null) {
-                        if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
+                    if (signatureCheckPs.sharedUser != null) {
+                        if (compareSignatures(signatureCheckPs.sharedUser.signatures.mSignatures,
                                 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
                             throw new PackageManagerException(
                                     INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
@@ -8946,7 +9352,7 @@
     }
 
     /**
-     * Asserts the parsed package is valid according to teh given policy. If the
+     * Asserts the parsed package is valid according to the given policy. If the
      * package is invalid, for whatever reason, throws {@link PackgeManagerException}.
      * <p>
      * Implementation detail: This method must NOT have any side effects. It would
@@ -8992,6 +9398,128 @@
                         + " already installed.  Skipping duplicate.");
             }
 
+            if (pkg.applicationInfo.isStaticSharedLibrary()) {
+                // Static libs have a synthetic package name containing the version
+                // but we still want the base name to be unique.
+                if (mPackages.containsKey(pkg.manifestPackageName)) {
+                    throw new PackageManagerException(
+                            "Duplicate static shared lib provider package");
+                }
+
+                // Static shared libraries should have at least O target SDK
+                if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.O) {
+                    throw new PackageManagerException(
+                            "Packages declaring static-shared libs must target O SDK or higher");
+                }
+
+                // Package declaring static a shared lib cannot be ephemeral
+                if (pkg.applicationInfo.isEphemeralApp()) {
+                    throw new PackageManagerException(
+                            "Packages declaring static-shared libs cannot be ephemeral");
+                }
+
+                // Package declaring static a shared lib cannot be renamed since the package
+                // name is synthetic and apps can't code around package manager internals.
+                if (!ArrayUtils.isEmpty(pkg.mOriginalPackages)) {
+                    throw new PackageManagerException(
+                            "Packages declaring static-shared libs cannot be renamed");
+                }
+
+                // Package declaring static a shared lib cannot declare child packages
+                if (!ArrayUtils.isEmpty(pkg.childPackages)) {
+                    throw new PackageManagerException(
+                            "Packages declaring static-shared libs cannot have child packages");
+                }
+
+                // Package declaring static a shared lib cannot declare dynamic libs
+                if (!ArrayUtils.isEmpty(pkg.libraryNames)) {
+                    throw new PackageManagerException(
+                            "Packages declaring static-shared libs cannot declare dynamic libs");
+                }
+
+                // Package declaring static a shared lib cannot declare shared users
+                if (pkg.mSharedUserId != null) {
+                    throw new PackageManagerException(
+                            "Packages declaring static-shared libs cannot declare shared users");
+                }
+
+                // Static shared libs cannot declare activities
+                if (!pkg.activities.isEmpty()) {
+                    throw new PackageManagerException(
+                            "Static shared libs cannot declare activities");
+                }
+
+                // Static shared libs cannot declare services
+                if (!pkg.services.isEmpty()) {
+                    throw new PackageManagerException(
+                            "Static shared libs cannot declare services");
+                }
+
+                // Static shared libs cannot declare providers
+                if (!pkg.providers.isEmpty()) {
+                    throw new PackageManagerException(
+                            "Static shared libs cannot declare content providers");
+                }
+
+                // Static shared libs cannot declare receivers
+                if (!pkg.receivers.isEmpty()) {
+                    throw new PackageManagerException(
+                            "Static shared libs cannot declare broadcast receivers");
+                }
+
+                // Static shared libs cannot declare permission groups
+                if (!pkg.permissionGroups.isEmpty()) {
+                    throw new PackageManagerException(
+                            "Static shared libs cannot declare permission groups");
+                }
+
+                // Static shared libs cannot declare permissions
+                if (!pkg.permissions.isEmpty()) {
+                    throw new PackageManagerException(
+                            "Static shared libs cannot declare permissions");
+                }
+
+                // Static shared libs cannot declare protected broadcasts
+                if (pkg.protectedBroadcasts != null) {
+                    throw new PackageManagerException(
+                            "Static shared libs cannot declare protected broadcasts");
+                }
+
+                // Static shared libs cannot be overlay targets
+                if (pkg.mOverlayTarget != null) {
+                    throw new PackageManagerException(
+                            "Static shared libs cannot be overlay targets");
+                }
+
+                // The version codes must be ordered as lib versions
+                int minVersionCode = Integer.MIN_VALUE;
+                int maxVersionCode = Integer.MAX_VALUE;
+
+                SparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(
+                        pkg.staticSharedLibName);
+                if (versionedLib != null) {
+                    final int versionCount = versionedLib.size();
+                    for (int i = 0; i < versionCount; i++) {
+                        SharedLibraryInfo libInfo = versionedLib.valueAt(i).info;
+                        // TODO: We will change version code to long, so in the new API it is long
+                        final int libVersionCode = (int) libInfo.getDeclaringPackage()
+                                .getVersionCode();
+                        if (libInfo.getVersion() <  pkg.staticSharedLibVersion) {
+                            minVersionCode = Math.max(minVersionCode, libVersionCode + 1);
+                        } else if (libInfo.getVersion() >  pkg.staticSharedLibVersion) {
+                            maxVersionCode = Math.min(maxVersionCode, libVersionCode - 1);
+                        } else {
+                            minVersionCode = maxVersionCode = libVersionCode;
+                            break;
+                        }
+                    }
+                }
+                if (pkg.mVersionCode < minVersionCode || pkg.mVersionCode > maxVersionCode) {
+                    throw new PackageManagerException("Static shared"
+                            + " lib version codes must be ordered as lib versions");
+                }
+            }
+
             // Only privileged apps and updated privileged apps can add child packages.
             if (pkg.childPackages != null && !pkg.childPackages.isEmpty()) {
                 if ((policyFlags & PARSE_IS_PRIVILEGED) == 0) {
@@ -9072,6 +9600,45 @@
         }
     }
 
+    private boolean addSharedLibraryLPw(String path, String apk, String name, int version,
+            int type, String declaringPackageName, int declaringVersionCode) {
+        SparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(name);
+        if (versionedLib == null) {
+            versionedLib = new SparseArray<>();
+            mSharedLibraries.put(name, versionedLib);
+            if (type == SharedLibraryInfo.TYPE_STATIC) {
+                mStaticLibsByDeclaringPackage.put(declaringPackageName, versionedLib);
+            }
+        } else if (versionedLib.indexOfKey(version) >= 0) {
+            return false;
+        }
+        SharedLibraryEntry libEntry = new SharedLibraryEntry(path, apk, name,
+                version, type, declaringPackageName, declaringVersionCode);
+        versionedLib.put(version, libEntry);
+        return true;
+    }
+
+    private boolean removeSharedLibraryLPw(String name, int version) {
+        SparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(name);
+        if (versionedLib == null) {
+            return false;
+        }
+        final int libIdx = versionedLib.indexOfKey(version);
+        if (libIdx < 0) {
+            return false;
+        }
+        SharedLibraryEntry libEntry = versionedLib.valueAt(libIdx);
+        versionedLib.remove(version);
+        if (versionedLib.size() <= 0) {
+            mSharedLibraries.remove(name);
+            if (libEntry.info.getType() == SharedLibraryInfo.TYPE_STATIC) {
+                mStaticLibsByDeclaringPackage.remove(libEntry.info.getDeclaringPackage()
+                        .getPackageName());
+            }
+        }
+        return true;
+    }
+
     /**
      * Adds a scanned package to the system. When this method is finished, the package will
      * be available for query, resolution, etc...
@@ -9124,10 +9691,30 @@
         ArrayList<PackageParser.Package> clientLibPkgs = null;
         // writer
         synchronized (mPackages) {
-            if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
-                // Only system apps can add new shared libraries.
+            boolean hasStaticSharedLibs = false;
+
+            // Any app can add new static shared libraries
+            if (pkg.staticSharedLibName != null) {
+                // Static shared libs don't allow renaming as they have synthetic package
+                // names to allow install of multiple versions, so use name from manifest.
+                if (addSharedLibraryLPw(null, pkg.packageName, pkg.staticSharedLibName,
+                        pkg.staticSharedLibVersion, SharedLibraryInfo.TYPE_STATIC,
+                        pkg.manifestPackageName, pkg.mVersionCode)) {
+                    hasStaticSharedLibs = true;
+                } else {
+                    Slog.w(TAG, "Package " + pkg.packageName + " library "
+                                + pkg.staticSharedLibName + " already exists; skipping");
+                }
+                // Static shared libs cannot be updated once installed since they
+                // use synthetic package name which includes the version code, so
+                // not need to update other packages's shared lib dependencies.
+            }
+
+            if (!hasStaticSharedLibs
+                    && (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                // Only system apps can add new dynamic shared libraries.
                 if (pkg.libraryNames != null) {
-                    for (int i=0; i<pkg.libraryNames.size(); i++) {
+                    for (int i = 0; i < pkg.libraryNames.size(); i++) {
                         String name = pkg.libraryNames.get(i);
                         boolean allowed = false;
                         if (pkg.isUpdatedSystemApp()) {
@@ -9144,7 +9731,7 @@
                             final PackageSetting sysPs = mSettings
                                     .getDisabledSystemPkgLPr(pkg.packageName);
                             if (sysPs.pkg != null && sysPs.pkg.libraryNames != null) {
-                                for (int j=0; j<sysPs.pkg.libraryNames.size(); j++) {
+                                for (int j = 0; j < sysPs.pkg.libraryNames.size(); j++) {
                                     if (name.equals(sysPs.pkg.libraryNames.get(j))) {
                                         allowed = true;
                                         break;
@@ -9155,9 +9742,10 @@
                             allowed = true;
                         }
                         if (allowed) {
-                            if (!mSharedLibraries.containsKey(name)) {
-                                mSharedLibraries.put(name, new SharedLibraryEntry(null, pkg.packageName));
-                            } else if (!name.equals(pkg.packageName)) {
+                            if (!addSharedLibraryLPw(null, pkg.packageName, name,
+                                    SharedLibraryInfo.VERSION_UNDEFINED,
+                                    SharedLibraryInfo.TYPE_DYNAMIC,
+                                    pkg.packageName, pkg.mVersionCode)) {
                                 Slog.w(TAG, "Package " + pkg.packageName + " library "
                                         + name + " already exists; skipping");
                             }
@@ -9166,6 +9754,7 @@
                                     + name + " that is not declared on system image; skipping");
                         }
                     }
+
                     if ((scanFlags & SCAN_BOOTING) == 0) {
                         // If we are not booting, we need to update any applications
                         // that are clients of our shared library.  If we are booting,
@@ -10379,11 +10968,9 @@
         if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
             // Only system apps can hold shared libraries.
             if (pkg.libraryNames != null) {
-                for (i=0; i<pkg.libraryNames.size(); i++) {
+                for (i = 0; i < pkg.libraryNames.size(); i++) {
                     String name = pkg.libraryNames.get(i);
-                    SharedLibraryEntry cur = mSharedLibraries.get(name);
-                    if (cur != null && cur.apk != null && cur.apk.equals(pkg.packageName)) {
-                        mSharedLibraries.remove(name);
+                    if (removeSharedLibraryLPw(name, 0)) {
                         if (DEBUG_REMOVE && chatty) {
                             if (r == null) {
                                 r = new StringBuilder(256);
@@ -10396,6 +10983,23 @@
                 }
             }
         }
+
+        r = null;
+
+        // Any package can hold static shared libraries.
+        if (pkg.staticSharedLibName != null) {
+            if (removeSharedLibraryLPw(pkg.staticSharedLibName, pkg.staticSharedLibVersion)) {
+                if (DEBUG_REMOVE && chatty) {
+                    if (r == null) {
+                        r = new StringBuilder(256);
+                    } else {
+                        r.append(' ');
+                    }
+                    r.append(pkg.staticSharedLibName);
+                }
+            }
+        }
+
         if (r != null) {
             if (DEBUG_REMOVE) Log.d(TAG, "  Libraries: " + r);
         }
@@ -12457,6 +13061,16 @@
                     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.
+                PackageParser.Package pkg = mPackages.get(packageName);
+                if (pkg != null && pkg.staticSharedLibName != null) {
+                    Slog.w(TAG, "Cannot hide package: " + packageName
+                            + " providing static shared library: "
+                            + pkg.staticSharedLibName);
+                    return false;
+                }
                 // Only allow protected packages to hide themselves.
                 if (hidden && !UserHandle.isSameApp(uid, pkgSetting.appId)
                         && mProtectedPackages.isPackageStateProtected(userId, packageName)) {
@@ -12717,6 +13331,17 @@
             return false;
         }
 
+        // 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.
+        PackageParser.Package pkg = mPackages.get(packageName);
+        if (pkg != null && pkg.applicationInfo.isStaticSharedLibrary()) {
+            Slog.w(TAG, "Cannot suspend package: " + packageName
+                    + " providing static shared library: "
+                    + pkg.staticSharedLibName);
+            return false;
+        }
+
         return true;
     }
 
@@ -15150,6 +15775,7 @@
         res.removedInfo = new PackageRemovedInfo();
         res.removedInfo.uid = oldPackage.applicationInfo.uid;
         res.removedInfo.removedPackage = oldPackage.packageName;
+        res.removedInfo.isStaticSharedLib = pkg.staticSharedLibName != null;
         res.removedInfo.isUpdate = true;
         res.removedInfo.origUsers = installedUsers;
         final PackageSetting ps = mSettings.getPackageLPr(pkgName);
@@ -15812,6 +16438,19 @@
             return;
         }
 
+        if (pkg.applicationInfo.isStaticSharedLibrary()) {
+            // Static shared libraries have synthetic package names
+            renameStaticSharedLibraryPackage(pkg);
+
+            // No static shared libs on external storage
+            if (onExternal) {
+                Slog.i(TAG, "Static shared libs can only be installed on internal storage.");
+                res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
+                        "Packages declaring static-shared libs cannot be updated");
+                return;
+            }
+        }
+
         // If we are installing a clustered package add results for the children
         if (pkg.childPackages != null) {
             synchronized (mPackages) {
@@ -15936,11 +16575,23 @@
             if (ps != null) {
                 if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);
 
+                // Static shared libs have same package with different versions where
+                // we internally use a synthetic package name to allow multiple versions
+                // of the same package, therefore we need to compare signatures against
+                // the package setting for the latest library version.
+                PackageSetting signatureCheckPs = ps;
+                if (pkg.applicationInfo.isStaticSharedLibrary()) {
+                    SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg);
+                    if (libraryEntry != null) {
+                        signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk);
+                    }
+                }
+
                 // Quick sanity check that we're signed correctly if updating;
                 // we'll check this again later when scanning, but we want to
                 // bail early here before tripping over redefined permissions.
-                if (shouldCheckUpgradeKeySetLP(ps, scanFlags)) {
-                    if (!checkUpgradeKeySetLP(ps, pkg)) {
+                if (shouldCheckUpgradeKeySetLP(signatureCheckPs, scanFlags)) {
+                    if (!checkUpgradeKeySetLP(signatureCheckPs, pkg)) {
                         res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
                                 + pkg.packageName + " upgrade keys do not match the "
                                 + "previously installed version");
@@ -15948,7 +16599,7 @@
                     }
                 } else {
                     try {
-                        verifySignaturesLP(ps, pkg);
+                        verifySignaturesLP(signatureCheckPs, pkg);
                     } catch (PackageManagerException e) {
                         res.setError(e.error, e.getMessage());
                         return;
@@ -16065,14 +16716,6 @@
                 return;
             }
 
-            // Shared libraries for the package need to be updated.
-            synchronized (mPackages) {
-                try {
-                    updateSharedLibrariesLPr(pkg, null);
-                } catch (PackageManagerException e) {
-                    Slog.e(TAG, "updateSharedLibrariesLPw failed: " + e.getMessage());
-                }
-            }
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
             // Do not run PackageDexOptimizer through the local performDexOpt
             // method because `pkg` may not be in `mPackages` yet.
@@ -16100,6 +16743,18 @@
         try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags,
                 "installPackageLI")) {
             if (replace) {
+                if (pkg.applicationInfo.isStaticSharedLibrary()) {
+                    // Static libs have a synthetic package name containing the version
+                    // and cannot be updated as an update would get a new package name,
+                    // unless this is the exact same version code which is useful for
+                    // development.
+                    PackageParser.Package existingPkg = mPackages.get(pkg.packageName);
+                    if (existingPkg != null && existingPkg.mVersionCode != pkg.mVersionCode) {
+                        res.setError(INSTALL_FAILED_DUPLICATE_PACKAGE, "Packages declaring "
+                                + "static-shared libs cannot be updated");
+                        return;
+                    }
+                }
                 replacePackageLIF(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
                         installerPackageName, res, args.installReason);
             } else {
@@ -16345,22 +17000,37 @@
     }
 
     @Override
-    public void deletePackageAsUser(String packageName, IPackageDeleteObserver observer, int userId,
-            int flags) {
-        deletePackage(packageName, new LegacyPackageDeleteObserver(observer).getBinder(), userId,
-                flags);
+    public void deletePackageAsUser(String packageName, int versionCode,
+            IPackageDeleteObserver observer, int userId, int flags) {
+        deletePackageVersioned(new VersionedPackage(packageName, versionCode),
+                new LegacyPackageDeleteObserver(observer).getBinder(), userId, flags);
     }
 
     @Override
-    public void deletePackage(final String packageName,
+    public void deletePackageVersioned(VersionedPackage versionedPackage,
             final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.DELETE_PACKAGES, null);
-        Preconditions.checkNotNull(packageName);
+        Preconditions.checkNotNull(versionedPackage);
         Preconditions.checkNotNull(observer);
+        Preconditions.checkArgumentInRange(versionedPackage.getVersionCode(),
+                PackageManager.VERSION_CODE_HIGHEST,
+                Integer.MAX_VALUE, "versionCode must be >= -1");
+
+        final String packageName = versionedPackage.getPackageName();
+        // TODO: We will change version code to long, so in the new API it is long
+        final int versionCode = (int) versionedPackage.getVersionCode();
+        final String internalPackageName;
+        synchronized (mPackages) {
+            // Normalize package name to handle renamed packages and static libs
+            internalPackageName = resolveInternalPackageNameLPr(versionedPackage.getPackageName(),
+                    // TODO: We will change version code to long, so in the new API it is long
+                    (int) versionedPackage.getVersionCode());
+        }
+
         final int uid = Binder.getCallingUid();
-        if (!isOrphaned(packageName)
-                && !isCallerAllowedToSilentlyUninstall(uid, packageName)) {
+        if (!isOrphaned(internalPackageName)
+                && !isCallerAllowedToSilentlyUninstall(uid, internalPackageName)) {
             try {
                 final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
                 intent.setData(Uri.fromParts(PACKAGE_SCHEME, packageName, null));
@@ -16387,7 +17057,7 @@
             return;
         }
 
-        if (!deleteAllUsers && getBlockUninstallForUser(packageName, userId)) {
+        if (!deleteAllUsers && getBlockUninstallForUser(internalPackageName, userId)) {
             try {
                 observer.onPackageDeleted(packageName,
                         PackageManager.DELETE_FAILED_OWNER_BLOCKED, null);
@@ -16397,8 +17067,10 @@
         }
 
         if (DEBUG_REMOVE) {
-            Slog.d(TAG, "deletePackageAsUser: pkg=" + packageName + " user=" + userId
-                    + " deleteAllUsers: " + deleteAllUsers );
+            Slog.d(TAG, "deletePackageAsUser: pkg=" + internalPackageName + " user=" + userId
+                    + " deleteAllUsers: " + deleteAllUsers + " version="
+                    + (versionCode == PackageManager.VERSION_CODE_HIGHEST
+                    ? "VERSION_CODE_HIGHEST" : versionCode));
         }
         // Queue up an async operation since the package deletion may take a little while.
         mHandler.post(new Runnable() {
@@ -16406,18 +17078,22 @@
                 mHandler.removeCallbacks(this);
                 int returnCode;
                 if (!deleteAllUsers) {
-                    returnCode = deletePackageX(packageName, userId, deleteFlags);
+                    returnCode = deletePackageX(internalPackageName, versionCode,
+                            userId, deleteFlags);
                 } else {
-                    int[] blockUninstallUserIds = getBlockUninstallForUsers(packageName, users);
+                    int[] blockUninstallUserIds = getBlockUninstallForUsers(
+                            internalPackageName, users);
                     // If nobody is blocking uninstall, proceed with delete for all users
                     if (ArrayUtils.isEmpty(blockUninstallUserIds)) {
-                        returnCode = deletePackageX(packageName, userId, deleteFlags);
+                        returnCode = deletePackageX(internalPackageName, versionCode,
+                                userId, deleteFlags);
                     } else {
                         // Otherwise uninstall individually for users with blockUninstalls=false
                         final int userFlags = deleteFlags & ~PackageManager.DELETE_ALL_USERS;
                         for (int userId : users) {
                             if (!ArrayUtils.contains(blockUninstallUserIds, userId)) {
-                                returnCode = deletePackageX(packageName, userId, userFlags);
+                                returnCode = deletePackageX(internalPackageName, versionCode,
+                                        userId, userFlags);
                                 if (returnCode != PackageManager.DELETE_SUCCEEDED) {
                                     Slog.w(TAG, "Package delete failed for user " + userId
                                             + ", returnCode " + returnCode);
@@ -16438,6 +17114,80 @@
         });
     }
 
+    private String resolveExternalPackageNameLPr(PackageParser.Package pkg) {
+        if (pkg.staticSharedLibName != null) {
+            return pkg.manifestPackageName;
+        }
+        return pkg.packageName;
+    }
+
+    private String resolveInternalPackageNameLPr(String packageName, int versionCode) {
+        // Handle renamed packages
+        String normalizedPackageName = mSettings.getRenamedPackageLPr(packageName);
+        packageName = normalizedPackageName != null ? normalizedPackageName : packageName;
+
+        // Is this a static library?
+        SparseArray<SharedLibraryEntry> versionedLib =
+                mStaticLibsByDeclaringPackage.get(packageName);
+        if (versionedLib == null || versionedLib.size() <= 0) {
+            return packageName;
+        }
+
+        // Figure out which lib versions the caller can see
+        SparseIntArray versionsCallerCanSee = null;
+        final int callingAppId = UserHandle.getAppId(Binder.getCallingUid());
+        if (callingAppId != Process.SYSTEM_UID && callingAppId != Process.SHELL_UID
+                && callingAppId != Process.ROOT_UID) {
+            versionsCallerCanSee = new SparseIntArray();
+            String libName = versionedLib.valueAt(0).info.getName();
+            String[] uidPackages = getPackagesForUid(Binder.getCallingUid());
+            if (uidPackages != null) {
+                for (String uidPackage : uidPackages) {
+                    PackageSetting ps = mSettings.getPackageLPr(uidPackage);
+                    final int libIdx = ArrayUtils.indexOf(ps.usesStaticLibraries, libName);
+                    if (libIdx >= 0) {
+                        final int libVersion = ps.usesStaticLibrariesVersions[libIdx];
+                        versionsCallerCanSee.append(libVersion, libVersion);
+                    }
+                }
+            }
+        }
+
+        // Caller can see nothing - done
+        if (versionsCallerCanSee != null && versionsCallerCanSee.size() <= 0) {
+            return packageName;
+        }
+
+        // Find the version the caller can see and the app version code
+        SharedLibraryEntry highestVersion = null;
+        final int versionCount = versionedLib.size();
+        for (int i = 0; i < versionCount; i++) {
+            SharedLibraryEntry libEntry = versionedLib.valueAt(i);
+            if (versionsCallerCanSee != null && versionsCallerCanSee.indexOfKey(
+                    libEntry.info.getVersion()) < 0) {
+                continue;
+            }
+            // TODO: We will change version code to long, so in the new API it is long
+            final int libVersionCode = (int) libEntry.info.getDeclaringPackage().getVersionCode();
+            if (versionCode != PackageManager.VERSION_CODE_HIGHEST) {
+                if (libVersionCode == versionCode) {
+                    return libEntry.apk;
+                }
+            } else if (highestVersion == null) {
+                highestVersion = libEntry;
+            } else if (libVersionCode  > highestVersion.info
+                    .getDeclaringPackage().getVersionCode()) {
+                highestVersion = libEntry;
+            }
+        }
+
+        if (highestVersion != null) {
+            return highestVersion.apk;
+        }
+
+        return packageName;
+    }
+
     private boolean isCallerAllowedToSilentlyUninstall(int callingUid, String pkgName) {
         if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID
               || callingUid == Process.SYSTEM_UID) {
@@ -16536,7 +17286,7 @@
      *  persisting settings for later use
      *  sending a broadcast if necessary
      */
-    private int deletePackageX(String packageName, int userId, int deleteFlags) {
+    private int deletePackageX(String packageName, int versionCode, int userId, int deleteFlags) {
         final PackageRemovedInfo info = new PackageRemovedInfo();
         final boolean res;
 
@@ -16559,6 +17309,32 @@
                 Slog.w(TAG, "Not removing non-existent package " + packageName);
                 return PackageManager.DELETE_FAILED_INTERNAL_ERROR;
             }
+
+            if (versionCode != PackageManager.VERSION_CODE_HIGHEST
+                    && uninstalledPs.versionCode != versionCode) {
+                Slog.w(TAG, "Not removing package " + packageName + " with versionCode "
+                        + uninstalledPs.versionCode + " != " + versionCode);
+                return PackageManager.DELETE_FAILED_INTERNAL_ERROR;
+            }
+
+            // Static shared libs can be declared by any package, so let us not
+            // allow removing a package if it provides a lib others depend on.
+            PackageParser.Package pkg = mPackages.get(packageName);
+            if (pkg != null && pkg.staticSharedLibName != null) {
+                SharedLibraryEntry libEntry = getSharedLibraryEntryLPr(pkg.staticSharedLibName,
+                        pkg.staticSharedLibVersion);
+                if (libEntry != null) {
+                    List<VersionedPackage> libClientPackages = getPackagesUsingSharedLibraryLPr(
+                            libEntry.info, 0, userId);
+                    if (!ArrayUtils.isEmpty(libClientPackages)) {
+                        Slog.w(TAG, "Not removing package " + pkg.manifestPackageName
+                                + " hosting lib " + libEntry.info.getName() + " version "
+                                + libEntry.info.getVersion()  + " used by " + libClientPackages);
+                        return PackageManager.DELETE_FAILED_USED_SHARED_LIBRARY;
+                    }
+                }
+            }
+
             allUsers = sUserManager.getUserIds();
             info.origUsers = uninstalledPs.queryInstalledUsers(allUsers, true);
         }
@@ -16617,6 +17393,7 @@
         boolean isUpdate;
         boolean dataRemoved;
         boolean removedForAllUsers;
+        boolean isStaticSharedLib;
         // Clean up resources deleted packages.
         InstallArgs args = null;
         ArrayMap<String, PackageRemovedInfo> removedChildPackages;
@@ -16668,6 +17445,12 @@
         }
 
         private void sendPackageRemovedBroadcastInternal(boolean killApp) {
+            // Don't send static shared library removal broadcasts as these
+            // libs are visible only the the apps that depend on them an one
+            // cannot remove the library if it has a dependency.
+            if (isStaticSharedLib) {
+                return;
+            }
             Bundle extras = new Bundle(2);
             extras.putInt(Intent.EXTRA_UID, removedAppId >= 0  ? removedAppId : uid);
             extras.putBoolean(Intent.EXTRA_DATA_REMOVED, dataRemoved);
@@ -16711,6 +17494,8 @@
             deletedPs = mSettings.mPackages.get(packageName);
             if (outInfo != null) {
                 outInfo.removedPackage = packageName;
+                outInfo.isStaticSharedLib = deletedPkg != null
+                        && deletedPkg.staticSharedLibName != null;
                 outInfo.removedUsers = deletedPs != null
                         ? deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true)
                         : null;
@@ -16738,15 +17523,18 @@
             schedulePackageCleaning(packageName, UserHandle.USER_ALL, true);
         }
 
+        int removedAppId = -1;
+
         // writer
         synchronized (mPackages) {
             if (deletedPs != null) {
                 if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
                     clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL);
                     clearDefaultBrowserIfNeeded(packageName);
+                    mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName);
+                    removedAppId = mSettings.removePackageLPw(packageName);
                     if (outInfo != null) {
-                        mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName);
-                        outInfo.removedAppId = mSettings.removePackageLPw(packageName);
+                        outInfo.removedAppId = removedAppId;
                     }
                     updatePermissionsLPw(deletedPs.name, null, 0);
                     if (deletedPs.sharedUser != null) {
@@ -16796,10 +17584,10 @@
                 mSettings.writeLPr();
             }
         }
-        if (outInfo != null) {
+        if (removedAppId != -1) {
             // A user ID was deleted here. Go through all users and remove it
             // from KeyStore.
-            removeKeystoreDataIfNeeded(UserHandle.USER_ALL, outInfo.removedAppId);
+            removeKeystoreDataIfNeeded(UserHandle.USER_ALL, removedAppId);
         }
     }
 
@@ -16915,12 +17703,6 @@
                     + e.getMessage());
             return false;
         }
-        try {
-            // update shared libraries for the newly re-installed system package
-            updateSharedLibrariesLPr(newPkg, null);
-        } catch (PackageManagerException e) {
-            Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
-        }
 
         prepareAppDataAfterInstallLIF(newPkg);
 
@@ -17033,6 +17815,15 @@
                 Log.i(TAG, "Package doesn't exist in set block uninstall " + packageName);
                 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.
+            PackageParser.Package pkg = mPackages.get(packageName);
+            if (pkg != null && pkg.staticSharedLibName != null) {
+                Slog.w(TAG, "Cannot block uninstall of package: " + packageName
+                        + " providing static shared library: " + pkg.staticSharedLibName);
+                return false;
+            }
             if (!ps.getInstalled(userId)) {
                 // Can't block uninstall for an app that is not installed or enabled.
                 Log.i(TAG, "Package not installed in set block uninstall " + packageName);
@@ -17094,7 +17885,6 @@
         if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageLI: " + packageName + " user " + user);
 
         PackageSetting ps;
-
         synchronized (mPackages) {
             ps = mSettings.mPackages.get(packageName);
             if (ps == null) {
@@ -17287,6 +18077,7 @@
 
         if (outInfo != null) {
             outInfo.removedPackage = ps.name;
+            outInfo.isStaticSharedLib = pkg != null && pkg.staticSharedLibName != null;
             outInfo.removedAppId = ps.appId;
             outInfo.removedUsers = userIds;
         }
@@ -19307,6 +20098,7 @@
                     pw.println("Error: check-permission missing package argument");
                     return;
                 }
+
                 String pkg = args[opti];
                 opti++;
                 int user = UserHandle.getUserId(Binder.getCallingUid());
@@ -19319,6 +20111,10 @@
                         return;
                     }
                 }
+
+                // Normalize package name to handle renamed packages and static libs
+                pkg = resolveInternalPackageNameLPr(pkg, PackageManager.VERSION_CODE_HIGHEST);
+
                 pw.println(checkPermission(perm, pkg, user));
                 return;
             } else if ("l".equals(cmd) || "libraries".equals(cmd)) {
@@ -19471,41 +20267,41 @@
                 boolean printedHeader = false;
                 final Iterator<String> it = mSharedLibraries.keySet().iterator();
                 while (it.hasNext()) {
-                    String name = it.next();
-                    SharedLibraryEntry ent = mSharedLibraries.get(name);
-                    if (!checkin) {
-                        if (!printedHeader) {
-                            if (dumpState.onTitlePrinted())
-                                pw.println();
-                            pw.println("Libraries:");
-                            printedHeader = true;
-                        }
-                        pw.print("  ");
-                    } else {
-                        pw.print("lib,");
+                    String libName = it.next();
+                    SparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(libName);
+                    if (versionedLib == null) {
+                        continue;
                     }
-                    pw.print(name);
-                    if (!checkin) {
-                        pw.print(" -> ");
-                    }
-                    if (ent.path != null) {
+                    final int versionCount = versionedLib.size();
+                    for (int i = 0; i < versionCount; i++) {
+                        SharedLibraryEntry libEntry = versionedLib.valueAt(i);
                         if (!checkin) {
-                            pw.print("(jar) ");
-                            pw.print(ent.path);
+                            if (!printedHeader) {
+                                if (dumpState.onTitlePrinted())
+                                    pw.println();
+                                pw.println("Libraries:");
+                                printedHeader = true;
+                            }
+                            pw.print("  ");
                         } else {
-                            pw.print(",jar,");
-                            pw.print(ent.path);
+                            pw.print("lib,");
                         }
-                    } else {
+                        pw.print(libEntry.info.getName());
+                        if (libEntry.info.isStatic()) {
+                            pw.print(" version=" + libEntry.info.getVersion());
+                        }
                         if (!checkin) {
-                            pw.print("(apk) ");
-                            pw.print(ent.apk);
-                        } else {
-                            pw.print(",apk,");
-                            pw.print(ent.apk);
+                            pw.print(" -> ");
                         }
+                        if (libEntry.path != null) {
+                            pw.print(" (jar) ");
+                            pw.print(libEntry.path);
+                        } else {
+                            pw.print(" (apk) ");
+                            pw.print(libEntry.apk);
+                        }
+                        pw.println();
                     }
-                    pw.println();
                 }
             }
 
@@ -20619,14 +21415,29 @@
         }
     }
 
+    private List<String> collectAbsoluteCodePaths() {
+        synchronized (mPackages) {
+            List<String> codePaths = new ArrayList<>();
+            final int packageCount = mSettings.mPackages.size();
+            for (int i = 0; i < packageCount; i++) {
+                final PackageSetting ps = mSettings.mPackages.valueAt(i);
+                codePaths.add(ps.codePath.getAbsolutePath());
+            }
+            return codePaths;
+        }
+    }
+
     /**
      * Examine all apps present on given mounted volume, and destroy apps that
      * aren't expected, either due to uninstallation or reinstallation on
      * another volume.
      */
     private void reconcileApps(String volumeUuid) {
-        final File[] files = FileUtils
-                .listFilesOrEmpty(Environment.getDataAppDirectory(volumeUuid));
+        List<String> absoluteCodePaths = collectAbsoluteCodePaths();
+        List<File> filesToDelete = null;
+
+        final File[] files = FileUtils.listFilesOrEmpty(
+                Environment.getDataAppDirectory(volumeUuid));
         for (File file : files) {
             final boolean isPackage = (isApkFile(file) || file.isDirectory())
                     && !PackageInstallerService.isStageName(file.getName());
@@ -20635,15 +21446,33 @@
                 continue;
             }
 
-            try {
-                final PackageLite pkg = PackageParser.parsePackageLite(file,
-                        PackageParser.PARSE_MUST_BE_APK);
-                assertPackageKnown(volumeUuid, pkg.packageName);
+            String absolutePath = file.getAbsolutePath();
 
-            } catch (PackageParserException | PackageManagerException e) {
-                logCriticalInfo(Log.WARN, "Destroying " + file + " due to: " + e);
+            boolean pathValid = false;
+            final int absoluteCodePathCount = absoluteCodePaths.size();
+            for (int i = 0; i < absoluteCodePathCount; i++) {
+                String absoluteCodePath = absoluteCodePaths.get(i);
+                if (absolutePath.startsWith(absoluteCodePath)) {
+                    pathValid = true;
+                    break;
+                }
+            }
+
+            if (!pathValid) {
+                if (filesToDelete == null) {
+                    filesToDelete = new ArrayList<>();
+                }
+                filesToDelete.add(file);
+            }
+        }
+
+        if (filesToDelete != null) {
+            final int fileToDeleteCount = filesToDelete.size();
+            for (int i = 0; i < fileToDeleteCount; i++) {
+                File fileToDelete = filesToDelete.get(i);
+                logCriticalInfo(Log.WARN, "Destroying orphaned" + fileToDelete);
                 synchronized (mInstallLock) {
-                    removeCodePathLI(file);
+                    removeCodePathLI(fileToDelete);
                 }
             }
         }
@@ -21421,7 +22250,8 @@
                 }
                 mHandler.post(new Runnable() {
                     public void run() {
-                        deletePackageX(packageName, userHandle, 0);
+                        deletePackageX(packageName, PackageManager.VERSION_CODE_HIGHEST,
+                                userHandle, 0);
                     } //end run
                 });
             }
@@ -21631,7 +22461,8 @@
             // after this method returns.
             mHandler.post(new Runnable() {
                 public void run() {
-                    deletePackageX(packageName, 0, PackageManager.DELETE_ALL_USERS);
+                    deletePackageX(packageName, PackageManager.VERSION_CODE_HIGHEST,
+                            0, PackageManager.DELETE_ALL_USERS);
                 }
             });
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 2751742..aa421b1 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -40,6 +40,7 @@
 import android.content.pm.PackageInstaller.SessionInfo;
 import android.content.pm.PackageInstaller.SessionParams;
 import android.content.pm.ResolveInfo;
+import android.content.pm.VersionedPackage;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.net.Uri;
@@ -663,7 +664,8 @@
                     pw.print(info.applicationInfo.sourceDir);
                     pw.print("=");
                 }
-                pw.print(info.packageName);
+                pw.print(info.packageName); pw.print( " versionCode:"
+                        + info.applicationInfo.versionCode);
                 if (listInstaller) {
                     pw.print("  installer=");
                     pw.print(mInterface.getInstallerPackageName(info.packageName));
@@ -770,6 +772,7 @@
         final PrintWriter pw = getOutPrintWriter();
         int flags = 0;
         int userId = UserHandle.USER_ALL;
+        int versionCode = PackageManager.VERSION_CODE_HIGHEST;
 
         String opt;
         while ((opt = getNextOption()) != null) {
@@ -780,6 +783,9 @@
                 case "--user":
                     userId = UserHandle.parseUserArg(getNextArgRequired());
                     break;
+                case "--versionCode":
+                    versionCode = Integer.parseInt(getNextArgRequired());
+                    break;
                 default:
                     pw.println("Error: Unknown option: " + opt);
                     return 1;
@@ -819,7 +825,8 @@
         }
 
         final LocalIntentReceiver receiver = new LocalIntentReceiver();
-        mInterface.getPackageInstaller().uninstall(packageName, null /*callerPackageName*/, flags,
+        mInterface.getPackageInstaller().uninstall(new VersionedPackage(packageName,
+                versionCode), null /*callerPackageName*/, flags,
                 receiver.getIntentSender(), userId);
 
         final Intent result = receiver.getResult();
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 80a398a..5f348ab 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -46,10 +46,12 @@
             String legacyNativeLibraryPathString, String primaryCpuAbiString,
             String secondaryCpuAbiString, String cpuAbiOverrideString,
             int pVersionCode, int pkgFlags, int privateFlags, String parentPackageName,
-            List<String> childPackageNames, int sharedUserId) {
+            List<String> childPackageNames, int sharedUserId, String[] usesStaticLibraries,
+            int[] usesStaticLibrariesVersions) {
         super(name, realName, codePath, resourcePath, legacyNativeLibraryPathString,
                 primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
-                pVersionCode, pkgFlags, privateFlags, parentPackageName, childPackageNames);
+                pVersionCode, pkgFlags, privateFlags, parentPackageName, childPackageNames,
+                usesStaticLibraries, usesStaticLibrariesVersions);
         this.sharedUserId = sharedUserId;
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index b332fa5..b63edfd 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -32,6 +32,7 @@
 
 import java.io.File;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
 
@@ -68,6 +69,9 @@
     File resourcePath;
     String resourcePathString;
 
+    String[] usesStaticLibraries;
+    int[] usesStaticLibrariesVersions;
+
     /**
      * The path under which native libraries have been unpacked. This path is
      * always derived at runtime, and is only stored here for cleanup when a
@@ -139,13 +143,16 @@
             String legacyNativeLibraryPathString, String primaryCpuAbiString,
             String secondaryCpuAbiString, String cpuAbiOverrideString,
             int pVersionCode, int pkgFlags, int pkgPrivateFlags,
-            String parentPackageName, List<String> childPackageNames) {
+            String parentPackageName, List<String> childPackageNames,
+            String[] usesStaticLibraries, int[] usesStaticLibrariesVersions) {
         super(pkgFlags, pkgPrivateFlags);
         this.name = name;
         this.realName = realName;
         this.parentPackageName = parentPackageName;
         this.childPackageNames = (childPackageNames != null)
                 ? new ArrayList<>(childPackageNames) : null;
+        this.usesStaticLibraries = usesStaticLibraries;
+        this.usesStaticLibrariesVersions = usesStaticLibrariesVersions;
         init(codePath, resourcePath, legacyNativeLibraryPathString, primaryCpuAbiString,
                 secondaryCpuAbiString, cpuAbiOverrideString, pVersionCode);
     }
@@ -250,6 +257,12 @@
         versionCode = orig.versionCode;
         volumeUuid = orig.volumeUuid;
         categoryHint = orig.categoryHint;
+        usesStaticLibraries = orig.usesStaticLibraries != null
+                ? Arrays.copyOf(orig.usesStaticLibraries,
+                        orig.usesStaticLibraries.length) : null;
+        usesStaticLibrariesVersions = orig.usesStaticLibrariesVersions != null
+                ? Arrays.copyOf(orig.usesStaticLibrariesVersions,
+                       orig.usesStaticLibrariesVersions.length) : null;
     }
 
     private PackageUserState modifyUserState(int userId) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 8761a6d..281e445 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -183,6 +183,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_STATIC_LIB = "uses-static-lib";
 
     private static final String TAG_PERSISTENT_PREFERRED_ACTIVITIES =
             "persistent-preferred-activities";
@@ -201,6 +202,7 @@
     private static final String ATTR_CODE = "code";
     private static final String ATTR_GRANTED = "granted";
     private static final String ATTR_FLAGS = "flags";
+    private static final String ATTR_VERSION = "version";
 
     private static final String ATTR_CE_DATA_INODE = "ceDataInode";
     private static final String ATTR_INSTALLED = "inst";
@@ -561,7 +563,8 @@
                 p.legacyNativeLibraryPathString, p.primaryCpuAbiString,
                 p.secondaryCpuAbiString, p.cpuAbiOverrideString,
                 p.appId, p.versionCode, p.pkgFlags, p.pkgPrivateFlags,
-                p.parentPackageName, p.childPackageNames);
+                p.parentPackageName, p.childPackageNames, p.usesStaticLibraries,
+                p.usesStaticLibrariesVersions);
         mDisabledSysPackages.remove(name);
         return ret;
     }
@@ -578,7 +581,8 @@
             String legacyNativeLibraryPathString, String primaryCpuAbiString,
             String secondaryCpuAbiString, String cpuAbiOverrideString, int uid, int vc, int
             pkgFlags, int pkgPrivateFlags, String parentPackageName,
-            List<String> childPackageNames) {
+            List<String> childPackageNames, String[] usesStaticLibraries,
+            int[] usesStaticLibraryNames) {
         PackageSetting p = mPackages.get(name);
         if (p != null) {
             if (p.appId == uid) {
@@ -591,7 +595,7 @@
         p = new PackageSetting(name, realName, codePath, resourcePath,
                 legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
                 cpuAbiOverrideString, vc, pkgFlags, pkgPrivateFlags, parentPackageName,
-                childPackageNames, 0 /*userId*/);
+                childPackageNames, 0 /*userId*/, usesStaticLibraries, usesStaticLibraryNames);
         p.appId = uid;
         if (addUserIdLPw(uid, p, name)) {
             mPackages.put(name, p);
@@ -678,7 +682,8 @@
             File codePath, File resourcePath, String legacyNativeLibraryPath, String primaryCpuAbi,
             String secondaryCpuAbi, int versionCode, int pkgFlags, int pkgPrivateFlags,
             UserHandle installUser, boolean allowInstall, String parentPkgName,
-            List<String> childPkgNames, UserManagerService userManager) {
+            List<String> childPkgNames, UserManagerService userManager,
+            String[] usesStaticLibraries, int[] usesStaticLibrariesVersions) {
         final PackageSetting pkgSetting;
         if (originalPkg != null) {
             if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
@@ -699,13 +704,16 @@
             // overwrite the signatures in the original package setting.
             pkgSetting.signatures = new PackageSignatures();
             pkgSetting.versionCode = versionCode;
+            pkgSetting.usesStaticLibraries = usesStaticLibraries;
+            pkgSetting.usesStaticLibrariesVersions = usesStaticLibrariesVersions;
             // Update new package state.
             pkgSetting.setTimeStamp(codePath.lastModified());
         } else {
             pkgSetting = new PackageSetting(pkgName, realPkgName, codePath, resourcePath,
                     legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi,
                     null /*cpuAbiOverrideString*/, versionCode, pkgFlags, pkgPrivateFlags,
-                    parentPkgName, childPkgNames, 0 /*sharedUserId*/);
+                    parentPkgName, childPkgNames, 0 /*sharedUserId*/, usesStaticLibraries,
+                    usesStaticLibrariesVersions);
             pkgSetting.setTimeStamp(codePath.lastModified());
             pkgSetting.sharedUser = sharedUser;
             // If this is not a system app, it starts out stopped.
@@ -782,7 +790,8 @@
             @NonNull File codePath, @Nullable String legacyNativeLibraryPath,
             @Nullable String primaryCpuAbi, @Nullable String secondaryCpuAbi,
             int pkgFlags, int pkgPrivateFlags, @Nullable List<String> childPkgNames,
-            @NonNull UserManagerService userManager) throws PackageManagerException {
+            @NonNull UserManagerService userManager, @Nullable String[] usesStaticLibraries,
+            @Nullable int[] usesStaticLibrariesVersions) throws PackageManagerException {
         final String pkgName = pkgSetting.name;
         if (pkgSetting.sharedUser != sharedUser) {
             PackageManagerService.reportSettingsProblem(Log.WARN,
@@ -844,6 +853,14 @@
         if (childPkgNames != null) {
             pkgSetting.childPackageNames = new ArrayList<>(childPkgNames);
         }
+        if (usesStaticLibraries != null) {
+            pkgSetting.usesStaticLibraries = Arrays.copyOf(usesStaticLibraries,
+                    usesStaticLibraries.length);
+        }
+        if (usesStaticLibrariesVersions != null) {
+            pkgSetting.usesStaticLibrariesVersions = Arrays.copyOf(usesStaticLibrariesVersions,
+                    usesStaticLibrariesVersions.length);
+        }
     }
 
     /**
@@ -949,6 +966,16 @@
         if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
             p.sharedUser.signatures.assignSignatures(pkg.mSignatures);
         }
+        // Update static shared library dependencies if needed
+        if (pkg.usesStaticLibraries != null && pkg.usesStaticLibrariesVersions != null
+                && pkg.usesStaticLibraries.size() == pkg.usesStaticLibrariesVersions.length) {
+            String[] usesStaticLibraries = new String[pkg.usesStaticLibraries.size()];
+            pkg.usesStaticLibraries.toArray(usesStaticLibraries);
+            p.usesStaticLibrariesVersions = pkg.usesStaticLibrariesVersions;
+        } else {
+            pkg.usesStaticLibraries = null;
+            p.usesStaticLibrariesVersions = null;
+        }
         addPackageSettingLPw(p, p.sharedUser);
     }
 
@@ -2163,6 +2190,53 @@
         }
     }
 
+    void readUsesStaticLibLPw(XmlPullParser parser, PackageSetting outPs)
+            throws IOException, XmlPullParserException {
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+            String libName = parser.getAttributeValue(null, ATTR_NAME);
+            String libVersionStr = parser.getAttributeValue(null, ATTR_VERSION);
+
+            int libVersion = -1;
+            try {
+                libVersion = Integer.parseInt(libVersionStr);
+            } catch (NumberFormatException e) {
+                // ignore
+            }
+
+            if (libName != null && libVersion >= 0) {
+                outPs.usesStaticLibraries = ArrayUtils.appendElement(String.class,
+                        outPs.usesStaticLibraries, libName);
+                outPs.usesStaticLibrariesVersions = ArrayUtils.appendInt(
+                        outPs.usesStaticLibrariesVersions, libVersion);
+            }
+
+            XmlUtils.skipCurrentTag(parser);
+        }
+    }
+
+    void writeUsesStaticLibLPw(XmlSerializer serializer, String[] usesStaticLibraries,
+            int[] usesStaticLibraryVersions) throws IOException {
+        if (ArrayUtils.isEmpty(usesStaticLibraries) || ArrayUtils.isEmpty(usesStaticLibraryVersions)
+                || usesStaticLibraries.length != usesStaticLibraryVersions.length) {
+            return;
+        }
+        final int libCount = usesStaticLibraries.length;
+        for (int i = 0; i < libCount; i++) {
+            final String libName = usesStaticLibraries[i];
+            final int libVersion = usesStaticLibraryVersions[i];
+            serializer.startTag(null, TAG_USES_STATIC_LIB);
+            serializer.attribute(null, ATTR_NAME, libName);
+            serializer.attribute(null, ATTR_VERSION, Integer.toString(libVersion));
+            serializer.endTag(null, TAG_USES_STATIC_LIB);
+        }
+    }
+
     // Note: assumed "stopped" field is already cleared in all packages.
     // Legacy reader, used to read in the old file format after an upgrade. Not used after that.
     void readStoppedLPw() {
@@ -2622,6 +2696,8 @@
 
         writeChildPackagesLPw(serializer, pkg.childPackageNames);
 
+        writeUsesStaticLibLPw(serializer, pkg.usesStaticLibraries, pkg.usesStaticLibrariesVersions);
+
         // If this is a shared user, the permissions will be written there.
         if (pkg.sharedUser == null) {
             writePermissionsLPr(serializer, pkg.getPermissionsState()
@@ -2692,6 +2768,8 @@
 
         writeChildPackagesLPw(serializer, pkg.childPackageNames);
 
+        writeUsesStaticLibLPw(serializer, pkg.usesStaticLibraries, pkg.usesStaticLibrariesVersions);
+
         pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
 
         writePermissionsLPr(serializer, pkg.getPermissionsState()
@@ -3465,7 +3543,7 @@
         PackageSetting ps = new PackageSetting(name, realName, codePathFile,
                 new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiStr,
                 secondaryCpuAbiStr, cpuAbiOverrideStr, versionCode, pkgFlags, pkgPrivateFlags,
-                parentPackageName, null /*childPackageNames*/, 0 /*sharedUserId*/);
+                parentPackageName, null /*childPackageNames*/, 0 /*sharedUserId*/, null, null);
         String timeStampStr = parser.getAttributeValue(null, "ft");
         if (timeStampStr != null) {
             try {
@@ -3520,6 +3598,8 @@
                     ps.childPackageNames = new ArrayList<>();
                 }
                 ps.childPackageNames.add(childPackageName);
+            } else if (parser.getName().equals(TAG_USES_STATIC_LIB)) {
+                readUsesStaticLibLPw(parser, ps);
             } else {
                 PackageManagerService.reportSettingsProblem(Log.WARN,
                         "Unknown element under <updated-package>: " + parser.getName());
@@ -3705,7 +3785,8 @@
                 packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
                         new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiString,
                         secondaryCpuAbiString, cpuAbiOverrideString, userId, versionCode, pkgFlags,
-                        pkgPrivateFlags, parentPackageName, null /*childPackageNames*/);
+                        pkgPrivateFlags, parentPackageName, null /*childPackageNames*/,
+                        null /*usesStaticLibraries*/, null /*usesStaticLibraryVersions*/);
                 if (PackageManagerService.DEBUG_SETTINGS)
                     Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId="
                             + userId + " pkg=" + packageSetting);
@@ -3724,7 +3805,8 @@
                             codePathStr), new File(resourcePathStr), legacyNativeLibraryPathStr,
                             primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
                             versionCode, pkgFlags, pkgPrivateFlags, parentPackageName,
-                            null /*childPackageNames*/, sharedUserId);
+                            null /*childPackageNames*/, sharedUserId,
+                            null /*usesStaticLibraries*/, null /*usesStaticLibraryVersions*/);
                     packageSetting.setTimeStamp(timeStamp);
                     packageSetting.firstInstallTime = firstInstallTime;
                     packageSetting.lastUpdateTime = lastUpdateTime;
@@ -4294,6 +4376,7 @@
         ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_EXPLICITLY_SET, "RESIZEABLE_ACTIVITIES_EXPLICITLY_SET",
         ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES_VIA_SDK_VERSION, "RESIZEABLE_ACTIVITIES_VIA_SDK_VERSION",
         ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND, "BACKUP_IN_FOREGROUND",
+        ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY, "STATIC_SHARED_LIBRARY",
     };
 
     void dumpVersionLPr(IndentingPrintWriter pw) {
@@ -4486,23 +4569,39 @@
             }
             pw.println("]");
             if (ps.pkg.libraryNames != null && ps.pkg.libraryNames.size() > 0) {
-                pw.print(prefix); pw.println("  libraries:");
-                for (int i=0; i<ps.pkg.libraryNames.size(); i++) {
-                    pw.print(prefix); pw.print("    "); pw.println(ps.pkg.libraryNames.get(i));
+                pw.print(prefix); pw.println("  dynamic libraries:");
+                for (int i = 0; i<ps.pkg.libraryNames.size(); i++) {
+                    pw.print(prefix); pw.print("    ");
+                            pw.println(ps.pkg.libraryNames.get(i));
                 }
             }
+            if (ps.pkg.staticSharedLibName != null) {
+                pw.print(prefix); pw.println("  static library:");
+                pw.print(prefix); pw.print("    ");
+                pw.print("name:"); pw.print(ps.pkg.staticSharedLibName);
+                pw.print(" version:"); pw.println(ps.pkg.staticSharedLibVersion);
+            }
             if (ps.pkg.usesLibraries != null && ps.pkg.usesLibraries.size() > 0) {
                 pw.print(prefix); pw.println("  usesLibraries:");
                 for (int i=0; i<ps.pkg.usesLibraries.size(); i++) {
                     pw.print(prefix); pw.print("    "); pw.println(ps.pkg.usesLibraries.get(i));
                 }
             }
+            if (ps.pkg.usesStaticLibraries != null
+                    && ps.pkg.usesStaticLibraries.size() > 0) {
+                pw.print(prefix); pw.println("  usesStaticLibraries:");
+                for (int i=0; i<ps.pkg.usesStaticLibraries.size(); i++) {
+                    pw.print(prefix); pw.print("    ");
+                    pw.print(ps.pkg.usesStaticLibraries.get(i)); pw.print(" version:");
+                            pw.println(ps.pkg.usesStaticLibrariesVersions[i]);
+                }
+            }
             if (ps.pkg.usesOptionalLibraries != null
                     && ps.pkg.usesOptionalLibraries.size() > 0) {
                 pw.print(prefix); pw.println("  usesOptionalLibraries:");
                 for (int i=0; i<ps.pkg.usesOptionalLibraries.size(); i++) {
                     pw.print(prefix); pw.print("    ");
-                        pw.println(ps.pkg.usesOptionalLibraries.get(i));
+                    pw.println(ps.pkg.usesOptionalLibraries.get(i));
                 }
             }
             if (ps.pkg.usesLibraryFiles != null
diff --git a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
index 64c5622..fec3267 100644
--- a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
@@ -39,7 +39,8 @@
     public PackageSetting generateFakePackageSetting(String name) {
         return new PackageSetting(name, name, new File(mContext.getCacheDir(), "fakeCodePath"),
                 new File(mContext.getCacheDir(), "fakeResPath"), "", "", "",
-                "", 1, 0, 0, null, null, 0 /*sharedUserId*/);
+                "", 1, 0, 0, null, null, 0 /*sharedUserId*/, null /*usesStaticLibraries*/,
+                null /*usesStaticLibrariesVersions*/);
     }
 
     @Override
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 bd2bb6c..baf60c5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -216,7 +216,9 @@
                 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED|ApplicationInfo.PRIVATE_FLAG_HIDDEN,
                 PARENT_PACKAGE_NAME,
                 childPackageNames,
-                0);
+                0,
+                null /*usesStaticLibraries*/,
+                null /*usesStaticLibrariesVersions*/);
         final PackageSetting testPkgSetting01 = new PackageSetting(origPkgSetting01);
         verifySettingCopy(origPkgSetting01, testPkgSetting01);
     }
@@ -241,7 +243,9 @@
                 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED|ApplicationInfo.PRIVATE_FLAG_HIDDEN,
                 PARENT_PACKAGE_NAME,
                 childPackageNames,
-                0);
+                0,
+                null /*usesStaticLibraries*/,
+                null /*usesStaticLibrariesVersions*/);
         final PackageSetting testPkgSetting01 = new PackageSetting(
                 PACKAGE_NAME /*pkgName*/,
                 REAL_PACKAGE_NAME /*realPkgName*/,
@@ -256,7 +260,9 @@
                 0 /*pkgPrivateFlags*/,
                 null /*parentPkgName*/,
                 null /*childPkgNames*/,
-                0);
+                0,
+                null /*usesStaticLibraries*/,
+                null /*usesStaticLibrariesVersions*/);
         testPkgSetting01.copyFrom(origPkgSetting01);
         verifySettingCopy(origPkgSetting01, testPkgSetting01);
     }
@@ -281,7 +287,9 @@
                 0 /*pkgFlags*/,
                 0 /*pkgPrivateFlags*/,
                 null /*childPkgNames*/,
-                UserManagerService.getInstance());
+                UserManagerService.getInstance(),
+                null /*usesStaticLibraries*/,
+                null /*usesStaticLibrariesVersions*/);
         assertThat(testPkgSetting01.primaryCpuAbiString, is("arm64-v8a"));
         assertThat(testPkgSetting01.secondaryCpuAbiString, is("armeabi"));
         assertThat(testPkgSetting01.origPackage, is(nullValue()));
@@ -313,7 +321,9 @@
                 ApplicationInfo.FLAG_SYSTEM /*pkgFlags*/,
                 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED /*pkgPrivateFlags*/,
                 null /*childPkgNames*/,
-                UserManagerService.getInstance());
+                UserManagerService.getInstance(),
+                null /*usesStaticLibraries*/,
+                null /*usesStaticLibrariesVersions*/);
         assertThat(testPkgSetting01.primaryCpuAbiString, is("arm64-v8a"));
         assertThat(testPkgSetting01.secondaryCpuAbiString, is("armeabi"));
         assertThat(testPkgSetting01.origPackage, is(nullValue()));
@@ -348,7 +358,9 @@
                     0 /*pkgFlags*/,
                     0 /*pkgPrivateFlags*/,
                     null /*childPkgNames*/,
-                    UserManagerService.getInstance());
+                    UserManagerService.getInstance(),
+                    null /*usesStaticLibraries*/,
+                    null /*usesStaticLibrariesVersions*/);
             fail("Expected a PackageManagerException");
         } catch (PackageManagerException expected) {
         }
@@ -378,7 +390,9 @@
                 false /*allowInstall*/,
                 null /*parentPkgName*/,
                 null /*childPkgNames*/,
-                UserManagerService.getInstance());
+                UserManagerService.getInstance(),
+                null /*usesStaticLibraries*/,
+                null /*usesStaticLibrariesVersions*/);
         assertThat(testPkgSetting01.codePath, is(UPDATED_CODE_PATH));
         assertThat(testPkgSetting01.name, is(PACKAGE_NAME));
         assertThat(testPkgSetting01.pkgFlags, is(ApplicationInfo.FLAG_SYSTEM));
@@ -416,7 +430,9 @@
                 true /*allowInstall*/,
                 null /*parentPkgName*/,
                 null /*childPkgNames*/,
-                UserManagerService.getInstance());
+                UserManagerService.getInstance(),
+                null /*usesStaticLibraries*/,
+                null /*usesStaticLibrariesVersions*/);
         assertThat(testPkgSetting01.appId, is(0));
         assertThat(testPkgSetting01.codePath, is(INITIAL_CODE_PATH));
         assertThat(testPkgSetting01.name, is(PACKAGE_NAME));
@@ -457,7 +473,9 @@
                 false /*allowInstall*/,
                 null /*parentPkgName*/,
                 null /*childPkgNames*/,
-                UserManagerService.getInstance());
+                UserManagerService.getInstance(),
+                null /*usesStaticLibraries*/,
+                null /*usesStaticLibrariesVersions*/);
         assertThat(testPkgSetting01.appId, is(10064));
         assertThat(testPkgSetting01.codePath, is(INITIAL_CODE_PATH));
         assertThat(testPkgSetting01.name, is(PACKAGE_NAME));
@@ -498,7 +516,9 @@
                 false /*allowInstall*/,
                 null /*parentPkgName*/,
                 null /*childPkgNames*/,
-                UserManagerService.getInstance());
+                UserManagerService.getInstance(),
+                null /*usesStaticLibraries*/,
+                null /*usesStaticLibrariesVersions*/);
         assertThat(testPkgSetting01.appId, is(10064));
         assertThat(testPkgSetting01.codePath, is(UPDATED_CODE_PATH));
         assertThat(testPkgSetting01.name, is(PACKAGE_NAME));
@@ -624,7 +644,9 @@
                 0 /*privateFlags*/,
                 null /*parentPackageName*/,
                 null /*childPackageNames*/,
-                sharedUserId);
+                sharedUserId,
+                null /*usesStaticLibraries*/,
+                null /*usesStaticLibrariesVersions*/);
     }
 
     private @NonNull List<UserInfo> createFakeUsers() {
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index c46d4a5..0c34f20 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -16,6 +16,7 @@
 
 package android.test.mock;
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.PackageInstallObserver;
@@ -43,7 +44,9 @@
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.content.pm.SharedLibraryInfo;
 import android.content.pm.VerifierDeviceIdentity;
+import android.content.pm.VersionedPackage;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.graphics.Rect;
@@ -72,6 +75,12 @@
         throw new UnsupportedOperationException();
     }
 
+    @Override
+    public PackageInfo getPackageInfo(VersionedPackage versionedPackage,
+            int flags) throws NameNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
     /** @hide */
     @Override
     public PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId)
@@ -715,8 +724,7 @@
      * @hide - to match hiding in superclass
      */
     @Override
-    public void deletePackage(
-            String packageName, IPackageDeleteObserver observer, int flags) {
+    public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
         throw new UnsupportedOperationException();
     }
 
@@ -724,8 +732,8 @@
      * @hide - to match hiding in superclass
      */
     @Override
-    public void deletePackageAsUser(
-            String packageName, IPackageDeleteObserver observer, int flags, int userId) {
+    public void deletePackageAsUser(String packageName, IPackageDeleteObserver observer,
+            int flags, int userId) {
         throw new UnsupportedOperationException();
     }
 
@@ -818,6 +826,17 @@
         throw new UnsupportedOperationException();
     }
 
+    @Override
+    public @NonNull List<SharedLibraryInfo> getSharedLibraries(int flags) {
+        throw new UnsupportedOperationException();
+    }
+
+    /** @hide */
+    @Override
+    public @NonNull List<SharedLibraryInfo> getSharedLibrariesAsUser(int flags, int userId) {
+        throw new UnsupportedOperationException();
+    }
+
     /** @hide */
     @Override
     public @NonNull String getServicesSystemSharedLibraryPackageName() {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index bc7bc74..d3ec9e2 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -42,14 +42,15 @@
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.content.pm.SharedLibraryInfo;
 import android.content.pm.VerifierDeviceIdentity;
+import android.content.pm.VersionedPackage;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Handler;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.storage.VolumeInfo;
 import java.util.List;
@@ -71,6 +72,23 @@
     }
 
     @Override
+    public PackageInfo getPackageInfo(VersionedPackage versionedPackage,
+            @PackageInfoFlags int flags) throws NameNotFoundException {
+        return null;
+    }
+
+    @Override
+    public List<SharedLibraryInfo> getSharedLibraries(@InstallFlags int flags) {
+        return null;
+    }
+
+    @Override
+    public List<SharedLibraryInfo> getSharedLibrariesAsUser(@InstallFlags int flags,
+            int userId) {
+        return null;
+    }
+
+    @Override
     public String[] currentToCanonicalPackageNames(String[] names) {
         return new String[0];
     }