Prune unneeded density resources from APK

When a preferred density is specified, prune all but the
closest matching density when the exact density resource does not
exist.

If a preferred density resource does not exist and a higher density
resource exists, prune all but the resource with the next highest
density relative to the preferred density.

If a preferred density resource does not exist and there is no
higher density resource, prune all but the resource with the next
lowest density relative to the preferred density.

Manual merge of I99b3950fe3d8116a5625968ed383442315ae8526 from
frameworks/base/tools to frameworks/tools

bug:11224465
Change-Id: Idddf55dad27f114ffc429b61317c3a5b1435d808
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 3797b49..d8e113a 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -2487,6 +2487,15 @@
                 continue;
             }
 
+            // Get the preferred density if there is one. We do not match exactly for density.
+            // If our preferred density is hdpi but we only have mdpi and xhdpi resources, we
+            // pick xhdpi.
+            uint32_t preferredDensity = 0;
+            const SortedVector<uint32_t>* preferredConfigs = prefFilter.configsForAxis(AXIS_DENSITY);
+            if (preferredConfigs != NULL && preferredConfigs->size() > 0) {
+                preferredDensity = (*preferredConfigs)[0];
+            }
+
             // Now deal with preferred configurations.
             for (int axis=AXIS_START; axis<=AXIS_END; axis++) {
                 for (size_t k=0; k<grp->getFiles().size(); k++) {
@@ -2512,12 +2521,30 @@
                         // This is a resource we would prefer not to have.  Check
                         // to see if have a similar variation that we would like
                         // to have and, if so, we can drop it.
+
+                        uint32_t bestDensity = config.density;
+
                         for (size_t m=0; m<grp->getFiles().size(); m++) {
                             if (m == k) continue;
                             sp<AaptFile> mfile = grp->getFiles().valueAt(m);
                             const ResTable_config& mconfig(mfile->getGroupEntry().toParams());
                             if (AaptGroupEntry::configSameExcept(config, mconfig, axis)) {
-                                if (prefFilter.match(axis, mconfig)) {
+                                if (axis == AXIS_DENSITY && preferredDensity > 0) {
+                                    // See if there is a better density resource
+                                    if (mconfig.density < bestDensity &&
+                                            mconfig.density > preferredDensity &&
+                                            bestDensity > preferredDensity) {
+                                        // This density is between our best density and
+                                        // the preferred density, therefore it is better.
+                                        bestDensity = mconfig.density;
+                                    } else if (mconfig.density > bestDensity &&
+                                            bestDensity < preferredDensity) {
+                                        // This density is better than our best density and
+                                        // our best density was smaller than our preferred
+                                        // density, so it is better.
+                                        bestDensity = mconfig.density;
+                                    }
+                                } else if (prefFilter.match(axis, mconfig)) {
                                     if (bundle->getVerbose()) {
                                         printf("Pruning unneeded resource: %s\n",
                                                 file->getPrintableSource().string());
@@ -2528,6 +2555,16 @@
                                 }
                             }
                         }
+
+                        if (axis == AXIS_DENSITY && preferredDensity > 0 &&
+                                bestDensity != config.density) {
+                            if (bundle->getVerbose()) {
+                                printf("Pruning unneeded resource: %s\n",
+                                        file->getPrintableSource().string());
+                            }
+                            grp->removeFile(k);
+                            k--;
+                        }
                     }
                 }
             }