Add platform infrastructure for features.
This introduces a new mechanism to define features associated with
a platform, query the current device for the available features,
and enforce that apps requiring features that aren't available can't
be installed.
Also now allows uses-library to specify that a library is optional,
so the lack of such a library will not prevent the app from being
installed (but if it does exist it will be correctly linked into
the app).
Change-Id: I5b369b46cfa0b3d37c9e08fd14ef1098a978e67b
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 96c9486..4399df4 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -184,9 +184,12 @@
int N = p.configPreferences.size();
if (N > 0) {
pi.configPreferences = new ConfigurationInfo[N];
- for (int i=0; i<N; i++) {
- pi.configPreferences[i] = p.configPreferences.get(i);
- }
+ p.configPreferences.toArray(pi.configPreferences);
+ }
+ N = p.reqFeatures != null ? p.reqFeatures.size() : 0;
+ if (N > 0) {
+ pi.reqFeatures = new FeatureInfo[N];
+ p.reqFeatures.toArray(pi.reqFeatures);
}
}
if ((flags&PackageManager.GET_ACTIVITIES) != 0) {
@@ -760,14 +763,32 @@
XmlUtils.skipCurrentTag(parser);
} else if (tagName.equals("uses-feature")) {
- ConfigurationInfo cPref = new ConfigurationInfo();
+ FeatureInfo fi = new FeatureInfo();
sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifestUsesFeature);
- cPref.reqGlEsVersion = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
- ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
+ fi.name = sa.getNonResourceString(
+ com.android.internal.R.styleable.AndroidManifestUsesFeature_name);
+ if (fi.name == null) {
+ fi.reqGlEsVersion = sa.getInt(
+ com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
+ FeatureInfo.GL_ES_VERSION_UNDEFINED);
+ }
+ if (sa.getBoolean(
+ com.android.internal.R.styleable.AndroidManifestUsesFeature_required,
+ true)) {
+ fi.flags |= FeatureInfo.FLAG_REQUIRED;
+ }
sa.recycle();
- pkg.configPreferences.add(cPref);
+ if (pkg.reqFeatures == null) {
+ pkg.reqFeatures = new ArrayList<FeatureInfo>();
+ }
+ pkg.reqFeatures.add(fi);
+
+ if (fi.name == null) {
+ ConfigurationInfo cPref = new ConfigurationInfo();
+ cPref.reqGlEsVersion = fi.reqGlEsVersion;
+ pkg.configPreferences.add(cPref);
+ }
XmlUtils.skipCurrentTag(parser);
@@ -946,11 +967,6 @@
}
}
- if (pkg.usesLibraries.size() > 0) {
- pkg.usesLibraryFiles = new String[pkg.usesLibraries.size()];
- pkg.usesLibraries.toArray(pkg.usesLibraryFiles);
- }
-
if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
&& pkg.applicationInfo.targetSdkVersion
>= android.os.Build.VERSION_CODES.DONUT)) {
@@ -1436,11 +1452,28 @@
String lname = sa.getNonResourceString(
com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
+ boolean req = sa.getBoolean(
+ com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
+ true);
sa.recycle();
- if (lname != null && !owner.usesLibraries.contains(lname)) {
- owner.usesLibraries.add(lname.intern());
+ if (lname != null) {
+ if (req) {
+ if (owner.usesLibraries == null) {
+ owner.usesLibraries = new ArrayList<String>();
+ }
+ if (!owner.usesLibraries.contains(lname)) {
+ owner.usesLibraries.add(lname.intern());
+ }
+ } else {
+ if (owner.usesOptionalLibraries == null) {
+ owner.usesOptionalLibraries = new ArrayList<String>();
+ }
+ if (!owner.usesOptionalLibraries.contains(lname)) {
+ owner.usesOptionalLibraries.add(lname.intern());
+ }
+ }
}
XmlUtils.skipCurrentTag(parser);
@@ -2418,7 +2451,8 @@
public ArrayList<String> protectedBroadcasts;
- public final ArrayList<String> usesLibraries = new ArrayList<String>();
+ public ArrayList<String> usesLibraries = null;
+ public ArrayList<String> usesOptionalLibraries = null;
public String[] usesLibraryFiles = null;
// We store the application meta-data independently to avoid multiple unwanted references
@@ -2466,6 +2500,11 @@
public final ArrayList<ConfigurationInfo> configPreferences =
new ArrayList<ConfigurationInfo>();
+ /*
+ * Applications requested features
+ */
+ public ArrayList<FeatureInfo> reqFeatures = null;
+
public Package(String _name) {
packageName = _name;
applicationInfo.packageName = _name;