Add support for building split APKs

Build multiple APKs, each containing a disjoint subset
of configurations. These can then be loaded into the device
AssetManager and should operate as if they were never split.

Use the idea of building multiple sets of files, where each
set represents an APK. An ApkBuilder can place files
in a set based on its configuration, but you can actually
add directly to a set, in the case of the resources.arsc and
generated AndroidManifest.xml for splits.

Change-Id: Ic65d3f0ac1bbd290185695b9971d425c85ab1de3
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index e0dab78..12d5389 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -3,8 +3,10 @@
 //
 
 #include "AaptAssets.h"
-#include "ResourceFilter.h"
+#include "AaptConfig.h"
+#include "AaptUtil.h"
 #include "Main.h"
+#include "ResourceFilter.h"
 
 #include <utils/misc.h>
 #include <utils/SortedVector.h>
@@ -14,7 +16,6 @@
 #include <errno.h>
 
 static const char* kDefaultLocale = "default";
-static const char* kWildcardName = "any";
 static const char* kAssetDir = "assets";
 static const char* kResourceDir = "res";
 static const char* kValuesDir = "values";
@@ -149,24 +150,6 @@
 // =========================================================================
 // =========================================================================
 
-/* static */ void AaptLocaleValue::splitAndLowerCase(const char* const chars,
-        Vector<String8>* parts, const char separator) {
-    const char *p = chars;
-    const char *q;
-    while (NULL != (q = strchr(p, separator))) {
-         String8 val(p, q - p);
-         val.toLower();
-         parts->add(val);
-         p = q+1;
-    }
-
-    if (p < chars + strlen(chars)) {
-        String8 val(p);
-        val.toLower();
-        parts->add(val);
-    }
-}
-
 /* static */
 inline bool isAlpha(const String8& string) {
      const size_t length = string.length();
@@ -230,8 +213,7 @@
 bool AaptLocaleValue::initFromFilterString(const String8& str) {
      // A locale (as specified in the filter) is an underscore separated name such
      // as "en_US", "en_Latn_US", or "en_US_POSIX".
-     Vector<String8> parts;
-     splitAndLowerCase(str.string(), &parts, '_');
+     Vector<String8> parts = AaptUtil::splitAndLowerCase(str, '_');
 
      const int numTags = parts.size();
      bool valid = false;
@@ -301,8 +283,7 @@
     if (part[0] == 'b' && part[1] == '+') {
         // This is a "modified" BCP-47 language tag. Same semantics as BCP-47 tags,
         // except that the separator is "+" and not "-".
-        Vector<String8> subtags;
-        AaptLocaleValue::splitAndLowerCase(part.string(), &subtags, '+');
+        Vector<String8> subtags = AaptUtil::splitAndLowerCase(part, '+');
         subtags.removeItemsAt(0);
         if (subtags.size() == 1) {
             setLanguage(subtags[0]);
@@ -438,1349 +419,46 @@
     }
 }
 
-
-/* static */ bool
-AaptGroupEntry::parseFilterNamePart(const String8& part, int* axis, AxisValue* value)
-{
-    ResTable_config config;
-    memset(&config, 0, sizeof(ResTable_config));
-
-    // IMSI - MCC
-    if (getMccName(part.string(), &config)) {
-        *axis = AXIS_MCC;
-        value->intValue = config.mcc;
-        return true;
-    }
-
-    // IMSI - MNC
-    if (getMncName(part.string(), &config)) {
-        *axis = AXIS_MNC;
-        value->intValue = config.mnc;
-        return true;
-    }
-
-    // locale - language
-    if (value->localeValue.initFromFilterString(part)) {
-        *axis = AXIS_LOCALE;
-        return true;
-    }
-
-    // layout direction
-    if (getLayoutDirectionName(part.string(), &config)) {
-        *axis = AXIS_LAYOUTDIR;
-        value->intValue = (config.screenLayout&ResTable_config::MASK_LAYOUTDIR);
-        return true;
-    }
-
-    // smallest screen dp width
-    if (getSmallestScreenWidthDpName(part.string(), &config)) {
-        *axis = AXIS_SMALLESTSCREENWIDTHDP;
-        value->intValue = config.smallestScreenWidthDp;
-        return true;
-    }
-
-    // screen dp width
-    if (getScreenWidthDpName(part.string(), &config)) {
-        *axis = AXIS_SCREENWIDTHDP;
-        value->intValue = config.screenWidthDp;
-        return true;
-    }
-
-    // screen dp height
-    if (getScreenHeightDpName(part.string(), &config)) {
-        *axis = AXIS_SCREENHEIGHTDP;
-        value->intValue = config.screenHeightDp;
-        return true;
-    }
-
-    // screen layout size
-    if (getScreenLayoutSizeName(part.string(), &config)) {
-        *axis = AXIS_SCREENLAYOUTSIZE;
-        value->intValue = (config.screenLayout&ResTable_config::MASK_SCREENSIZE);
-        return true;
-    }
-
-    // screen layout long
-    if (getScreenLayoutLongName(part.string(), &config)) {
-        *axis = AXIS_SCREENLAYOUTLONG;
-        value->intValue = (config.screenLayout&ResTable_config::MASK_SCREENLONG);
-        return true;
-    }
-
-    // orientation
-    if (getOrientationName(part.string(), &config)) {
-        *axis = AXIS_ORIENTATION;
-        value->intValue = config.orientation;
-        return true;
-    }
-
-    // ui mode type
-    if (getUiModeTypeName(part.string(), &config)) {
-        *axis = AXIS_UIMODETYPE;
-        value->intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
-        return true;
-    }
-
-    // ui mode night
-    if (getUiModeNightName(part.string(), &config)) {
-        *axis = AXIS_UIMODENIGHT;
-        value->intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
-        return true;
-    }
-
-    // density
-    if (getDensityName(part.string(), &config)) {
-        *axis = AXIS_DENSITY;
-        value->intValue = config.density;
-        return true;
-    }
-
-    // touchscreen
-    if (getTouchscreenName(part.string(), &config)) {
-        *axis = AXIS_TOUCHSCREEN;
-        value->intValue = config.touchscreen;
-        return true;
-    }
-
-    // keyboard hidden
-    if (getKeysHiddenName(part.string(), &config)) {
-        *axis = AXIS_KEYSHIDDEN;
-        value->intValue = config.inputFlags;
-        return true;
-    }
-
-    // keyboard
-    if (getKeyboardName(part.string(), &config)) {
-        *axis = AXIS_KEYBOARD;
-        value->intValue = config.keyboard;
-        return true;
-    }
-
-    // navigation hidden
-    if (getNavHiddenName(part.string(), &config)) {
-        *axis = AXIS_NAVHIDDEN;
-        value->intValue = config.inputFlags;
-        return 0;
-    }
-
-    // navigation
-    if (getNavigationName(part.string(), &config)) {
-        *axis = AXIS_NAVIGATION;
-        value->intValue = config.navigation;
-        return true;
-    }
-
-    // screen size
-    if (getScreenSizeName(part.string(), &config)) {
-        *axis = AXIS_SCREENSIZE;
-        value->intValue = config.screenSize;
-        return true;
-    }
-
-    // version
-    if (getVersionName(part.string(), &config)) {
-        *axis = AXIS_VERSION;
-        value->intValue = config.version;
-        return true;
-    }
-
-    return false;
-}
-
-AxisValue
-AaptGroupEntry::getConfigValueForAxis(const ResTable_config& config, int axis)
-{
-    AxisValue value;
-    switch (axis) {
-        case AXIS_MCC:
-            value.intValue = config.mcc;
-            break;
-        case AXIS_MNC:
-            value.intValue = config.mnc;
-            break;
-        case AXIS_LOCALE:
-            value.localeValue.initFromResTable(config);
-            break;
-        case AXIS_LAYOUTDIR:
-            value.intValue = config.screenLayout&ResTable_config::MASK_LAYOUTDIR;
-            break;
-        case AXIS_SCREENLAYOUTSIZE:
-            value.intValue = config.screenLayout&ResTable_config::MASK_SCREENSIZE;
-            break;
-        case AXIS_ORIENTATION:
-            value.intValue = config.orientation;
-            break;
-        case AXIS_UIMODETYPE:
-            value.intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
-            break;
-        case AXIS_UIMODENIGHT:
-            value.intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
-            break;
-        case AXIS_DENSITY:
-            value.intValue = config.density;
-            break;
-        case AXIS_TOUCHSCREEN:
-            value.intValue = config.touchscreen;
-            break;
-        case AXIS_KEYSHIDDEN:
-            value.intValue = config.inputFlags;
-            break;
-        case AXIS_KEYBOARD:
-            value.intValue = config.keyboard;
-            break;
-        case AXIS_NAVIGATION:
-            value.intValue = config.navigation;
-            break;
-        case AXIS_SCREENSIZE:
-            value.intValue = config.screenSize;
-            break;
-        case AXIS_SMALLESTSCREENWIDTHDP:
-            value.intValue = config.smallestScreenWidthDp;
-            break;
-        case AXIS_SCREENWIDTHDP:
-            value.intValue = config.screenWidthDp;
-            break;
-        case AXIS_SCREENHEIGHTDP:
-            value.intValue = config.screenHeightDp;
-            break;
-        case AXIS_VERSION:
-            value.intValue = config.version;
-            break;
-    }
-
-    return value;
-}
-
-bool
-AaptGroupEntry::configSameExcept(const ResTable_config& config,
-        const ResTable_config& otherConfig, int axis)
-{
-    for (int i=AXIS_START; i<=AXIS_END; i++) {
-        if (i == axis) {
-            continue;
-        }
-        if (getConfigValueForAxis(config, i) != getConfigValueForAxis(otherConfig, i)) {
-            return false;
-        }
-    }
-    return true;
-}
-
 bool
 AaptGroupEntry::initFromDirName(const char* dir, String8* resType)
 {
-    mParamsChanged = true;
+    const char* q = strchr(dir, '-');
+    size_t typeLen;
+    if (q != NULL) {
+        typeLen = q - dir;
+    } else {
+        typeLen = strlen(dir);
+    }
 
-    Vector<String8> parts;
-    AaptLocaleValue::splitAndLowerCase(dir, &parts, '-');
-
-    String8 mcc, mnc, layoutsize, layoutlong, orient, den;
-    String8 touch, key, keysHidden, nav, navHidden, size, layoutDir, vers;
-    String8 uiModeType, uiModeNight, smallestwidthdp, widthdp, heightdp;
-
-    AaptLocaleValue locale;
-    int numLocaleComponents = 0;
-
-    const int N = parts.size();
-    int index = 0;
-    String8 part = parts[index];
-
-    // resource type
-    if (!isValidResourceType(part)) {
+    String8 type(dir, typeLen);
+    if (!isValidResourceType(type)) {
         return false;
     }
-    *resType = part;
 
-    index++;
-    if (index == N) {
-        goto success;
-    }
-    part = parts[index];
-
-    // imsi - mcc
-    if (getMccName(part.string())) {
-        mcc = part;
-
-        index++;
-        if (index == N) {
-            goto success;
+    if (q != NULL) {
+        if (!AaptConfig::parse(String8(q + 1), &mParams)) {
+            return false;
         }
-        part = parts[index];
-    } else {
-        //printf("not mcc: %s\n", part.string());
     }
 
-    // imsi - mnc
-    if (getMncName(part.string())) {
-        mnc = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not mnc: %s\n", part.string());
-    }
-
-    index = locale.initFromDirName(parts, index);
-    if (index == -1) {
-        return false;
-    }
-    if (index >= N){
-        goto success;
-    }
-
-    part = parts[index];
-    if (getLayoutDirectionName(part.string())) {
-        layoutDir = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not layout direction: %s\n", part.string());
-    }
-
-    if (getSmallestScreenWidthDpName(part.string())) {
-        smallestwidthdp = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not smallest screen width dp: %s\n", part.string());
-    }
-
-    if (getScreenWidthDpName(part.string())) {
-        widthdp = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not screen width dp: %s\n", part.string());
-    }
-
-    if (getScreenHeightDpName(part.string())) {
-        heightdp = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not screen height dp: %s\n", part.string());
-    }
-
-    if (getScreenLayoutSizeName(part.string())) {
-        layoutsize = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not screen layout size: %s\n", part.string());
-    }
-
-    if (getScreenLayoutLongName(part.string())) {
-        layoutlong = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not screen layout long: %s\n", part.string());
-    }
-
-    // orientation
-    if (getOrientationName(part.string())) {
-        orient = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not orientation: %s\n", part.string());
-    }
-
-    // ui mode type
-    if (getUiModeTypeName(part.string())) {
-        uiModeType = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not ui mode type: %s\n", part.string());
-    }
-
-    // ui mode night
-    if (getUiModeNightName(part.string())) {
-        uiModeNight = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not ui mode night: %s\n", part.string());
-    }
-
-    // density
-    if (getDensityName(part.string())) {
-        den = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not density: %s\n", part.string());
-    }
-
-    // touchscreen
-    if (getTouchscreenName(part.string())) {
-        touch = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not touchscreen: %s\n", part.string());
-    }
-
-    // keyboard hidden
-    if (getKeysHiddenName(part.string())) {
-        keysHidden = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not keysHidden: %s\n", part.string());
-    }
-
-    // keyboard
-    if (getKeyboardName(part.string())) {
-        key = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not keyboard: %s\n", part.string());
-    }
-
-    // navigation hidden
-    if (getNavHiddenName(part.string())) {
-        navHidden = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not navHidden: %s\n", part.string());
-    }
-
-    if (getNavigationName(part.string())) {
-        nav = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not navigation: %s\n", part.string());
-    }
-
-    if (getScreenSizeName(part.string())) {
-        size = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not screen size: %s\n", part.string());
-    }
-
-    if (getVersionName(part.string())) {
-        vers = part;
-
-        index++;
-        if (index == N) {
-            goto success;
-        }
-        part = parts[index];
-    } else {
-        //printf("not version: %s\n", part.string());
-    }
-
-    // if there are extra parts, it doesn't match
-    return false;
-
-success:
-    this->mcc = mcc;
-    this->mnc = mnc;
-    this->locale = locale;
-    this->screenLayoutSize = layoutsize;
-    this->screenLayoutLong = layoutlong;
-    this->smallestScreenWidthDp = smallestwidthdp;
-    this->screenWidthDp = widthdp;
-    this->screenHeightDp = heightdp;
-    this->orientation = orient;
-    this->uiModeType = uiModeType;
-    this->uiModeNight = uiModeNight;
-    this->density = den;
-    this->touchscreen = touch;
-    this->keysHidden = keysHidden;
-    this->keyboard = key;
-    this->navHidden = navHidden;
-    this->navigation = nav;
-    this->screenSize = size;
-    this->layoutDirection = layoutDir;
-    this->version = vers;
-
-    // what is this anyway?
-    this->vendor = "";
-
+    *resType = type;
     return true;
 }
 
 String8
-AaptGroupEntry::toString() const
-{
-    String8 s = this->mcc;
-    s += ",";
-    s += this->mnc;
-    s += ",";
-    s += locale.toDirName();
-    s += ",";
-    s += layoutDirection;
-    s += ",";
-    s += smallestScreenWidthDp;
-    s += ",";
-    s += screenWidthDp;
-    s += ",";
-    s += screenHeightDp;
-    s += ",";
-    s += screenLayoutSize;
-    s += ",";
-    s += screenLayoutLong;
-    s += ",";
-    s += this->orientation;
-    s += ",";
-    s += uiModeType;
-    s += ",";
-    s += uiModeNight;
-    s += ",";
-    s += density;
-    s += ",";
-    s += touchscreen;
-    s += ",";
-    s += keysHidden;
-    s += ",";
-    s += keyboard;
-    s += ",";
-    s += navHidden;
-    s += ",";
-    s += navigation;
-    s += ",";
-    s += screenSize;
-    s += ",";
-    s += version;
-    return s;
-}
-
-String8
 AaptGroupEntry::toDirName(const String8& resType) const
 {
     String8 s = resType;
-    if (this->mcc != "") {
+    String8 params = mParams.toString();
+    if (params.length() > 0) {
         if (s.length() > 0) {
             s += "-";
         }
-        s += mcc;
+        s += params;
     }
-    if (this->mnc != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += mnc;
-    }
-
-    const String8 localeComponent = locale.toDirName();
-    if (localeComponent != "") {
-         if (s.length() > 0) {
-             s += "-";
-         }
-         s += localeComponent;
-    }
-
-    if (this->layoutDirection != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += layoutDirection;
-    }
-    if (this->smallestScreenWidthDp != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += smallestScreenWidthDp;
-    }
-    if (this->screenWidthDp != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += screenWidthDp;
-    }
-    if (this->screenHeightDp != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += screenHeightDp;
-    }
-    if (this->screenLayoutSize != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += screenLayoutSize;
-    }
-    if (this->screenLayoutLong != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += screenLayoutLong;
-    }
-    if (this->orientation != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += orientation;
-    }
-    if (this->uiModeType != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += uiModeType;
-    }
-    if (this->uiModeNight != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += uiModeNight;
-    }
-    if (this->density != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += density;
-    }
-    if (this->touchscreen != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += touchscreen;
-    }
-    if (this->keysHidden != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += keysHidden;
-    }
-    if (this->keyboard != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += keyboard;
-    }
-    if (this->navHidden != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += navHidden;
-    }
-    if (this->navigation != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += navigation;
-    }
-    if (this->screenSize != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += screenSize;
-    }
-    if (this->version != "") {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += version;
-    }
-
     return s;
 }
 
-bool AaptGroupEntry::getMccName(const char* name,
-                                    ResTable_config* out)
-{
-    if (strcmp(name, kWildcardName) == 0) {
-        if (out) out->mcc = 0;
-        return true;
-    }
-    const char* c = name;
-    if (tolower(*c) != 'm') return false;
-    c++;
-    if (tolower(*c) != 'c') return false;
-    c++;
-    if (tolower(*c) != 'c') return false;
-    c++;
-
-    const char* val = c;
-
-    while (*c >= '0' && *c <= '9') {
-        c++;
-    }
-    if (*c != 0) return false;
-    if (c-val != 3) return false;
-
-    int d = atoi(val);
-    if (d != 0) {
-        if (out) out->mcc = d;
-        return true;
-    }
-
-    return false;
-}
-
-bool AaptGroupEntry::getMncName(const char* name,
-                                    ResTable_config* out)
-{
-    if (strcmp(name, kWildcardName) == 0) {
-        if (out) out->mcc = 0;
-        return true;
-    }
-    const char* c = name;
-    if (tolower(*c) != 'm') return false;
-    c++;
-    if (tolower(*c) != 'n') return false;
-    c++;
-    if (tolower(*c) != 'c') return false;
-    c++;
-
-    const char* val = c;
-
-    while (*c >= '0' && *c <= '9') {
-        c++;
-    }
-    if (*c != 0) return false;
-    if (c-val == 0 || c-val > 3) return false;
-
-    if (out) {
-        out->mnc = atoi(val);
-        if (out->mnc == 0) {
-            out->mnc = ACONFIGURATION_MNC_ZERO;
-        }
-    }
-
-    return true;
-}
-
-bool AaptGroupEntry::getLayoutDirectionName(const char* name, ResTable_config* out)
-{
-    if (strcmp(name, kWildcardName) == 0) {
-        if (out) out->screenLayout =
-                (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR)
-                | ResTable_config::LAYOUTDIR_ANY;
-        return true;
-    } else if (strcmp(name, "ldltr") == 0) {
-        if (out) out->screenLayout =
-                (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR)
-                | ResTable_config::LAYOUTDIR_LTR;
-        return true;
-    } else if (strcmp(name, "ldrtl") == 0) {
-        if (out) out->screenLayout =
-                (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR)
-                | ResTable_config::LAYOUTDIR_RTL;
-        return true;
-    }
-
-    return false;
-}
-
-bool AaptGroupEntry::getScreenLayoutSizeName(const char* name,
-                                     ResTable_config* out)
-{
-    if (strcmp(name, kWildcardName) == 0) {
-        if (out) out->screenLayout =
-                (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
-                | ResTable_config::SCREENSIZE_ANY;
-        return true;
-    } else if (strcmp(name, "small") == 0) {
-        if (out) out->screenLayout =
-                (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
-                | ResTable_config::SCREENSIZE_SMALL;
-        return true;
-    } else if (strcmp(name, "normal") == 0) {
-        if (out) out->screenLayout =
-                (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
-                | ResTable_config::SCREENSIZE_NORMAL;
-        return true;
-    } else if (strcmp(name, "large") == 0) {
-        if (out) out->screenLayout =
-                (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
-                | ResTable_config::SCREENSIZE_LARGE;
-        return true;
-    } else if (strcmp(name, "xlarge") == 0) {
-        if (out) out->screenLayout =
-                (out->screenLayout&~ResTable_config::MASK_SCREENSIZE)
-                | ResTable_config::SCREENSIZE_XLARGE;
-        return true;
-    }
-
-    return false;
-}
-
-bool AaptGroupEntry::getScreenLayoutLongName(const char* name,
-                                     ResTable_config* out)
-{
-    if (strcmp(name, kWildcardName) == 0) {
-        if (out) out->screenLayout =
-                (out->screenLayout&~ResTable_config::MASK_SCREENLONG)
-                | ResTable_config::SCREENLONG_ANY;
-        return true;
-    } else if (strcmp(name, "long") == 0) {
-        if (out) out->screenLayout =
-                (out->screenLayout&~ResTable_config::MASK_SCREENLONG)
-                | ResTable_config::SCREENLONG_YES;
-        return true;
-    } else if (strcmp(name, "notlong") == 0) {
-        if (out) out->screenLayout =
-                (out->screenLayout&~ResTable_config::MASK_SCREENLONG)
-                | ResTable_config::SCREENLONG_NO;
-        return true;
-    }
-
-    return false;
-}
-
-bool AaptGroupEntry::getOrientationName(const char* name,
-                                        ResTable_config* out)
-{
-    if (strcmp(name, kWildcardName) == 0) {
-        if (out) out->orientation = out->ORIENTATION_ANY;
-        return true;
-    } else if (strcmp(name, "port") == 0) {
-        if (out) out->orientation = out->ORIENTATION_PORT;
-        return true;
-    } else if (strcmp(name, "land") == 0) {
-        if (out) out->orientation = out->ORIENTATION_LAND;
-        return true;
-    } else if (strcmp(name, "square") == 0) {
-        if (out) out->orientation = out->ORIENTATION_SQUARE;
-        return true;
-    }
-
-    return false;
-}
-
-bool AaptGroupEntry::getUiModeTypeName(const char* name,
-                                       ResTable_config* out)
-{
-    if (strcmp(name, kWildcardName) == 0) {
-        if (out) out->uiMode =
-                (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
-                | ResTable_config::UI_MODE_TYPE_ANY;
-        return true;
-    } else if (strcmp(name, "desk") == 0) {
-      if (out) out->uiMode =
-              (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
-              | ResTable_config::UI_MODE_TYPE_DESK;
-        return true;
-    } else if (strcmp(name, "car") == 0) {
-      if (out) out->uiMode =
-              (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
-              | ResTable_config::UI_MODE_TYPE_CAR;
-        return true;
-    } else if (strcmp(name, "television") == 0) {
-      if (out) out->uiMode =
-              (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
-              | ResTable_config::UI_MODE_TYPE_TELEVISION;
-        return true;
-    } else if (strcmp(name, "appliance") == 0) {
-      if (out) out->uiMode =
-              (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
-              | ResTable_config::UI_MODE_TYPE_APPLIANCE;
-        return true;
-    } else if (strcmp(name, "watch") == 0) {
-      if (out) out->uiMode =
-              (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
-              | ResTable_config::UI_MODE_TYPE_WATCH;
-        return true;
-    }
-
-    return false;
-}
-
-bool AaptGroupEntry::getUiModeNightName(const char* name,
-                                          ResTable_config* out)
-{
-    if (strcmp(name, kWildcardName) == 0) {
-        if (out) out->uiMode =
-                (out->uiMode&~ResTable_config::MASK_UI_MODE_NIGHT)
-                | ResTable_config::UI_MODE_NIGHT_ANY;
-        return true;
-    } else if (strcmp(name, "night") == 0) {
-        if (out) out->uiMode =
-                (out->uiMode&~ResTable_config::MASK_UI_MODE_NIGHT)
-                | ResTable_config::UI_MODE_NIGHT_YES;
-        return true;
-    } else if (strcmp(name, "notnight") == 0) {
-      if (out) out->uiMode =
-              (out->uiMode&~ResTable_config::MASK_UI_MODE_NIGHT)
-              | ResTable_config::UI_MODE_NIGHT_NO;
-        return true;
-    }
-
-    return false;
-}
-
-bool AaptGroupEntry::getDensityName(const char* name,
-                                    ResTable_config* out)
-{
-    if (strcmp(name, kWildcardName) == 0) {
-        if (out) out->density = ResTable_config::DENSITY_DEFAULT;
-        return true;
-    }
-    
-    if (strcmp(name, "nodpi") == 0) {
-        if (out) out->density = ResTable_config::DENSITY_NONE;
-        return true;
-    }
-    
-    if (strcmp(name, "ldpi") == 0) {
-        if (out) out->density = ResTable_config::DENSITY_LOW;
-        return true;
-    }
-    
-    if (strcmp(name, "mdpi") == 0) {
-        if (out) out->density = ResTable_config::DENSITY_MEDIUM;
-        return true;
-    }
-    
-    if (strcmp(name, "tvdpi") == 0) {
-        if (out) out->density = ResTable_config::DENSITY_TV;
-        return true;
-    }
-    
-    if (strcmp(name, "hdpi") == 0) {
-        if (out) out->density = ResTable_config::DENSITY_HIGH;
-        return true;
-    }
-
-    if (strcmp(name, "xhdpi") == 0) {
-        if (out) out->density = ResTable_config::DENSITY_XHIGH;
-        return true;
-    }
-
-    if (strcmp(name, "xxhdpi") == 0) {
-        if (out) out->density = ResTable_config::DENSITY_XXHIGH;
-        return true;
-    }
-
-    if (strcmp(name, "xxxhdpi") == 0) {
-        if (out) out->density = ResTable_config::DENSITY_XXXHIGH;
-        return true;
-    }
-
-    char* c = (char*)name;
-    while (*c >= '0' && *c <= '9') {
-        c++;
-    }
-
-    // check that we have 'dpi' after the last digit.
-    if (toupper(c[0]) != 'D' ||
-            toupper(c[1]) != 'P' ||
-            toupper(c[2]) != 'I' ||
-            c[3] != 0) {
-        return false;
-    }
-
-    // temporarily replace the first letter with \0 to
-    // use atoi.
-    char tmp = c[0];
-    c[0] = '\0';
-
-    int d = atoi(name);
-    c[0] = tmp;
-
-    if (d != 0) {
-        if (out) out->density = d;
-        return true;
-    }
-
-    return false;
-}
-
-bool AaptGroupEntry::getTouchscreenName(const char* name,
-                                        ResTable_config* out)
-{
-    if (strcmp(name, kWildcardName) == 0) {
-        if (out) out->touchscreen = out->TOUCHSCREEN_ANY;
-        return true;
-    } else if (strcmp(name, "notouch") == 0) {
-        if (out) out->touchscreen = out->TOUCHSCREEN_NOTOUCH;
-        return true;
-    } else if (strcmp(name, "stylus") == 0) {
-        if (out) out->touchscreen = out->TOUCHSCREEN_STYLUS;
-        return true;
-    } else if (strcmp(name, "finger") == 0) {
-        if (out) out->touchscreen = out->TOUCHSCREEN_FINGER;
-        return true;
-    }
-
-    return false;
-}
-
-bool AaptGroupEntry::getKeysHiddenName(const char* name,
-                                       ResTable_config* out)
-{
-    uint8_t mask = 0;
-    uint8_t value = 0;
-    if (strcmp(name, kWildcardName) == 0) {
-        mask = ResTable_config::MASK_KEYSHIDDEN;
-        value = ResTable_config::KEYSHIDDEN_ANY;
-    } else if (strcmp(name, "keysexposed") == 0) {
-        mask = ResTable_config::MASK_KEYSHIDDEN;
-        value = ResTable_config::KEYSHIDDEN_NO;
-    } else if (strcmp(name, "keyshidden") == 0) {
-        mask = ResTable_config::MASK_KEYSHIDDEN;
-        value = ResTable_config::KEYSHIDDEN_YES;
-    } else if (strcmp(name, "keyssoft") == 0) {
-        mask = ResTable_config::MASK_KEYSHIDDEN;
-        value = ResTable_config::KEYSHIDDEN_SOFT;
-    }
-
-    if (mask != 0) {
-        if (out) out->inputFlags = (out->inputFlags&~mask) | value;
-        return true;
-    }
-
-    return false;
-}
-
-bool AaptGroupEntry::getKeyboardName(const char* name,
-                                        ResTable_config* out)
-{
-    if (strcmp(name, kWildcardName) == 0) {
-        if (out) out->keyboard = out->KEYBOARD_ANY;
-        return true;
-    } else if (strcmp(name, "nokeys") == 0) {
-        if (out) out->keyboard = out->KEYBOARD_NOKEYS;
-        return true;
-    } else if (strcmp(name, "qwerty") == 0) {
-        if (out) out->keyboard = out->KEYBOARD_QWERTY;
-        return true;
-    } else if (strcmp(name, "12key") == 0) {
-        if (out) out->keyboard = out->KEYBOARD_12KEY;
-        return true;
-    }
-
-    return false;
-}
-
-bool AaptGroupEntry::getNavHiddenName(const char* name,
-                                       ResTable_config* out)
-{
-    uint8_t mask = 0;
-    uint8_t value = 0;
-    if (strcmp(name, kWildcardName) == 0) {
-        mask = ResTable_config::MASK_NAVHIDDEN;
-        value = ResTable_config::NAVHIDDEN_ANY;
-    } else if (strcmp(name, "navexposed") == 0) {
-        mask = ResTable_config::MASK_NAVHIDDEN;
-        value = ResTable_config::NAVHIDDEN_NO;
-    } else if (strcmp(name, "navhidden") == 0) {
-        mask = ResTable_config::MASK_NAVHIDDEN;
-        value = ResTable_config::NAVHIDDEN_YES;
-    }
-
-    if (mask != 0) {
-        if (out) out->inputFlags = (out->inputFlags&~mask) | value;
-        return true;
-    }
-
-    return false;
-}
-
-bool AaptGroupEntry::getNavigationName(const char* name,
-                                     ResTable_config* out)
-{
-    if (strcmp(name, kWildcardName) == 0) {
-        if (out) out->navigation = out->NAVIGATION_ANY;
-        return true;
-    } else if (strcmp(name, "nonav") == 0) {
-        if (out) out->navigation = out->NAVIGATION_NONAV;
-        return true;
-    } else if (strcmp(name, "dpad") == 0) {
-        if (out) out->navigation = out->NAVIGATION_DPAD;
-        return true;
-    } else if (strcmp(name, "trackball") == 0) {
-        if (out) out->navigation = out->NAVIGATION_TRACKBALL;
-        return true;
-    } else if (strcmp(name, "wheel") == 0) {
-        if (out) out->navigation = out->NAVIGATION_WHEEL;
-        return true;
-    }
-
-    return false;
-}
-
-bool AaptGroupEntry::getScreenSizeName(const char* name, ResTable_config* out)
-{
-    if (strcmp(name, kWildcardName) == 0) {
-        if (out) {
-            out->screenWidth = out->SCREENWIDTH_ANY;
-            out->screenHeight = out->SCREENHEIGHT_ANY;
-        }
-        return true;
-    }
-
-    const char* x = name;
-    while (*x >= '0' && *x <= '9') x++;
-    if (x == name || *x != 'x') return false;
-    String8 xName(name, x-name);
-    x++;
-
-    const char* y = x;
-    while (*y >= '0' && *y <= '9') y++;
-    if (y == name || *y != 0) return false;
-    String8 yName(x, y-x);
-
-    uint16_t w = (uint16_t)atoi(xName.string());
-    uint16_t h = (uint16_t)atoi(yName.string());
-    if (w < h) {
-        return false;
-    }
-
-    if (out) {
-        out->screenWidth = w;
-        out->screenHeight = h;
-    }
-
-    return true;
-}
-
-bool AaptGroupEntry::getSmallestScreenWidthDpName(const char* name, ResTable_config* out)
-{
-    if (strcmp(name, kWildcardName) == 0) {
-        if (out) {
-            out->smallestScreenWidthDp = out->SCREENWIDTH_ANY;
-        }
-        return true;
-    }
-
-    if (*name != 's') return false;
-    name++;
-    if (*name != 'w') return false;
-    name++;
-    const char* x = name;
-    while (*x >= '0' && *x <= '9') x++;
-    if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false;
-    String8 xName(name, x-name);
-
-    if (out) {
-        out->smallestScreenWidthDp = (uint16_t)atoi(xName.string());
-    }
-
-    return true;
-}
-
-bool AaptGroupEntry::getScreenWidthDpName(const char* name, ResTable_config* out)
-{
-    if (strcmp(name, kWildcardName) == 0) {
-        if (out) {
-            out->screenWidthDp = out->SCREENWIDTH_ANY;
-        }
-        return true;
-    }
-
-    if (*name != 'w') return false;
-    name++;
-    const char* x = name;
-    while (*x >= '0' && *x <= '9') x++;
-    if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false;
-    String8 xName(name, x-name);
-
-    if (out) {
-        out->screenWidthDp = (uint16_t)atoi(xName.string());
-    }
-
-    return true;
-}
-
-bool AaptGroupEntry::getScreenHeightDpName(const char* name, ResTable_config* out)
-{
-    if (strcmp(name, kWildcardName) == 0) {
-        if (out) {
-            out->screenHeightDp = out->SCREENWIDTH_ANY;
-        }
-        return true;
-    }
-
-    if (*name != 'h') return false;
-    name++;
-    const char* x = name;
-    while (*x >= '0' && *x <= '9') x++;
-    if (x == name || x[0] != 'd' || x[1] != 'p' || x[2] != 0) return false;
-    String8 xName(name, x-name);
-
-    if (out) {
-        out->screenHeightDp = (uint16_t)atoi(xName.string());
-    }
-
-    return true;
-}
-
-bool AaptGroupEntry::getVersionName(const char* name, ResTable_config* out)
-{
-    if (strcmp(name, kWildcardName) == 0) {
-        if (out) {
-            out->sdkVersion = out->SDKVERSION_ANY;
-            out->minorVersion = out->MINORVERSION_ANY;
-        }
-        return true;
-    }
-
-    if (*name != 'v') {
-        return false;
-    }
-
-    name++;
-    const char* s = name;
-    while (*s >= '0' && *s <= '9') s++;
-    if (s == name || *s != 0) return false;
-    String8 sdkName(name, s-name);
-
-    if (out) {
-        out->sdkVersion = (uint16_t)atoi(sdkName.string());
-        out->minorVersion = 0;
-    }
-
-    return true;
-}
-
-int AaptGroupEntry::compare(const AaptGroupEntry& o) const
-{
-    int v = mcc.compare(o.mcc);
-    if (v == 0) v = mnc.compare(o.mnc);
-    if (v == 0) v = locale.compare(o.locale);
-    if (v == 0) v = layoutDirection.compare(o.layoutDirection);
-    if (v == 0) v = vendor.compare(o.vendor);
-    if (v == 0) v = smallestScreenWidthDp.compare(o.smallestScreenWidthDp);
-    if (v == 0) v = screenWidthDp.compare(o.screenWidthDp);
-    if (v == 0) v = screenHeightDp.compare(o.screenHeightDp);
-    if (v == 0) v = screenLayoutSize.compare(o.screenLayoutSize);
-    if (v == 0) v = screenLayoutLong.compare(o.screenLayoutLong);
-    if (v == 0) v = orientation.compare(o.orientation);
-    if (v == 0) v = uiModeType.compare(o.uiModeType);
-    if (v == 0) v = uiModeNight.compare(o.uiModeNight);
-    if (v == 0) v = density.compare(o.density);
-    if (v == 0) v = touchscreen.compare(o.touchscreen);
-    if (v == 0) v = keysHidden.compare(o.keysHidden);
-    if (v == 0) v = keyboard.compare(o.keyboard);
-    if (v == 0) v = navHidden.compare(o.navHidden);
-    if (v == 0) v = navigation.compare(o.navigation);
-    if (v == 0) v = screenSize.compare(o.screenSize);
-    if (v == 0) v = version.compare(o.version);
-    return v;
-}
-
-const ResTable_config AaptGroupEntry::toParams() const
-{
-    if (!mParamsChanged) {
-        return mParams;
-    }
-
-    mParamsChanged = false;
-    ResTable_config& params = mParams;
-    memset(&params, 0, sizeof(ResTable_config));
-    getMccName(mcc.string(), &params);
-    getMncName(mnc.string(), &params);
-    locale.writeTo(&params);
-    getLayoutDirectionName(layoutDirection.string(), &params);
-    getSmallestScreenWidthDpName(smallestScreenWidthDp.string(), &params);
-    getScreenWidthDpName(screenWidthDp.string(), &params);
-    getScreenHeightDpName(screenHeightDp.string(), &params);
-    getScreenLayoutSizeName(screenLayoutSize.string(), &params);
-    getScreenLayoutLongName(screenLayoutLong.string(), &params);
-    getOrientationName(orientation.string(), &params);
-    getUiModeTypeName(uiModeType.string(), &params);
-    getUiModeNightName(uiModeNight.string(), &params);
-    getDensityName(density.string(), &params);
-    getTouchscreenName(touchscreen.string(), &params);
-    getKeysHiddenName(keysHidden.string(), &params);
-    getKeyboardName(keyboard.string(), &params);
-    getNavHiddenName(navHidden.string(), &params);
-    getNavigationName(navigation.string(), &params);
-    getScreenSizeName(screenSize.string(), &params);
-    getVersionName(version.string(), &params);
-    
-    // Fix up version number based on specified parameters.
-    int minSdk = 0;
-    if (params.smallestScreenWidthDp != ResTable_config::SCREENWIDTH_ANY
-            || params.screenWidthDp != ResTable_config::SCREENWIDTH_ANY
-            || params.screenHeightDp != ResTable_config::SCREENHEIGHT_ANY) {
-        minSdk = SDK_HONEYCOMB_MR2;
-    } else if ((params.uiMode&ResTable_config::MASK_UI_MODE_TYPE)
-                != ResTable_config::UI_MODE_TYPE_ANY
-            ||  (params.uiMode&ResTable_config::MASK_UI_MODE_NIGHT)
-                != ResTable_config::UI_MODE_NIGHT_ANY) {
-        minSdk = SDK_FROYO;
-    } else if ((params.screenLayout&ResTable_config::MASK_SCREENSIZE)
-                != ResTable_config::SCREENSIZE_ANY
-            ||  (params.screenLayout&ResTable_config::MASK_SCREENLONG)
-                != ResTable_config::SCREENLONG_ANY
-            || params.density != ResTable_config::DENSITY_DEFAULT) {
-        minSdk = SDK_DONUT;
-    }
-    
-    if (minSdk > params.sdkVersion) {
-        params.sdkVersion = minSdk;
-    }
-    
-    return params;
-}
 
 // =========================================================================
 // =========================================================================
@@ -2229,9 +907,7 @@
     : AaptDir(String8(), String8()),
       mHavePrivateSymbols(false),
       mChanged(false), mHaveIncludedAssets(false),
-      mRes(NULL)
-{
-}
+      mRes(NULL) {}
 
 const SortedVector<AaptGroupEntry>& AaptAssets::getGroupEntries() const {
     if (mChanged) {
@@ -2506,7 +1182,7 @@
         String8 resType;
         bool b = group.initFromDirName(entry->d_name, &resType);
         if (!b) {
-            fprintf(stderr, "invalid resource directory name: %s/%s\n", srcDir.string(),
+            fprintf(stderr, "invalid resource directory name: %s %s\n", srcDir.string(),
                     entry->d_name);
             err = -1;
             continue;
@@ -2654,30 +1330,35 @@
 
 status_t AaptAssets::filter(Bundle* bundle)
 {
-    ResourceFilter reqFilter;
+    WeakResourceFilter reqFilter;
     status_t err = reqFilter.parse(bundle->getConfigurations());
     if (err != NO_ERROR) {
         return err;
     }
 
-    ResourceFilter prefFilter;
-    err = prefFilter.parse(bundle->getPreferredConfigurations());
-    if (err != NO_ERROR) {
-        return err;
+    uint32_t preferredDensity = 0;
+    if (bundle->getPreferredDensity().size() > 0) {
+        ResTable_config preferredConfig;
+        if (!AaptConfig::parseDensity(bundle->getPreferredDensity().string(), &preferredConfig)) {
+            fprintf(stderr, "Error parsing preferred density: %s\n",
+                    bundle->getPreferredDensity().string());
+            return UNKNOWN_ERROR;
+        }
+        preferredDensity = preferredConfig.density;
     }
 
-    if (reqFilter.isEmpty() && prefFilter.isEmpty()) {
+    if (reqFilter.isEmpty() && preferredDensity == 0) {
         return NO_ERROR;
     }
 
     if (bundle->getVerbose()) {
         if (!reqFilter.isEmpty()) {
             printf("Applying required filter: %s\n",
-                    bundle->getConfigurations());
+                    bundle->getConfigurations().string());
         }
-        if (!prefFilter.isEmpty()) {
-            printf("Applying preferred filter: %s\n",
-                    bundle->getPreferredConfigurations());
+        if (preferredDensity > 0) {
+            printf("Applying preferred density filter: %s\n",
+                    bundle->getPreferredDensity().string());
         }
     }
 
@@ -2734,89 +1415,71 @@
             }
 
             // Quick check: no preferred filters, nothing more to do.
-            if (prefFilter.isEmpty()) {
+            if (preferredDensity == 0) {
                 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<AxisValue>* preferredConfigs = prefFilter.configsForAxis(AXIS_DENSITY);
-            if (preferredConfigs != NULL && preferredConfigs->size() > 0) {
-                preferredDensity = (*preferredConfigs)[0].intValue;
-            }
+            for (size_t k=0; k<grp->getFiles().size(); k++) {
+                sp<AaptFile> file = grp->getFiles().valueAt(k);
+                if (k == 0 && grp->getFiles().size() == 1) {
+                    // If this is the only file left, we need to keep it.
+                    // Otherwise the resource IDs we are using will be inconsistent
+                    // with what we get when not stripping.  Sucky, but at least
+                    // for now we can rely on the back-end doing another filtering
+                    // pass to take this out and leave us with this resource name
+                    // containing no entries.
+                    continue;
+                }
+                if (file->getPath().getPathExtension() == ".xml") {
+                    // We can't remove .xml files at this point, because when
+                    // we parse them they may add identifier resources, so
+                    // removing them can cause our resource identifiers to
+                    // become inconsistent.
+                    continue;
+                }
+                const ResTable_config& config(file->getGroupEntry().toParams());
+                if (config.density != 0 && config.density != preferredDensity) {
+                    // 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;
 
-            // Now deal with preferred configurations.
-            for (int axis=AXIS_START; axis<=AXIS_END; axis++) {
-                for (size_t k=0; k<grp->getFiles().size(); k++) {
-                    sp<AaptFile> file = grp->getFiles().valueAt(k);
-                    if (k == 0 && grp->getFiles().size() == 1) {
-                        // If this is the only file left, we need to keep it.
-                        // Otherwise the resource IDs we are using will be inconsistent
-                        // with what we get when not stripping.  Sucky, but at least
-                        // for now we can rely on the back-end doing another filtering
-                        // pass to take this out and leave us with this resource name
-                        // containing no entries.
-                        continue;
-                    }
-                    if (file->getPath().getPathExtension() == ".xml") {
-                        // We can't remove .xml files at this point, because when
-                        // we parse them they may add identifier resources, so
-                        // removing them can cause our resource identifiers to
-                        // become inconsistent.
-                        continue;
-                    }
-                    const ResTable_config& config(file->getGroupEntry().toParams());
-                    if (!prefFilter.match(axis, config)) {
-                        // 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 (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());
-                                    }
-                                    grp->removeFile(k);
-                                    k--;
-                                    break;
-                                }
-                            }
+                    for (size_t m=0; m<grp->getFiles().size(); m++) {
+                        if (m == k) {
+                            continue;
                         }
 
-                        if (axis == AXIS_DENSITY && preferredDensity > 0 &&
-                                bestDensity != config.density) {
-                            if (bundle->getVerbose()) {
-                                printf("Pruning unneeded resource: %s\n",
-                                        file->getPrintableSource().string());
+                        sp<AaptFile> mfile = grp->getFiles().valueAt(m);
+                        const ResTable_config& mconfig(mfile->getGroupEntry().toParams());
+                        if (AaptConfig::isSameExcept(config, mconfig, ResTable_config::CONFIG_DENSITY)) {
+                            // 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;
                             }
-                            grp->removeFile(k);
-                            k--;
                         }
                     }
+
+                    if (bestDensity != config.density) {
+                        if (bundle->getVerbose()) {
+                            printf("Pruning unneeded resource: %s\n",
+                                    file->getPrintableSource().string());
+                        }
+                        grp->removeFile(k);
+                        k--;
+                    }
                 }
             }
         }