]> git.saurik.com Git - android/aapt.git/blobdiff - AaptAssets.cpp
Add new landscape and portrait orientation features.
[android/aapt.git] / AaptAssets.cpp
index 67af116d372dc5e67dff6bc01cba8e13d053fb2e..29d2b872eadd61f55a903d8fb830a56907bd95bc 100644 (file)
@@ -55,6 +55,7 @@ static bool validateFileName(const char* fileName)
 
 static bool isHidden(const char *root, const char *path)
 {
+    const char *ext  = NULL;
     const char *type = NULL;
 
     // Skip all hidden files.
@@ -83,6 +84,9 @@ static bool isHidden(const char *root, const char *path)
     } else if (path[strlen(path)-1] == '~') {
         // Skip suspected emacs backup files.
         type = "backup";
+    } else if ((ext = strrchr(path, '.')) != NULL && strcmp(ext, ".scc") == 0) {
+        // Skip VisualSourceSafe files and don't chatter about it
+        return true;
     } else {
         // Let everything else through.
         return false;
@@ -138,6 +142,41 @@ AaptGroupEntry::parseNamePart(const String8& part, int* axis, uint32_t* value)
         return 0;
     }
 
+    // smallest screen dp width
+    if (getSmallestScreenWidthDpName(part.string(), &config)) {
+        *axis = AXIS_SMALLESTSCREENWIDTHDP;
+        *value = config.smallestScreenWidthDp;
+        return 0;
+    }
+
+    // screen dp width
+    if (getScreenWidthDpName(part.string(), &config)) {
+        *axis = AXIS_SCREENWIDTHDP;
+        *value = config.screenWidthDp;
+        return 0;
+    }
+
+    // screen dp height
+    if (getScreenHeightDpName(part.string(), &config)) {
+        *axis = AXIS_SCREENHEIGHTDP;
+        *value = config.screenHeightDp;
+        return 0;
+    }
+
+    // screen layout size
+    if (getScreenLayoutSizeName(part.string(), &config)) {
+        *axis = AXIS_SCREENLAYOUTSIZE;
+        *value = (config.screenLayout&ResTable_config::MASK_SCREENSIZE);
+        return 0;
+    }
+
+    // screen layout long
+    if (getScreenLayoutLongName(part.string(), &config)) {
+        *axis = AXIS_SCREENLAYOUTLONG;
+        *value = (config.screenLayout&ResTable_config::MASK_SCREENLONG);
+        return 0;
+    }
+
     // orientation
     if (getOrientationName(part.string(), &config)) {
         *axis = AXIS_ORIENTATION;
@@ -145,6 +184,20 @@ AaptGroupEntry::parseNamePart(const String8& part, int* axis, uint32_t* value)
         return 0;
     }
 
+    // ui mode type
+    if (getUiModeTypeName(part.string(), &config)) {
+        *axis = AXIS_UIMODETYPE;
+        *value = (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
+        return 0;
+    }
+
+    // ui mode night
+    if (getUiModeNightName(part.string(), &config)) {
+        *axis = AXIS_UIMODENIGHT;
+        *value = (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
+        return 0;
+    }
+
     // density
     if (getDensityName(part.string(), &config)) {
         *axis = AXIS_DENSITY;
@@ -173,6 +226,13 @@ AaptGroupEntry::parseNamePart(const String8& part, int* axis, uint32_t* value)
         return 0;
     }
 
+    // navigation hidden
+    if (getNavHiddenName(part.string(), &config)) {
+        *axis = AXIS_NAVHIDDEN;
+        *value = config.inputFlags;
+        return 0;
+    }
+
     // navigation
     if (getNavigationName(part.string(), &config)) {
         *axis = AXIS_NAVIGATION;
@@ -187,13 +247,6 @@ AaptGroupEntry::parseNamePart(const String8& part, int* axis, uint32_t* value)
         return 0;
     }
 
-    // screen layout
-    if (getScreenLayoutName(part.string(), &config)) {
-        *axis = AXIS_SCREENLAYOUT;
-        *value = config.screenLayout;
-        return 0;
-    }
-
     // version
     if (getVersionName(part.string(), &config)) {
         *axis = AXIS_VERSION;
@@ -209,7 +262,9 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType)
 {
     Vector<String8> parts;
 
-    String8 mcc, mnc, loc, orient, den, touch, key, keysHidden, nav, size, layout, vers;
+    String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den;
+    String8 touch, key, keysHidden, nav, navHidden, size, vers;
+    String8 uiModeType, uiModeNight, smallestwidthdp, widthdp, heightdp;
 
     const char *p = dir;
     const char *q;
@@ -296,6 +351,66 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType)
         //printf("not region: %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;
@@ -309,6 +424,32 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType)
         //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;
@@ -361,8 +502,9 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType)
         //printf("not keyboard: %s\n", part.string());
     }
 
