Implement issue #3116702: New manifest tags for supported screen sizes

Merged from GB.

Change-Id: I94730b54bcacd083f77708e84c35f4932a7b9d2e
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 4469e68..e9833c9 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -334,13 +334,15 @@
     REQ_FIVE_WAY_NAV_ATTR = 0x01010232,
     TARGET_SDK_VERSION_ATTR = 0x01010270,
     TEST_ONLY_ATTR = 0x01010272,
-    DENSITY_ATTR = 0x0101026c,
+    ANY_DENSITY_ATTR = 0x0101026c,
     GL_ES_VERSION_ATTR = 0x01010281,
     SMALL_SCREEN_ATTR = 0x01010284,
     NORMAL_SCREEN_ATTR = 0x01010285,
     LARGE_SCREEN_ATTR = 0x01010286,
     XLARGE_SCREEN_ATTR = 0x010102bf,
     REQUIRED_ATTR = 0x0101028e,
+    SCREEN_SIZE_ATTR = 0x010102ca,
+    SCREEN_DENSITY_ATTR = 0x010102cb,
 };
 
 const char *getComponentName(String8 &pkgName, String8 &componentName) {
@@ -357,6 +359,42 @@
     return retStr.string();
 }
 
+static void printCompatibleScreens(ResXMLTree& tree) {
+    size_t len;
+    ResXMLTree::event_code_t code;
+    int depth = 0;
+    bool first = true;
+    printf("compatible-screens:");
+    while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
+        if (code == ResXMLTree::END_TAG) {
+            depth--;
+            if (depth < 0) {
+                break;
+            }
+            continue;
+        }
+        if (code != ResXMLTree::START_TAG) {
+            continue;
+        }
+        depth++;
+        String8 tag(tree.getElementName(&len));
+        if (tag == "screen") {
+            int32_t screenSize = getIntegerAttribute(tree,
+                    SCREEN_SIZE_ATTR, NULL, -1);
+            int32_t screenDensity = getIntegerAttribute(tree,
+                    SCREEN_DENSITY_ATTR, NULL, -1);
+            if (screenSize > 0 && screenDensity > 0) {
+                if (!first) {
+                    printf(",");
+                }
+                first = false;
+                printf("'%d/%d'", screenSize, screenDensity);
+            }
+        }
+    }
+    printf("\n");
+}
+
 /*
  * Handle the "dump" command, to extract select data from an archive.
  */
@@ -575,6 +613,7 @@
             int normalScreen = 1;
             int largeScreen = 1;
             int xlargeScreen = 1;
+            int anyDensity = 1;
             String8 pkg;
             String8 activityName;
             String8 activityLabel;
@@ -742,14 +781,6 @@
                             printf(" reqFiveWayNav='%d'", reqFiveWayNav);
                         }
                         printf("\n");
-                    } else if (tag == "supports-density") {
-                        int32_t dens = getIntegerAttribute(tree, DENSITY_ATTR, &error);
-                        if (error != "") {
-                            fprintf(stderr, "ERROR getting 'android:density' attribute: %s\n",
-                                    error.string());
-                            goto bail;
-                        }
-                        printf("supports-density:'%d'\n", dens);
                     } else if (tag == "supports-screens") {
                         smallScreen = getIntegerAttribute(tree,
                                 SMALL_SCREEN_ATTR, NULL, 1);
@@ -759,6 +790,8 @@
                                 LARGE_SCREEN_ATTR, NULL, 1);
                         xlargeScreen = getIntegerAttribute(tree,
                                 XLARGE_SCREEN_ATTR, NULL, 1);
+                        anyDensity = getIntegerAttribute(tree,
+                                ANY_DENSITY_ATTR, NULL, 1);
                     } else if (tag == "uses-feature") {
                         String8 name = getAttribute(tree, NAME_ATTR, &error);
 
@@ -883,6 +916,9 @@
                                     error.string());
                                 goto bail;
                         }
+                    } else if (tag == "compatible-screens") {
+                        printCompatibleScreens(tree);
+                        depth--;
                     }
                 } else if (depth == 3 && withinApplication) {
                     withinActivity = false;
@@ -1109,6 +1145,9 @@
                 // Introduced in Honeycomb.
                 xlargeScreen = targetSdk >= 10 ? -1 : 0;
             }
+            if (anyDensity > 0) {
+                anyDensity = targetSdk >= 4 ? -1 : 0;
+            }
             printf("supports-screens:");
             if (smallScreen != 0) printf(" 'small'");
             if (normalScreen != 0) printf(" 'normal'");
@@ -1116,6 +1155,8 @@
             if (xlargeScreen != 0) printf(" 'xlarge'");
             printf("\n");
 
+            printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false");
+
             printf("locales:");
             Vector<String8> locales;
             res.getLocales(&locales);