Implement issue #34842682: Add ability to limit permissions based on features

Two new attributes for <uses-permission>: android:requiredFeature and
android:requiredNotFeature.

Also update aapt to include this information in badging:

uses-permission: name='android.content.cts.REQUIRED_NOT_FEATURE_UNDEFINED' requiredNotFeature='android.software.cts.undefined'
uses-permission: name='android.content.cts.REQUIRED_MULTI_DENY' requiredFeature='android.software.cts.undefined' requiredNotFeature='android.software.cts'

Test: new PermissionFeatureTest suite.

Change-Id: Icc1f815a4675ae9dd2cb7f61730ab28b5c11228a
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 0e031e7..15648bd 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -309,6 +309,8 @@
     CATEGORY_ATTR = 0x010103e8,
     BANNER_ATTR = 0x10103f2,
     ISGAME_ATTR = 0x10103f4,
+    REQUIRED_FEATURE_ATTR = 0x1010557,
+    REQUIRED_NOT_FEATURE_ATTR = 0x1010558,
 };
 
 String8 getComponentName(String8 &pkgName, String8 &componentName) {
@@ -366,11 +368,19 @@
     printf("\n");
 }
 
-static void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1) {
+static void printUsesPermission(const String8& name, bool optional=false, int maxSdkVersion=-1,
+        const String8& requiredFeature = String8::empty(),
+        const String8& requiredNotFeature = String8::empty()) {
     printf("uses-permission: name='%s'", ResTable::normalizeForOutput(name.string()).string());
     if (maxSdkVersion != -1) {
          printf(" maxSdkVersion='%d'", maxSdkVersion);
     }
+    if (requiredFeature.length() > 0) {
+         printf(" requiredFeature='%s'", requiredFeature.string());
+    }
+    if (requiredNotFeature.length() > 0) {
+         printf(" requiredNotFeature='%s'", requiredNotFeature.string());
+    }
     printf("\n");
 
     if (optional) {
@@ -1545,6 +1555,10 @@
 
                         const int32_t maxSdkVersion =
                                 AaptXml::getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, -1);
+                        const String8 requiredFeature = AaptXml::getAttribute(tree,
+                                REQUIRED_FEATURE_ATTR, &error);
+                        const String8 requiredNotFeature = AaptXml::getAttribute(tree,
+                                REQUIRED_NOT_FEATURE_ATTR, &error);
 
                         if (name == "android.permission.WRITE_EXTERNAL_STORAGE") {
                             hasWriteExternalStoragePermission = true;
@@ -1565,7 +1579,7 @@
 
                         printUsesPermission(name,
                                 AaptXml::getIntegerAttribute(tree, REQUIRED_ATTR, 1) == 0,
-                                maxSdkVersion);
+                                maxSdkVersion, requiredFeature, requiredNotFeature);
 
                     } else if (tag == "uses-permission-sdk-23" || tag == "uses-permission-sdk-m") {
                         String8 name = AaptXml::getAttribute(tree, NAME_ATTR, &error);