-    if (getNavigationName(part.string())) {
-        nav = part;
+    // navigation hidden
+    if (getNavHiddenName(part.string())) {
+        navHidden = part;
 
         index++;
         if (index == N) {
@@ -370,11 +512,11 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType)
         }
         part = parts[index];
     } else {
-        //printf("not navigation: %s\n", part.string());
+        //printf("not navHidden: %s\n", part.string());
     }
 
-    if (getScreenSizeName(part.string())) {
-        size = part;
+    if (getNavigationName(part.string())) {
+        nav = part;
 
         index++;
         if (index == N) {
@@ -382,11 +524,11 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType)
         }
         part = parts[index];
     } else {
-        //printf("not screen size: %s\n", part.string());
+        //printf("not navigation: %s\n", part.string());
     }
 
-    if (getScreenLayoutName(part.string())) {
-        layout = part;
+    if (getScreenSizeName(part.string())) {
+        size = part;
 
         index++;
         if (index == N) {
@@ -394,7 +536,7 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType)
         }
         part = parts[index];
     } else {
-        //printf("not screen layout: %s\n", part.string());
+        //printf("not screen size: %s\n", part.string());
     }
 
     if (getVersionName(part.string())) {
@@ -416,14 +558,21 @@ success:
     this->mcc = mcc;
     this->mnc = mnc;
     this->locale = loc;
+    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->screenLayout = layout;
     this->version = vers;
 
     // what is this anyway?
@@ -441,8 +590,22 @@ AaptGroupEntry::toString() const
     s += ",";
     s += this->locale;
     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;
@@ -451,12 +614,12 @@ AaptGroupEntry::toString() const
     s += ",";
     s += keyboard;
     s += ",";
+    s += navHidden;
+    s += ",";
     s += navigation;
     s += ",";
     s += screenSize;
     s += ",";
-    s += screenLayout;
-    s += ",";
     s += version;
     return s;
 }
@@ -477,10 +640,38 @@ AaptGroupEntry::toDirName(const String8& resType) const
         s += "-";
         s += locale;
     }
+    if (this->smallestScreenWidthDp != "") {
+        s += "-";
+        s += smallestScreenWidthDp;
+    }
+    if (this->screenWidthDp != "") {
+        s += "-";
+        s += screenWidthDp;
+    }
+    if (this->screenHeightDp != "") {
+        s += "-";
+        s += screenHeightDp;
+    }
+    if (this->screenLayoutSize != "") {
+        s += "-";
+        s += screenLayoutSize;
+    }
+    if (this->screenLayoutLong != "") {
+        s += "-";
+        s += screenLayoutLong;
+    }
     if (this->orientation != "") {
         s += "-";
         s += orientation;
     }
+    if (this->uiModeType != "") {
+        s += "-";
+        s += uiModeType;
+    }
+    if (this->uiModeNight != "") {
+        s += "-";
+        s += uiModeNight;
+    }
     if (this->density != "") {
         s += "-";
         s += density;
@@ -497,6 +688,10 @@ AaptGroupEntry::toDirName(const String8& resType) const
         s += "-";
         s += keyboard;
     }
+    if (this->navHidden != "") {
+        s += "-";
+        s += navHidden;
+    }
     if (this->navigation != "") {
         s += "-";
         s += navigation;
@@ -505,10 +700,6 @@ AaptGroupEntry::toDirName(const String8& resType) const
         s += "-";
         s += screenSize;
     }
