diff --git a/api/current.txt b/api/current.txt index a47cb761e4a7c..db13a0b962176 100644 --- a/api/current.txt +++ b/api/current.txt @@ -1005,7 +1005,7 @@ package android { field public static final int preferenceStyle = 16842894; // 0x101008e field public static final int presentationTheme = 16843712; // 0x10103c0 field public static final int previewImage = 16843482; // 0x10102da - field public static final int primaryContentAlpha = 16843367; // 0x1010267 + field public static final int primaryContentAlpha = 16844117; // 0x1010555 field public static final int priority = 16842780; // 0x101001c field public static final int privateImeOptions = 16843299; // 0x1010223 field public static final int process = 16842769; // 0x1010011 @@ -1061,7 +1061,9 @@ package android { field public static final int requireDeviceUnlock = 16843756; // 0x10103ec field public static final int required = 16843406; // 0x101028e field public static final int requiredAccountType = 16843734; // 0x10103d6 + field public static final int requiredFeature = 16844119; // 0x1010557 field public static final int requiredForAllUsers = 16843728; // 0x10103d0 + field public static final int requiredNotFeature = 16844120; // 0x1010558 field public static final int requiresFadingEdge = 16843685; // 0x10103a5 field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364 field public static final int resizeClip = 16843983; // 0x10104cf @@ -1130,7 +1132,7 @@ package android { field public static final int searchSuggestSelection = 16843224; // 0x10101d8 field public static final int searchSuggestThreshold = 16843373; // 0x101026d field public static final int searchViewStyle = 16843904; // 0x1010480 - field public static final int secondaryContentAlpha = 16843688; // 0x10103a8 + field public static final int secondaryContentAlpha = 16844118; // 0x1010556 field public static final int secondaryProgress = 16843064; // 0x1010138 field public static final int secondaryProgressTint = 16843879; // 0x1010467 field public static final int secondaryProgressTintMode = 16843880; // 0x1010468 diff --git a/api/system-current.txt b/api/system-current.txt index e6fb17d65e914..9536d13dde57d 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1117,7 +1117,7 @@ package android { field public static final int preferenceStyle = 16842894; // 0x101008e field public static final int presentationTheme = 16843712; // 0x10103c0 field public static final int previewImage = 16843482; // 0x10102da - field public static final int primaryContentAlpha = 16843367; // 0x1010267 + field public static final int primaryContentAlpha = 16844117; // 0x1010555 field public static final int priority = 16842780; // 0x101001c field public static final int privateImeOptions = 16843299; // 0x1010223 field public static final int process = 16842769; // 0x1010011 @@ -1173,7 +1173,9 @@ package android { field public static final int requireDeviceUnlock = 16843756; // 0x10103ec field public static final int required = 16843406; // 0x101028e field public static final int requiredAccountType = 16843734; // 0x10103d6 + field public static final int requiredFeature = 16844119; // 0x1010557 field public static final int requiredForAllUsers = 16843728; // 0x10103d0 + field public static final int requiredNotFeature = 16844120; // 0x1010558 field public static final int requiresFadingEdge = 16843685; // 0x10103a5 field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364 field public static final int resizeClip = 16843983; // 0x10104cf @@ -1246,7 +1248,7 @@ package android { field public static final int searchSuggestSelection = 16843224; // 0x10101d8 field public static final int searchSuggestThreshold = 16843373; // 0x101026d field public static final int searchViewStyle = 16843904; // 0x1010480 - field public static final int secondaryContentAlpha = 16843688; // 0x10103a8 + field public static final int secondaryContentAlpha = 16844118; // 0x1010556 field public static final int secondaryProgress = 16843064; // 0x1010138 field public static final int secondaryProgressTint = 16843879; // 0x1010467 field public static final int secondaryProgressTintMode = 16843880; // 0x1010468 diff --git a/api/test-current.txt b/api/test-current.txt index 904aa40d07f0c..5776bc34881fb 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1005,7 +1005,7 @@ package android { field public static final int preferenceStyle = 16842894; // 0x101008e field public static final int presentationTheme = 16843712; // 0x10103c0 field public static final int previewImage = 16843482; // 0x10102da - field public static final int primaryContentAlpha = 16843367; // 0x1010267 + field public static final int primaryContentAlpha = 16844117; // 0x1010555 field public static final int priority = 16842780; // 0x101001c field public static final int privateImeOptions = 16843299; // 0x1010223 field public static final int process = 16842769; // 0x1010011 @@ -1061,7 +1061,9 @@ package android { field public static final int requireDeviceUnlock = 16843756; // 0x10103ec field public static final int required = 16843406; // 0x101028e field public static final int requiredAccountType = 16843734; // 0x10103d6 + field public static final int requiredFeature = 16844119; // 0x1010557 field public static final int requiredForAllUsers = 16843728; // 0x10103d0 + field public static final int requiredNotFeature = 16844120; // 0x1010558 field public static final int requiresFadingEdge = 16843685; // 0x10103a5 field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364 field public static final int resizeClip = 16843983; // 0x10104cf @@ -1130,7 +1132,7 @@ package android { field public static final int searchSuggestSelection = 16843224; // 0x10101d8 field public static final int searchSuggestThreshold = 16843373; // 0x101026d field public static final int searchViewStyle = 16843904; // 0x1010480 - field public static final int secondaryContentAlpha = 16843688; // 0x10103a8 + field public static final int secondaryContentAlpha = 16844118; // 0x1010556 field public static final int secondaryProgress = 16843064; // 0x1010138 field public static final int secondaryProgressTint = 16843879; // 0x1010467 field public static final int secondaryProgressTintMode = 16843880; // 0x1010468 diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 9fda3cd3dee7b..73dc9968d6dc5 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -5000,6 +5000,7 @@ public abstract class PackageManager { */ public PackageInfo getPackageArchiveInfo(String archiveFilePath, @PackageInfoFlags int flags) { final PackageParser parser = new PackageParser(); + parser.setCallback(new PackageParser.CallbackImpl(this)); final File apkFile = new File(archiveFilePath); try { if ((flags & (MATCH_DIRECT_BOOT_UNAWARE | MATCH_DIRECT_BOOT_AWARE)) != 0) { diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index f801e4547658d..60cc6b06bf11a 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -285,6 +285,7 @@ public class PackageParser { private String[] mSeparateProcesses; private boolean mOnlyCoreApps; private DisplayMetrics mMetrics; + private Callback mCallback; private File mCacheDir; private static final int SDK_VERSION = Build.VERSION.SDK_INT; @@ -506,6 +507,37 @@ public class PackageParser { mCacheDir = cacheDir; } + /** + * Callback interface for retrieving information that may be needed while parsing + * a package. + */ + public interface Callback { + boolean hasFeature(String feature); + } + + /** + * Standard implementation of {@link Callback} on top of the public {@link PackageManager} + * class. + */ + public static final class CallbackImpl implements Callback { + private final PackageManager mPm; + + public CallbackImpl(PackageManager pm) { + mPm = pm; + } + + @Override public boolean hasFeature(String feature) { + return mPm.hasSystemFeature(feature); + } + } + + /** + * Set the {@link Callback} that can be used while parsing. + */ + public void setCallback(Callback cb) { + mCallback = cb; + } + public static final boolean isApkFile(File file) { return isApkPath(file.getName()); } @@ -2079,15 +2111,15 @@ public class PackageParser { return null; } } else if (tagName.equals(TAG_PERMISSION_GROUP)) { - if (parsePermissionGroup(pkg, flags, res, parser, outError) == null) { + if (!parsePermissionGroup(pkg, flags, res, parser, outError)) { return null; } } else if (tagName.equals(TAG_PERMISSION)) { - if (parsePermission(pkg, res, parser, outError) == null) { + if (!parsePermission(pkg, res, parser, outError)) { return null; } } else if (tagName.equals(TAG_PERMISSION_TREE)) { - if (parsePermissionTree(pkg, res, parser, outError) == null) { + if (!parsePermissionTree(pkg, res, parser, outError)) { return null; } } else if (tagName.equals(TAG_USES_PERMISSION)) { @@ -2708,22 +2740,44 @@ public class PackageParser { } } + final String requiredFeature = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredFeature, 0); + + final String requiredNotfeature = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0); + sa.recycle(); - if ((maxSdkVersion == 0) || (maxSdkVersion >= Build.VERSION.RESOURCES_SDK_INT)) { - if (name != null) { - int index = pkg.requestedPermissions.indexOf(name); - if (index == -1) { - pkg.requestedPermissions.add(name.intern()); - } else { - Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: " - + name + " in package: " + pkg.packageName + " at: " - + parser.getPositionDescription()); - } - } + XmlUtils.skipCurrentTag(parser); + + if (name == null) { + return true; + } + + if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) { + return true; + } + + // Only allow requesting this permission if the platform supports the given feature. + if (requiredFeature != null && mCallback != null && !mCallback.hasFeature(requiredFeature)) { + return true; + } + + // Only allow requesting this permission if the platform doesn't support the given feature. + if (requiredNotfeature != null && mCallback != null + && mCallback.hasFeature(requiredNotfeature)) { + return true; + } + + int index = pkg.requestedPermissions.indexOf(name); + if (index == -1) { + pkg.requestedPermissions.add(name.intern()); + } else { + Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: " + + name + " in package: " + pkg.packageName + " at: " + + parser.getPositionDescription()); } - XmlUtils.skipCurrentTag(parser); return true; } @@ -2951,7 +3005,7 @@ public class PackageParser { return true; } - private PermissionGroup parsePermissionGroup(Package owner, int flags, Resources res, + private boolean parsePermissionGroup(Package owner, int flags, Resources res, XmlResourceParser parser, String[] outError) throws XmlPullParserException, IOException { PermissionGroup perm = new PermissionGroup(owner); @@ -2968,7 +3022,7 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestPermissionGroup_banner)) { sa.recycle(); mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; + return false; } perm.info.descriptionRes = sa.getResourceId( @@ -2987,22 +3041,22 @@ public class PackageParser { if (!parseAllMetaData(res, parser, "", perm, outError)) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; + return false; } owner.permissionGroups.add(perm); - return perm; + return true; } - private Permission parsePermission(Package owner, Resources res, + private boolean parsePermission(Package owner, Resources res, XmlResourceParser parser, String[] outError) throws XmlPullParserException, IOException { - Permission perm = new Permission(owner); TypedArray sa = res.obtainAttributes(parser, com.android.internal.R.styleable.AndroidManifestPermission); + Permission perm = new Permission(owner); if (!parsePackageItemInfo(owner, perm.info, outError, "", sa, true /*nameRequired*/, com.android.internal.R.styleable.AndroidManifestPermission_name, @@ -3013,7 +3067,7 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestPermission_banner)) { sa.recycle(); mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; + return false; } // Note: don't allow this value to be a reference to a resource @@ -3040,7 +3094,7 @@ public class PackageParser { if (perm.info.protectionLevel == -1) { outError[0] = " does not specify protectionLevel"; mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; + return false; } perm.info.protectionLevel = PermissionInfo.fixProtectionLevel(perm.info.protectionLevel); @@ -3052,21 +3106,21 @@ public class PackageParser { outError[0] = " protectionLevel specifies a non-ephemeral flag but is " + "not based on signature type"; mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; + return false; } } if (!parseAllMetaData(res, parser, "", perm, outError)) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; + return false; } owner.permissions.add(perm); - return perm; + return true; } - private Permission parsePermissionTree(Package owner, Resources res, + private boolean parsePermissionTree(Package owner, Resources res, XmlResourceParser parser, String[] outError) throws XmlPullParserException, IOException { Permission perm = new Permission(owner); @@ -3084,7 +3138,7 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestPermissionTree_banner)) { sa.recycle(); mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; + return false; } sa.recycle(); @@ -3097,7 +3151,7 @@ public class PackageParser { outError[0] = " name has less than three segments: " + perm.info.name; mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; + return false; } perm.info.descriptionRes = 0; @@ -3107,12 +3161,12 @@ public class PackageParser { if (!parseAllMetaData(res, parser, "", perm, outError)) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; - return null; + return false; } owner.permissions.add(perm); - return perm; + return true; } private Instrumentation parseInstrumentation(Package owner, Resources res, diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 76f4a7654af73..deacc24be158f 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1534,6 +1534,14 @@ of Android higher than the number given here, the permission will not be requested. --> + + + +