]> git.saurik.com Git - android/aapt.git/commitdiff
am ba6c98db: am 82943ecf: am d40c93f6: Merge "Add dependency generation to Aapt for...
authorXavier Ducrohet <xav@android.com>
Tue, 19 Jul 2011 17:18:28 +0000 (10:18 -0700)
committerAndroid Git Automerger <android-git-automerger@android.com>
Tue, 19 Jul 2011 17:18:28 +0000 (10:18 -0700)
* commit 'ba6c98db8f21016f81ecac35bb0ea3c433044bb7':
  Add dependency generation to Aapt for R.java

1  2 
AaptAssets.cpp
AaptAssets.h
Command.cpp
Resource.cpp

diff --combined AaptAssets.cpp
index 29d2b872eadd61f55a903d8fb830a56907bd95bc,9c5a51400465f66f7ae77b5e1adaa742dbf14066..b35878a7b313fde3f0575c0f4abee28e014077d2
@@@ -142,27 -142,6 +142,27 @@@ AaptGroupEntry::parseNamePart(const Str
          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;
@@@ -264,7 -243,7 +264,7 @@@ AaptGroupEntry::initFromDirName(const c
  
      String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den;
      String8 touch, key, keysHidden, nav, navHidden, size, vers;
 -    String8 uiModeType, uiModeNight;
 +    String8 uiModeType, uiModeNight, smallestwidthdp, widthdp, heightdp;
  
      const char *p = dir;
      const char *q;
          //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;
  
@@@ -560,9 -503,6 +560,9 @@@ success
      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;
@@@ -590,12 -530,6 +590,12 @@@ AaptGroupEntry::toString() cons
      s += ",";
      s += this->locale;
      s += ",";
 +    s += smallestScreenWidthDp;
 +    s += ",";
 +    s += screenWidthDp;
 +    s += ",";
 +    s += screenHeightDp;
 +    s += ",";
      s += screenLayoutSize;
      s += ",";
      s += screenLayoutLong;
@@@ -640,18 -574,6 +640,18 @@@ AaptGroupEntry::toDirName(const String8
          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;
@@@ -913,11 -835,6 +913,11 @@@ bool AaptGroupEntry::getUiModeTypeName(
                (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;
@@@ -969,11 -886,6 +969,11 @@@ bool AaptGroupEntry::getDensityName(con
          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;
@@@ -1127,7 -1039,8 +1127,7 @@@ bool AaptGroupEntry::getNavigationName(
      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) {
      return true;
  }
  
 -bool AaptGroupEntry::getVersionName(const char* name,
 -                                    ResTable_config* out)
 +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) {
@@@ -1267,9 -1110,6 +1267,9 @@@ int AaptGroupEntry::compare(const AaptG
      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);
@@@ -1293,9 -1133,6 +1293,9 @@@ ResTable_config AaptGroupEntry::toParam
      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);
      
      // Fix up version number based on specified parameters.
      int minSdk = 0;
 -    if ((params.uiMode&ResTable_config::MASK_UI_MODE_TYPE)
 +    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) {
@@@ -1560,10 -1393,10 +1560,10 @@@ status_t AaptDir::addLeafFile(const Str
  }
  
  ssize_t AaptDir::slurpFullTree(Bundle* bundle, const String8& srcDir,
-                             const AaptGroupEntry& kind, const String8& resType)
+                             const AaptGroupEntry& kind, const String8& resType,
+                             sp<FilePathStore>& fullResPaths)
  {
      Vector<String8> fileNames;
      {
          DIR* dir = NULL;
  
              if (isHidden(srcDir.string(), entry->d_name))
                  continue;
  
-             fileNames.add(String8(entry->d_name));
+             String8 name(entry->d_name);
+             fileNames.add(name);
+             // Add fully qualified path for dependency purposes
+             // if we're collecting them
+             if (fullResPaths != NULL) {
+                 fullResPaths->add(srcDir.appendPathCopy(name));
+             }
          }
          closedir(dir);
      }
  
                  notAdded = true;
              }
              ssize_t res = subdir->slurpFullTree(bundle, pathName, kind,
-                                                 resType);
+                                                 resType, fullResPaths);
              if (res < NO_ERROR) {
                  return res;
              }
@@@ -1847,7 -1685,7 +1852,7 @@@ ssize_t AaptAssets::slurpFromArgs(Bundl
          sp<AaptDir> assetAaptDir = makeDir(String8(kAssetDir));
          AaptGroupEntry group;
          count = assetAaptDir->slurpFullTree(bundle, assetRoot, group,
-                                             String8());
+                                             String8(), mFullResPaths);
          if (count < 0) {
              totalCount = count;
              goto bail;
                      sp<AaptAssets> nextOverlay = new AaptAssets();
                      current->setOverlay(nextOverlay);
                      current = nextOverlay;
+                     current->setFullResPaths(mFullResPaths);
                  }
                  count = current->slurpResourceTree(bundle, String8(res));
  
           * guarantees about ordering, so we're okay with an inorder search
           * using whatever order the OS happens to hand back to us.
           */
-         count = slurpFullTree(bundle, assetRoot, AaptGroupEntry(), String8());
+         count = slurpFullTree(bundle, assetRoot, AaptGroupEntry(), String8(), mFullResPaths);
          if (count < 0) {
              /* failure; report error and remove archive */
              totalCount = count;
@@@ -1946,9 -1785,10 +1952,10 @@@ bail
  
  ssize_t AaptAssets::slurpFullTree(Bundle* bundle, const String8& srcDir,
                                      const AaptGroupEntry& kind,
-                                     const String8& resType)
+                                     const String8& resType,
+                                     sp<FilePathStore>& fullResPaths)
  {
-     ssize_t res = AaptDir::slurpFullTree(bundle, srcDir, kind, resType);
+     ssize_t res = AaptDir::slurpFullTree(bundle, srcDir, kind, resType, fullResPaths);
      if (res > 0) {
          mGroupEntries.add(kind);
      }
@@@ -2010,7 -1850,7 +2017,7 @@@ ssize_t AaptAssets::slurpResourceTree(B
          if (type == kFileTypeDirectory) {
              sp<AaptDir> dir = makeDir(String8(entry->d_name));
              ssize_t res = dir->slurpFullTree(bundle, subdirName, group,
-                                                 resType);
+                                                 resType, mFullResPaths);
              if (res < 0) {
                  count = res;
                  goto bail;
diff --combined AaptAssets.h
index 65743d80f35b33732d433034b947718808eafe68,cdde5adc77aa5b2e91a04f1d5c38d440c8eb508c..a1c7c40818ddc2ec9d99ced133b45da50fc8be87
@@@ -42,9 -42,6 +42,9 @@@ enum 
      AXIS_NAVHIDDEN,
      AXIS_NAVIGATION,
      AXIS_SCREENSIZE,
 +    AXIS_SMALLESTSCREENWIDTHDP,
 +    AXIS_SCREENWIDTHDP,
 +    AXIS_SCREENHEIGHTDP,
      AXIS_VERSION
  };
  
@@@ -55,7 -52,6 +55,7 @@@ enum 
      SDK_ECLAIR_0_1 = 6,
      SDK_MR1 = 7,
      SDK_FROYO = 8,
 +    SDK_HONEYCOMB_MR2 = 13,
  };
  
  /**
@@@ -73,9 -69,6 +73,9 @@@ public
      String8 mnc;
      String8 locale;
      String8 vendor;
 +    String8 smallestScreenWidthDp;
 +    String8 screenWidthDp;
 +    String8 screenHeightDp;
      String8 screenLayoutSize;
      String8 screenLayoutLong;
      String8 orientation;
      static bool getNavigationName(const char* name, ResTable_config* out = NULL);
      static bool getNavHiddenName(const char* name, ResTable_config* out = NULL);
      static bool getScreenSizeName(const char* name, ResTable_config* out = NULL);
 +    static bool getSmallestScreenWidthDpName(const char* name, ResTable_config* out = NULL);
 +    static bool getScreenWidthDpName(const char* name, ResTable_config* out = NULL);
 +    static bool getScreenHeightDpName(const char* name, ResTable_config* out = NULL);
      static bool getVersionName(const char* name, ResTable_config* out = NULL);
  
      int compare(const AaptGroupEntry& o) const;
@@@ -140,6 -130,7 +140,7 @@@ inline int strictly_order_type(const Aa
  }
  
  class AaptGroup;
+ class FilePathStore;
  
  /**
   * A single asset file we know about.
@@@ -269,7 -260,8 +270,8 @@@ public
      virtual ssize_t slurpFullTree(Bundle* bundle,
                                    const String8& srcDir,
                                    const AaptGroupEntry& kind,
-                                   const String8& resType);
+                                   const String8& resType,
+                                   sp<FilePathStore>& fullResPaths);
  
      /*
       * Perform some sanity checks on the names of files and directories here.
@@@ -484,6 -476,14 +486,14 @@@ public
      ResourceTypeSet();
  };
  
+ // Storage for lists of fully qualified paths for
+ // resources encountered during slurping.
+ class FilePathStore : public RefBase,
+                       public Vector<String8>
+ {
+ public:
+     FilePathStore();
+ };
  
  /**
   * Asset hierarchy being operated on.
@@@ -517,7 -517,8 +527,8 @@@ public
      virtual ssize_t slurpFullTree(Bundle* bundle,
                                    const String8& srcDir,
                                    const AaptGroupEntry& kind,
-                                   const String8& resType);
+                                   const String8& resType,
+                                   sp<FilePathStore>& fullResPaths);
  
      ssize_t slurpResourceTree(Bundle* bundle, const String8& srcDir);
      ssize_t slurpResourceZip(Bundle* bundle, const char* filename);
      inline void 
          setResources(KeyedVector<String8, sp<ResourceTypeSet> >* res) { delete mRes; mRes = res; }
  
+     inline sp<FilePathStore>& getFullResPaths() { return mFullResPaths; }
+     inline void
+         setFullResPaths(sp<FilePathStore>& res) { mFullResPaths = res; }
  private:
      String8 mPackage;
      SortedVector<AaptGroupEntry> mGroupEntries;
  
      sp<AaptAssets> mOverlay;
      KeyedVector<String8, sp<ResourceTypeSet> >* mRes;
+     sp<FilePathStore> mFullResPaths;
  };
  
  #endif // __AAPT_ASSETS_H
diff --combined Command.cpp
index a369e8042c2cd4903637c6b8359f0373bbe83e2f,89f45df1b853f817986e7c23c2d98a64412711b2..903c62cef1fe69d3102286d2886530a36f400968
@@@ -198,10 -198,8 +198,10 @@@ int doList(Bundle* bundle
          if (&res == NULL) {
              printf("\nNo resource table found.\n");
          } else {
 +#ifndef HAVE_ANDROID_OS
              printf("\nResource table:\n");
              res.print(false);
 +#endif
          }
  
          Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml",
@@@ -291,27 -289,6 +291,27 @@@ static int32_t getIntegerAttribute(cons
      return value.data;
  }
  
 +static int32_t getResolvedIntegerAttribute(const ResTable* resTable, const ResXMLTree& tree,
 +        uint32_t attrRes, String8* outError, int32_t defValue = -1)
 +{
 +    ssize_t idx = indexOfAttribute(tree, attrRes);
 +    if (idx < 0) {
 +        return defValue;
 +    }
 +    Res_value value;
 +    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
 +        if (value.dataType == Res_value::TYPE_REFERENCE) {
 +            resTable->resolveReference(&value, 0);
 +        }
 +        if (value.dataType < Res_value::TYPE_FIRST_INT
 +                || value.dataType > Res_value::TYPE_LAST_INT) {
 +            if (outError != NULL) *outError = "attribute is not an integer value";
 +            return defValue;
 +        }
 +    }
 +    return value.data;
 +}
 +
  static String8 getResolvedAttribute(const ResTable* resTable, const ResXMLTree& tree,
          uint32_t attrRes, String8* outError)
  {
  // These are attribute resource constants for the platform, as found
  // in android.R.attr
  enum {
 +    LABEL_ATTR = 0x01010001,
 +    ICON_ATTR = 0x01010002,
      NAME_ATTR = 0x01010003,
      VERSION_CODE_ATTR = 0x0101021b,
      VERSION_NAME_ATTR = 0x0101021c,
 -    LABEL_ATTR = 0x01010001,
 -    ICON_ATTR = 0x01010002,
 +    SCREEN_ORIENTATION_ATTR = 0x0101001e,
      MIN_SDK_VERSION_ATTR = 0x0101020c,
      MAX_SDK_VERSION_ATTR = 0x01010271,
      REQ_TOUCH_SCREEN_ATTR = 0x01010227,
      REQUIRED_ATTR = 0x0101028e,
      SCREEN_SIZE_ATTR = 0x010102ca,
      SCREEN_DENSITY_ATTR = 0x010102cb,
 +    REQUIRES_SMALLEST_WIDTH_DP_ATTR = 0x01010364,
 +    COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365,
 +    LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366,
  };
  
  const char *getComponentName(String8 &pkgName, String8 &componentName) {
@@@ -448,24 -421,6 +448,24 @@@ int doDump(Bundle* bundle
          return 1;
      }
  
 +    // Make a dummy config for retrieving resources...  we need to supply
 +    // non-default values for some configs so that we can retrieve resources
 +    // in the app that don't have a default.  The most important of these is
 +    // the API version because key resources like icons will have an implicit
 +    // version if they are using newer config types like density.
 +    ResTable_config config;
 +    config.language[0] = 'e';
 +    config.language[1] = 'n';
 +    config.country[0] = 'U';
 +    config.country[1] = 'S';
 +    config.orientation = ResTable_config::ORIENTATION_PORT;
 +    config.density = ResTable_config::DENSITY_MEDIUM;
 +    config.sdkVersion = 10000; // Very high.
 +    config.screenWidthDp = 320;
 +    config.screenHeightDp = 480;
 +    config.smallestScreenWidthDp = 320;
 +    assets.setConfiguration(config);
 +
      const ResTable& res = assets.getResources(false);
      if (&res == NULL) {
          fprintf(stderr, "ERROR: dump failed because no resource table was found\n");
      }
  
      if (strcmp("resources", option) == 0) {
 +#ifndef HAVE_ANDROID_OS
          res.print(bundle->getValues());
 -
 +#endif
      } else if (strcmp("xmltree", option) == 0) {
          if (bundle->getFileSpecCount() < 3) {
              fprintf(stderr, "ERROR: no dump xmltree resource file specified\n");
                  }
              }
          } else if (strcmp("badging", option) == 0) {
 +            Vector<String8> locales;
 +            res.getLocales(&locales);
 +
 +            Vector<ResTable_config> configs;
 +            res.getConfigurations(&configs);
 +            SortedVector<int> densities;
 +            const size_t NC = configs.size();
 +            for (size_t i=0; i<NC; i++) {
 +                int dens = configs[i].density;
 +                if (dens == 0) dens = 160;
 +                densities.add(dens);
 +            }
 +
              size_t len;
              ResXMLTree::event_code_t code;
              int depth = 0;
              bool specTouchscreenFeature = false; // touchscreen-related
              bool specMultitouchFeature = false;
              bool reqDistinctMultitouchFeature = false;
 +            bool specScreenPortraitFeature = false;
 +            bool specScreenLandscapeFeature = false;
 +            bool reqScreenPortraitFeature = false;
 +            bool reqScreenLandscapeFeature = false;
              // 2.2 also added some other features that apps can request, but that
              // have no corresponding permission, so we cannot implement any
              // back-compatibility heuristic for them. The below are thus unnecessary
              int largeScreen = 1;
              int xlargeScreen = 1;
              int anyDensity = 1;
 +            int requiresSmallestWidthDp = 0;
 +            int compatibleWidthLimitDp = 0;
 +            int largestWidthLimitDp = 0;
              String8 pkg;
              String8 activityName;
              String8 activityLabel;
                      } else if (depth < 3) {
                          if (withinActivity && isMainActivity && isLauncherActivity) {
                              const char *aName = getComponentName(pkg, activityName);
 +                            printf("launchable-activity:");
                              if (aName != NULL) {
 -                                printf("launchable activity name='%s'", aName);
 +                                printf(" name='%s' ", aName);
                              }
 -                            printf("label='%s' icon='%s'\n",
 +                            printf(" label='%s' icon='%s'\n",
                                      activityLabel.string(),
                                      activityIcon.string());
                          }
                      withinApplication = false;
                      if (tag == "application") {
                          withinApplication = true;
 -                        String8 label = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
 -                         if (error != "") {
 -                             fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n", error.string());
 -                             goto bail;
 +
 +                        String8 label;
 +                        const size_t NL = locales.size();
 +                        for (size_t i=0; i<NL; i++) {
 +                            const char* localeStr =  locales[i].string();
 +                            assets.setLocale(localeStr != NULL ? localeStr : "");
 +                            String8 llabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
 +                            if (llabel != "") {
 +                                if (localeStr == NULL || strlen(localeStr) == 0) {
 +                                    label = llabel;
 +                                    printf("application-label:'%s'\n", llabel.string());
 +                                } else {
 +                                    if (label == "") {
 +                                        label = llabel;
 +                                    }
 +                                    printf("application-label-%s:'%s'\n", localeStr,
 +                                            llabel.string());
 +                                }
 +                            }
                          }
 -                        printf("application: label='%s' ", label.string());
 +
 +                        ResTable_config tmpConfig = config;
 +                        const size_t ND = densities.size();
 +                        for (size_t i=0; i<ND; i++) {
 +                            tmpConfig.density = densities[i];
 +                            assets.setConfiguration(tmpConfig);
 +                            String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
 +                            if (icon != "") {
 +                                printf("application-icon-%d:'%s'\n", densities[i], icon.string());
 +                            }
 +                        }
 +                        assets.setConfiguration(config);
 +
                          String8 icon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
                          if (error != "") {
                              fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string());
                              goto bail;
                          }
 -                        printf("icon='%s'\n", icon.string());
                          int32_t testOnly = getIntegerAttribute(tree, TEST_ONLY_ATTR, &error, 0);
                          if (error != "") {
                              fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", error.string());
                              goto bail;
                          }
 +                        printf("application: label='%s' ", label.string());
 +                        printf("icon='%s'\n", icon.string());
                          if (testOnly != 0) {
                              printf("testOnly='%d'\n", testOnly);
                          }
                                  XLARGE_SCREEN_ATTR, NULL, 1);
                          anyDensity = getIntegerAttribute(tree,
                                  ANY_DENSITY_ATTR, NULL, 1);
 +                        requiresSmallestWidthDp = getIntegerAttribute(tree,
 +                                REQUIRES_SMALLEST_WIDTH_DP_ATTR, NULL, 0);
 +                        compatibleWidthLimitDp = getIntegerAttribute(tree,
 +                                COMPATIBLE_WIDTH_LIMIT_DP_ATTR, NULL, 0);
 +                        largestWidthLimitDp = getIntegerAttribute(tree,
 +                                LARGEST_WIDTH_LIMIT_DP_ATTR, NULL, 0);
                      } else if (tag == "uses-feature") {
                          String8 name = getAttribute(tree, NAME_ATTR, &error);
  
                                  // these have no corresponding permission to check for,
                                  // but should imply the foundational telephony permission
                                  reqTelephonySubFeature = true;
 +                            } else if (name == "android.hardware.screen.portrait") {
 +                                specScreenPortraitFeature = true;
 +                            } else if (name == "android.hardware.screen.landscape") {
 +                                specScreenLandscapeFeature = true;
                              }
                              printf("uses-feature%s:'%s'\n",
                                      req ? "" : "-not-required", name.string());
                              fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string());
                              goto bail;
                          }
 +
 +                        int32_t orien = getResolvedIntegerAttribute(&res, tree,
 +                                SCREEN_ORIENTATION_ATTR, &error);
 +                        if (error == "") {
 +                            if (orien == 0 || orien == 6 || orien == 8) {
 +                                // Requests landscape, sensorLandscape, or reverseLandscape.
 +                                reqScreenLandscapeFeature = true;
 +                            } else if (orien == 1 || orien == 7 || orien == 9) {
 +                                // Requests portrait, sensorPortrait, or reversePortrait.
 +                                reqScreenPortraitFeature = true;
 +                            }
 +                        }
                      } else if (tag == "uses-library") {
                          String8 libraryName = getAttribute(tree, NAME_ATTR, &error);
                          if (error != "") {
                  printf("uses-feature:'android.hardware.touchscreen.multitouch'\n");
              }
  
 +            // Landscape/portrait-related compatibility logic
 +            if (!specScreenLandscapeFeature && !specScreenPortraitFeature) {
 +                // If the app has specified any activities in its manifest
 +                // that request a specific orientation, then assume that
 +                // orientation is required.
 +                if (reqScreenLandscapeFeature) {
 +                    printf("uses-feature:'android.hardware.screen.landscape'\n");
 +                }
 +                if (reqScreenPortraitFeature) {
 +                    printf("uses-feature:'android.hardware.screen.portrait'\n");
 +                }
 +            }
 +
              if (hasMainActivity) {
                  printf("main\n");
              }
                  printf("other-services\n");
              }
  
 +            // For modern apps, if screen size buckets haven't been specified
 +            // but the new width ranges have, then infer the buckets from them.
 +            if (smallScreen > 0 && normalScreen > 0 && largeScreen > 0 && xlargeScreen > 0
 +                    && requiresSmallestWidthDp > 0) {
 +                int compatWidth = compatibleWidthLimitDp;
 +                if (compatWidth <= 0) compatWidth = requiresSmallestWidthDp;
 +                if (requiresSmallestWidthDp <= 240 && compatWidth >= 240) {
 +                    smallScreen = -1;
 +                } else {
 +                    smallScreen = 0;
 +                }
 +                if (requiresSmallestWidthDp <= 320 && compatWidth >= 320) {
 +                    normalScreen = -1;
 +                } else {
 +                    normalScreen = 0;
 +                }
 +                if (requiresSmallestWidthDp <= 480 && compatWidth >= 480) {
 +                    largeScreen = -1;
 +                } else {
 +                    largeScreen = 0;
 +                }
 +                if (requiresSmallestWidthDp <= 720 && compatWidth >= 720) {
 +                    xlargeScreen = -1;
 +                } else {
 +                    xlargeScreen = 0;
 +                }
 +            }
 +
              // Determine default values for any unspecified screen sizes,
              // based on the target SDK of the package.  As of 4 (donut)
              // the screen size support was introduced, so all default to
                  xlargeScreen = targetSdk >= 9 ? -1 : 0;
              }
              if (anyDensity > 0) {
 -                anyDensity = targetSdk >= 4 ? -1 : 0;
 +                anyDensity = (targetSdk >= 4 || requiresSmallestWidthDp > 0
 +                        || compatibleWidthLimitDp > 0) ? -1 : 0;
              }
              printf("supports-screens:");
              if (smallScreen != 0) printf(" 'small'");
              if (largeScreen != 0) printf(" 'large'");
              if (xlargeScreen != 0) printf(" 'xlarge'");
              printf("\n");
 -
              printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false");
 +            if (requiresSmallestWidthDp > 0) {
 +                printf("requires-smallest-width:'%d'\n", requiresSmallestWidthDp);
 +            }
 +            if (compatibleWidthLimitDp > 0) {
 +                printf("compatible-width-limit:'%d'\n", compatibleWidthLimitDp);
 +            }
 +            if (largestWidthLimitDp > 0) {
 +                printf("largest-width-limit:'%d'\n", largestWidthLimitDp);
 +            }
  
              printf("locales:");
 -            Vector<String8> locales;
 -            res.getLocales(&locales);
              const size_t NL = locales.size();
              for (size_t i=0; i<NL; i++) {
                  const char* localeStr =  locales[i].string();
              }
              printf("\n");
  
 -            Vector<ResTable_config> configs;
 -            res.getConfigurations(&configs);
 -            SortedVector<int> densities;
 -            const size_t NC = configs.size();
 -            for (size_t i=0; i<NC; i++) {
 -                int dens = configs[i].density;
 -                if (dens == 0) dens = 160;
 -                densities.add(dens);
 -            }
 -
              printf("densities:");
              const size_t ND = densities.size();
              for (size_t i=0; i<ND; i++) {
@@@ -1508,6 -1353,8 +1508,8 @@@ int doPackage(Bundle* bundle
      status_t err;
      sp<AaptAssets> assets;
      int N;
+     FILE* fp;
+     String8 dependencyFile;
  
      // -c zz_ZZ means do pseudolocalization
      ResourceFilter filter;
  
      // Load the assets.
      assets = new AaptAssets();
+     // Set up the resource gathering in assets if we're trying to make R.java
+     if (bundle->getGenDependencies()) {
+         sp<FilePathStore> pathStore = new FilePathStore;
+         assets->setFullResPaths(pathStore);
+     }
      err = assets->slurpFromArgs(bundle);
      if (err < 0) {
          goto bail;
          assets->print();
      }
  
-     // If they asked for any files that need to be compiled, do so.
+     // If they asked for any fileAs that need to be compiled, do so.
      if (bundle->getResourceSourceDirs().size() || bundle->getAndroidManifestFile()) {
          err = buildResources(bundle, assets);
          if (err != 0) {
          goto bail;
      }
  
+     if (bundle->getGenDependencies()) {
+         dependencyFile = String8(bundle->getRClassDir());
+         // Make sure we have a clean dependency file to start with
+         dependencyFile.appendPath("R.d");
+         fp = fopen(dependencyFile, "w");
+         fclose(fp);
+     }
      // Write out R.java constants
      if (assets->getPackage() == assets->getSymbolsPrivatePackage()) {
          if (bundle->getCustomPackage() == NULL) {
              err = writeResourceSymbols(bundle, assets, assets->getPackage(), true);
              // Copy R.java for libraries
              if (bundle->getExtraPackages() != NULL) {
-                 // Split on semicolon
+                 // Split on colon
                  String8 libs(bundle->getExtraPackages());
-                 char* packageString = strtok(libs.lockBuffer(libs.length()), ";");
+                 char* packageString = strtok(libs.lockBuffer(libs.length()), ":");
                  while (packageString != NULL) {
                      err = writeResourceSymbols(bundle, assets, String8(packageString), true);
-                     packageString = strtok(NULL, ";");
+                     packageString = strtok(NULL, ":");
                  }
                  libs.unlockBuffer();
              }
          }
      }
  
+     if (bundle->getGenDependencies()) {
+         // Now that writeResourceSymbols has taken care of writing the
+         // dependency targets to the dependencyFile, we'll write the
+         // pre-requisites.
+         fp = fopen(dependencyFile, "a+");
+         fprintf(fp, " : ");
+         err = writeDependencyPreReqs(bundle, assets, fp);
+         // Also manually add the AndroidManifeset since it's a non-asset
+         fprintf(fp, "%s \\\n", bundle->getAndroidManifestFile());
+         fclose(fp);
+     }
      // Write out the ProGuard file
      err = writeProguardFile(bundle, assets);
      if (err < 0) {
diff --combined Resource.cpp
index 730bd71160f8ce0b9b99fdc1a2c8a2ddda3cb2d0,a603314709ab9c1c1a31da4a052e5f3e77d8da4b..ae4bdc80c31459cc5985362e6d9f81cf28092fef
@@@ -51,6 -51,12 +51,12 @@@ ResourceTypeSet::ResourceTypeSet(
  {
  }
  
+ FilePathStore::FilePathStore()
+     :RefBase(),
+      Vector<String8>()
+ {
+ }
  class ResourceDirIterator
  {
  public:
@@@ -148,10 -154,9 +154,10 @@@ private
  
  bool isValidResourceType(const String8& type)
  {
 -    return type == "anim" || type == "drawable" || type == "layout"
 +    return type == "anim" || type == "animator" || type == "interpolator"
 +        || type == "drawable" || type == "layout"
          || type == "values" || type == "xml" || type == "raw"
 -        || type == "color" || type == "menu";
 +        || type == "color" || type == "menu" || type == "mipmap";
  }
  
  static sp<AaptFile> getResourceFile(const sp<AaptAssets>& assets, bool makeIfNecessary=true)
@@@ -285,9 -290,9 +291,9 @@@ static status_t makeFileResources(Bundl
  }
  
  static status_t preProcessImages(Bundle* bundle, const sp<AaptAssets>& assets,
 -                          const sp<ResourceTypeSet>& set)
 +                          const sp<ResourceTypeSet>& set, const char* type)
  {
 -    ResourceDirIterator it(set, String8("drawable"));
 +    ResourceDirIterator it(set, String8(type));
      Vector<sp<AaptFile> > newNameFiles;
      Vector<String8> newNamePaths;
      bool hasErrors = false;
@@@ -543,11 -548,11 +549,11 @@@ static bool applyFileOverlay(Bundle *bu
                          DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > baseFiles =
                                  baseGroup->getFiles();
                          for (size_t i=0; i < baseFiles.size(); i++) {
 -                            printf("baseFile %ld has flavor %s\n", i,
 +                            printf("baseFile %zd has flavor %s\n", i,
                                      baseFiles.keyAt(i).toString().string());
                          }
                          for (size_t i=0; i < overlayFiles.size(); i++) {
 -                            printf("overlayFile %ld has flavor %s\n", i,
 +                            printf("overlayFile %zd has flavor %s\n", i,
                                      overlayFiles.keyAt(i).toString().string());
                          }
                      }
                                  keyAt(overlayGroupIndex));
                          if(baseFileIndex < UNKNOWN_ERROR) {
                              if (bundle->getVerbose()) {
 -                                printf("found a match (%ld) for overlay file %s, for flavor %s\n",
 +                                printf("found a match (%zd) for overlay file %s, for flavor %s\n",
                                          baseFileIndex,
                                          overlayGroup->getLeaf().string(),
                                          overlayFiles.keyAt(overlayGroupIndex).toString().string());
@@@ -799,24 -804,18 +805,24 @@@ status_t buildResources(Bundle* bundle
      sp<ResourceTypeSet> drawables;
      sp<ResourceTypeSet> layouts;
      sp<ResourceTypeSet> anims;
 +    sp<ResourceTypeSet> animators;
 +    sp<ResourceTypeSet> interpolators;
      sp<ResourceTypeSet> xmls;
      sp<ResourceTypeSet> raws;
      sp<ResourceTypeSet> colors;
      sp<ResourceTypeSet> menus;
 +    sp<ResourceTypeSet> mipmaps;
  
      ASSIGN_IT(drawable);
      ASSIGN_IT(layout);
      ASSIGN_IT(anim);
 +    ASSIGN_IT(animator);
 +    ASSIGN_IT(interpolator);
      ASSIGN_IT(xml);
      ASSIGN_IT(raw);
      ASSIGN_IT(color);
      ASSIGN_IT(menu);
 +    ASSIGN_IT(mipmap);
  
      assets->setResources(resources);
      // now go through any resource overlays and collect their files
      if (!applyFileOverlay(bundle, assets, &drawables, "drawable") ||
              !applyFileOverlay(bundle, assets, &layouts, "layout") ||
              !applyFileOverlay(bundle, assets, &anims, "anim") ||
 +            !applyFileOverlay(bundle, assets, &animators, "animator") ||
 +            !applyFileOverlay(bundle, assets, &interpolators, "interpolator") ||
              !applyFileOverlay(bundle, assets, &xmls, "xml") ||
              !applyFileOverlay(bundle, assets, &raws, "raw") ||
              !applyFileOverlay(bundle, assets, &colors, "color") ||
 -            !applyFileOverlay(bundle, assets, &menus, "menu")) {
 +            !applyFileOverlay(bundle, assets, &menus, "menu") ||
 +            !applyFileOverlay(bundle, assets, &mipmaps, "mipmap")) {
          return UNKNOWN_ERROR;
      }
  
  
      if (drawables != NULL) {
          if (bundle->getOutputAPKFile() != NULL) {
 -            err = preProcessImages(bundle, assets, drawables);
 +            err = preProcessImages(bundle, assets, drawables, "drawable");
          }
          if (err == NO_ERROR) {
              err = makeFileResources(bundle, assets, &table, drawables, "drawable");
          }
      }
  
 +    if (mipmaps != NULL) {
 +        if (bundle->getOutputAPKFile() != NULL) {
 +            err = preProcessImages(bundle, assets, mipmaps, "mipmap");
 +        }
 +        if (err == NO_ERROR) {
 +            err = makeFileResources(bundle, assets, &table, mipmaps, "mipmap");
 +            if (err != NO_ERROR) {
 +                hasErrors = true;
 +            }
 +        } else {
 +            hasErrors = true;
 +        }
 +    }
 +
      if (layouts != NULL) {
          err = makeFileResources(bundle, assets, &table, layouts, "layout");
          if (err != NO_ERROR) {
          }
      }
  
 +    if (animators != NULL) {
 +        err = makeFileResources(bundle, assets, &table, animators, "animator");
 +        if (err != NO_ERROR) {
 +            hasErrors = true;
 +        }
 +    }
 +
 +    if (interpolators != NULL) {
 +        err = makeFileResources(bundle, assets, &table, interpolators, "interpolator");
 +        if (err != NO_ERROR) {
 +            hasErrors = true;
 +        }
 +    }
 +
      if (xmls != NULL) {
          err = makeFileResources(bundle, assets, &table, xmls, "xml");
          if (err != NO_ERROR) {
          err = NO_ERROR;
      }
  
 +    if (animators != NULL) {
 +        ResourceDirIterator it(animators, String8("animator"));
 +        while ((err=it.next()) == NO_ERROR) {
 +            err = compileXmlFile(assets, it.getFile(), &table, xmlFlags);
 +            if (err != NO_ERROR) {
 +                hasErrors = true;
 +            }
 +        }
 +
 +        if (err < NO_ERROR) {
 +            hasErrors = true;
 +        }
 +        err = NO_ERROR;
 +    }
 +
 +    if (interpolators != NULL) {
 +        ResourceDirIterator it(interpolators, String8("interpolator"));
 +        while ((err=it.next()) == NO_ERROR) {
 +            err = compileXmlFile(assets, it.getFile(), &table, xmlFlags);
 +            if (err != NO_ERROR) {
 +                hasErrors = true;
 +            }
 +        }
 +
 +        if (err < NO_ERROR) {
 +            hasErrors = true;
 +        }
 +        err = NO_ERROR;
 +    }
 +
      if (xmls != NULL) {
          ResourceDirIterator it(xmls, String8("xml"));
          while ((err=it.next()) == NO_ERROR) {
@@@ -1917,6 -1855,16 +1923,16 @@@ status_t writeResourceSymbols(Bundle* b
              return err;
          }
          fclose(fp);
+         if (bundle->getGenDependencies()) {
+             // Add this R.java to the dependency file
+             String8 dependencyFile(bundle->getRClassDir());
+             dependencyFile.appendPath("R.d");
+             fp = fopen(dependencyFile.string(), "a");
+             fprintf(fp,"%s \\\n", dest.string());
+             fclose(fp);
+         }
      }
  
      return NO_ERROR;
@@@ -2156,13 -2104,12 +2172,13 @@@ writeProguardForLayouts(ProguardKeepSet
      // tag:attribute pairs that should be checked in layout files.
      KeyedVector<String8, NamespaceAttributePair> kLayoutTagAttrPairs;
      addTagAttrPair(&kLayoutTagAttrPairs, "view", NULL, "class");
 +    addTagAttrPair(&kLayoutTagAttrPairs, "fragment", NULL, "class");
      addTagAttrPair(&kLayoutTagAttrPairs, "fragment", RESOURCES_ANDROID_NAMESPACE, "name");
  
      // tag:attribute pairs that should be checked in xml files.
      KeyedVector<String8, NamespaceAttributePair> kXmlTagAttrPairs;
      addTagAttrPair(&kXmlTagAttrPairs, "PreferenceScreen", RESOURCES_ANDROID_NAMESPACE, "fragment");
 -    addTagAttrPair(&kXmlTagAttrPairs, "Header", RESOURCES_ANDROID_NAMESPACE, "fragment");
 +    addTagAttrPair(&kXmlTagAttrPairs, "header", RESOURCES_ANDROID_NAMESPACE, "fragment");
  
      const Vector<sp<AaptDir> >& dirs = assets->resDirs();
      const size_t K = dirs.size();
@@@ -2239,3 -2186,16 +2255,16 @@@ writeProguardFile(Bundle* bundle, cons
  
      return err;
  }
 -}
+ status_t
+ writeDependencyPreReqs(Bundle* bundle, const sp<AaptAssets>& assets, FILE* fp)
+ {
+     status_t deps = -1;
+     sp<FilePathStore> files = assets->getFullResPaths();
+     for (size_t file_i = 0; file_i < files->size(); ++file_i) {
+         // Add the full file path to the dependency file
+         fprintf(fp, "%s \\\n", files->itemAt(file_i).string());
+         deps++;
+     }
+     return deps;
++}