-    if (this->screenLayout != "") {
-        s += "-";
-        s += screenLayout;
-    }
     if (this->version != "") {
         s += "-";
         s += version;
@@ -572,13 +763,11 @@ bool AaptGroupEntry::getMncName(const char* name,
     if (*c != 0) return false;
     if (c-val == 0 || c-val > 3) return false;
 
-    int d = atoi(val);
-    if (d != 0) {
-        if (out) out->mnc = d;
-        return true;
+    if (out) {
+        out->mnc = atoi(val);
     }
 
-    return false;
+    return true;
 }
 
 /*
@@ -630,6 +819,62 @@ bool AaptGroupEntry::getLocaleName(const char* fileName,
     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)
 {
@@ -650,13 +895,95 @@ bool AaptGroupEntry::getOrientationName(const char* name,
     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;
+    }
+
+    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 = 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_MEDIUM*2;
         return true;
     }
+    
     char* c = (char*)name;
     while (*c >= '0' && *c <= '9') {
         c++;
@@ -712,17 +1039,17 @@ bool AaptGroupEntry::getKeysHiddenName(const char* name,
     uint8_t mask = 0;
     uint8_t value = 0;
     if (strcmp(name, kWildcardName) == 0) {
-        mask = out->MASK_KEYSHIDDEN;
-        value = out->KEYSHIDDEN_ANY;
+        mask = ResTable_config::MASK_KEYSHIDDEN;
+        value = ResTable_config::KEYSHIDDEN_ANY;
     } else if (strcmp(name, "keysexposed") == 0) {
-        mask = out->MASK_KEYSHIDDEN;
-        value = out->KEYSHIDDEN_NO;
+        mask = ResTable_config::MASK_KEYSHIDDEN;
+        value = ResTable_config::KEYSHIDDEN_NO;
     } else if (strcmp(name, "keyshidden") == 0) {
-        mask = out->MASK_KEYSHIDDEN;
-        value = out->KEYSHIDDEN_YES;
+        mask = ResTable_config::MASK_KEYSHIDDEN;
+        value = ResTable_config::KEYSHIDDEN_YES;
     } else if (strcmp(name, "keyssoft") == 0) {
-        mask = out->MASK_KEYSHIDDEN;
-        value = out->KEYSHIDDEN_SOFT;
+        mask = ResTable_config::MASK_KEYSHIDDEN;
+        value = ResTable_config::KEYSHIDDEN_SOFT;
     }
 
     if (mask != 0) {
@@ -753,6 +1080,30 @@ bool AaptGroupEntry::getKeyboardName(const char* name,
     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)
 {
@@ -776,8 +1127,7 @@ bool AaptGroupEntry::getNavigationName(const char* name,
     return false;
 }
 
-bool AaptGroupEntry::getScreenSizeName(const char* name,
-                                       ResTable_config* out)
+bool AaptGroupEntry::getScreenSizeName(const char* name, ResTable_config* out)
 {
     if (strcmp(name, kWildcardName) == 0) {
         if (out) {
@@ -812,28 +1162,78 @@ bool AaptGroupEntry::getScreenSizeName(const char* name,
     return true;
 }
 
-bool AaptGroupEntry::getScreenLayoutName(const char* name,
-                                     ResTable_config* out)
+bool AaptGroupEntry::getSmallestScreenWidthDpName(const char* name, ResTable_config* out)
 {
     if (strcmp(name, kWildcardName) == 0) {
-        if (out) out->screenLayout = out->SCREENLAYOUT_ANY;
-        return true;
-    } else if (strcmp(name, "smallscreen") == 0) {
-        if (out) out->screenLayout = out->SCREENLAYOUT_SMALL;
+        if (out) {
+            out->smallestScreenWidthDp = out->SCREENWIDTH_ANY;
+        }
         return true;
-    } else if (strcmp(name, "normalscreen") == 0) {
-        if (out) out->screenLayout = out->SCREENLAYOUT_NORMAL;
+    }
+
+    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;
-    } else if (strcmp(name, "largescreen") == 0) {
-        if (out) out->screenLayout = out->SCREENLAYOUT_LARGE;
+    }
+
+    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;
     }
 
-    return false;
+    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)
+bool AaptGroupEntry::getVersionName(const char* name, ResTable_config* out)
 {
     if (strcmp(name, kWildcardName) == 0) {
         if (out) {
@@ -867,14 +1267,21 @@ int AaptGroupEntry::compare(const AaptGroupEntry& o) const
     if (v == 0) v = mnc.compare(o.mnc);
     if (v == 0) v = locale.compare(o.locale);
     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 = screenLayout.compare(o.screenLayout);
     if (v == 0) v = version.compare(o.version);
     return v;
 }
@@ -886,15 +1293,46 @@ ResTable_config AaptGroupEntry::toParams() const
     getMccName(mcc.string(), &params);
     getMncName(mnc.string(), &params);
     getLocaleName(locale.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);
-    getScreenLayoutName(screenLayout.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;
 }
 
@@ -1557,6 +1995,16 @@ ssize_t AaptAssets::slurpResourceTree(Bundle* bundle, const String8& srcDir)
             continue;
         }
 
+        if (bundle->getMaxResVersion() != NULL && group.version.length() != 0) {
+            int maxResInt = atoi(bundle->getMaxResVersion());
+            const char *verString = group.version.string();
+            int dirVersionInt = atoi(verString + 1); // skip 'v' in version name
+            if (dirVersionInt > maxResInt) {
+              fprintf(stderr, "max res %d, skipping %s\n", maxResInt, entry->d_name);
+              continue;
+            }
+        }
+
         FileType type = getFileType(subdirName.string());
 
         if (type == kFileTypeDirectory) {
@@ -1738,6 +2186,19 @@ void AaptAssets::print() const
     AaptDir::print();
 }
 
+sp<AaptDir> AaptAssets::resDir(const String8& name)
+{
+    const Vector<sp<AaptDir> >& dirs = mDirs;
+    const size_t N = dirs.size();
+    for (size_t i=0; i<N; i++) {
+        const sp<AaptDir>& d = dirs.itemAt(i);
+        if (d->getLeaf() == name) {
+            return d;
+        }
+    }
+    return NULL;
+}
+
 bool
 valid_symbol_name(const String8& symbol)
 {