Merge "Platform support for static shared libraries"
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
* <permission>} tags included under <manifest>,
@@ -150,7 +150,7 @@
* {@link PackageManager#GET_PERMISSIONS} was set.
*/
public PermissionInfo[] permissions;
-
+
/**
* Array of all {@link android.R.styleable#AndroidManifestUsesPermission
* <uses-permission>} tags included under <manifest>,
@@ -160,7 +160,7 @@
* by the system at install time.
*/
public String[] requestedPermissions;
-
+
/**
* Array of flags of all {@link android.R.styleable#AndroidManifestUsesPermission
* <uses-permission>} tags included under <manifest>,
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];
}