+status_t AaptAssets::filter(Bundle* bundle)
+{
+ ResourceFilter 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;
+ }
+
+ if (reqFilter.isEmpty() && prefFilter.isEmpty()) {
+ return NO_ERROR;
+ }
+
+ if (bundle->getVerbose()) {
+ if (!reqFilter.isEmpty()) {
+ printf("Applying required filter: %s\n",
+ bundle->getConfigurations());
+ }
+ if (!prefFilter.isEmpty()) {
+ printf("Applying preferred filter: %s\n",
+ bundle->getPreferredConfigurations());
+ }
+ }
+
+ const Vector<sp<AaptDir> >& resdirs = mResDirs;
+ const size_t ND = resdirs.size();
+ for (size_t i=0; i<ND; i++) {
+ const sp<AaptDir>& dir = resdirs.itemAt(i);
+ if (dir->getLeaf() == kValuesDir) {
+ // The "value" dir is special since a single file defines
+ // multiple resources, so we can not do filtering on the
+ // files themselves.
+ continue;
+ }
+ if (dir->getLeaf() == kMipmapDir) {
+ // We also skip the "mipmap" directory, since the point of this
+ // is to include all densities without stripping. If you put
+ // other configurations in here as well they won't be stripped
+ // either... So don't do that. Seriously. What is wrong with you?
+ continue;
+ }
+
+ const size_t NG = dir->getFiles().size();
+ for (size_t j=0; j<NG; j++) {
+ sp<AaptGroup> grp = dir->getFiles().valueAt(j);
+
+ // First remove any configurations we know we don't need.
+ 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 (!reqFilter.match(config)) {
+ if (bundle->getVerbose()) {
+ printf("Pruning unneeded resource: %s\n",
+ file->getPrintableSource().string());
+ }
+ grp->removeFile(k);
+ k--;
+ }
+ }
+
+ // Quick check: no preferred filters, nothing more to do.
+ if (prefFilter.isEmpty()) {
+ continue;
+ }
+
+ // 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.
+ for (size_t m=0; m<grp->getFiles().size(); m++) {
+ if (m == k) continue;
+ sp<AaptFile> mfile = grp->getFiles().valueAt(m);
+ const ResTable_config& mconfig(mfile->getGroupEntry().toParams());
+ if (AaptGroupEntry::configSameExcept(config, mconfig, axis)) {
+ if (prefFilter.match(axis, mconfig)) {
+ if (bundle->getVerbose()) {
+ printf("Pruning unneeded resource: %s\n",
+ file->getPrintableSource().string());
+ }
+ grp->removeFile(k);
+ k--;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return NO_ERROR;
+}
+