diff options
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/content/pm/parsing/ParsingPackageUtils.java | 108 |
1 files changed, 93 insertions, 15 deletions
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java index 9197020e1fce..b936c6323a80 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java @@ -1080,14 +1080,57 @@ public class ParsingPackageUtils { } } - final String requiredFeature = sa.getNonConfigurationString( - R.styleable.AndroidManifestUsesPermission_requiredFeature, 0); + final ArraySet<String> requiredFeatures = new ArraySet<>(); + String feature = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredFeature, + 0); + if (feature != null) { + requiredFeatures.add(feature); + } - final String requiredNotfeature = sa.getNonConfigurationString( - R.styleable.AndroidManifestUsesPermission_requiredNotFeature, + final ArraySet<String> requiredNotFeatures = new ArraySet<>(); + feature = sa.getNonConfigurationString( + com.android.internal.R.styleable + .AndroidManifestUsesPermission_requiredNotFeature, 0); + if (feature != null) { + requiredNotFeatures.add(feature); + } + + final 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; + } + + final ParseResult<?> result; + switch (parser.getName()) { + case "required-feature": + result = parseRequiredFeature(input, res, parser); + if (result.isSuccess()) { + requiredFeatures.add((String) result.getResult()); + } + break; + + case "required-not-feature": + result = parseRequiredNotFeature(input, res, parser); + if (result.isSuccess()) { + requiredNotFeatures.add((String) result.getResult()); + } + break; - XmlUtils.skipCurrentTag(parser); + default: + result = ParsingUtils.unknownTag("<uses-permission>", pkg, parser, input); + break; + } + + if (result.isError()) { + return input.error(result); + } + } // Can only succeed from here on out ParseResult<ParsingPackage> success = input.success(pkg); @@ -1100,17 +1143,22 @@ public class ParsingPackageUtils { return success; } - // Only allow requesting this permission if the platform supports the given feature. - if (requiredFeature != null && mCallback != null && !mCallback.hasFeature( - requiredFeature)) { - return success; - } + if (mCallback != null) { + // Only allow requesting this permission if the platform supports all of the + // "required-feature"s. + for (int i = requiredFeatures.size() - 1; i >= 0; i--) { + if (!mCallback.hasFeature(requiredFeatures.valueAt(i))) { + return success; + } + } - // Only allow requesting this permission if the platform doesn't support the given - // feature. - if (requiredNotfeature != null && mCallback != null - && mCallback.hasFeature(requiredNotfeature)) { - return success; + // Only allow requesting this permission if the platform does not supports any of + // the "required-not-feature"s. + for (int i = requiredNotFeatures.size() - 1; i >= 0; i--) { + if (mCallback.hasFeature(requiredNotFeatures.valueAt(i))) { + return success; + } + } } if (!pkg.getRequestedPermissions().contains(name)) { @@ -1127,6 +1175,36 @@ public class ParsingPackageUtils { } } + private ParseResult<String> parseRequiredFeature(ParseInput input, Resources res, + AttributeSet attrs) { + final TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestRequiredFeature); + try { + final String featureName = sa.getString( + R.styleable.AndroidManifestRequiredFeature_name); + return TextUtils.isEmpty(featureName) + ? input.error("Feature name is missing from <required-feature> tag.") + : input.success(featureName); + } finally { + sa.recycle(); + } + } + + private ParseResult<String> parseRequiredNotFeature(ParseInput input, Resources res, + AttributeSet attrs) { + final TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestRequiredNotFeature); + try { + final String featureName = sa.getString( + R.styleable.AndroidManifestRequiredNotFeature_name); + return TextUtils.isEmpty(featureName) + ? input.error("Feature name is missing from <required-not-feature> tag.") + : input.success(featureName); + } finally { + sa.recycle(); + } + } + private static ParseResult<ParsingPackage> parseUsesConfiguration(ParseInput input, ParsingPackage pkg, Resources res, XmlResourceParser parser) { ConfigurationInfo cPref = new ConfigurationInfo(); |
