Add new aapt flag --error-on-missing-config-entry

It forces aapt to return an error if aapt fails to find an resource
entry for a configuration.

Bug: 11259444
Change-Id: Ie5674a29dff5d4455e7d7c94f6b25560fb1305b7
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index b67ca09..52d9266 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -55,14 +55,15 @@
           mCompressionMethod(0), mJunkPath(false), mOutputAPKFile(NULL),
           mManifestPackageNameOverride(NULL), mInstrumentationPackageNameOverride(NULL),
           mAutoAddOverlay(false), mGenDependencies(false),
-          mAssetSourceDir(NULL), 
+          mAssetSourceDir(NULL),
           mCrunchedOutputDir(NULL), mProguardFile(NULL),
           mAndroidManifestFile(NULL), mPublicOutputFile(NULL),
           mRClassDir(NULL), mResourceIntermediatesDir(NULL), mManifestMinSdkVersion(NULL),
           mMinSdkVersion(NULL), mTargetSdkVersion(NULL), mMaxSdkVersion(NULL),
           mVersionCode(NULL), mVersionName(NULL), mCustomPackage(NULL), mExtraPackages(NULL),
           mMaxResVersion(NULL), mDebugMode(false), mNonConstantId(false), mProduct(NULL),
-          mUseCrunchCache(false), mErrorOnFailedInsert(false), mOutputTextSymbols(NULL),
+          mUseCrunchCache(false), mErrorOnFailedInsert(false), mErrorOnMissingConfigEntry(false),
+          mOutputTextSymbols(NULL),
           mSingleCrunchInputFile(NULL), mSingleCrunchOutputFile(NULL),
           mArgc(0), mArgv(NULL)
         {}
@@ -117,6 +118,8 @@
     void setGenDependencies(bool val) { mGenDependencies = val; }
     bool getErrorOnFailedInsert() { return mErrorOnFailedInsert; }
     void setErrorOnFailedInsert(bool val) { mErrorOnFailedInsert = val; }
+    bool getErrorOnMissingConfigEntry() { return mErrorOnMissingConfigEntry; }
+    void setErrorOnMissingConfigEntry(bool val) { mErrorOnMissingConfigEntry = val; }
 
     bool getUTF16StringsOption() {
         return mWantUTF16 || !isMinSdkAtLeast(SDK_FROYO);
@@ -291,6 +294,7 @@
     const char* mProduct;
     bool        mUseCrunchCache;
     bool        mErrorOnFailedInsert;
+    bool        mErrorOnMissingConfigEntry;
     const char* mOutputTextSymbols;
     const char* mSingleCrunchInputFile;
     const char* mSingleCrunchOutputFile;
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 4a8aa9c..51a1248 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -190,6 +190,8 @@
         "       with --debug-mode, --min-sdk-version, --target-sdk-version --version-code\n"
         "       and --version-name.\n"
         "       Insertion typically fails if the manifest already defines the attribute.\n"
+        "   --error-on-missing-config-entry\n"
+        "       Forces aapt to return an error if it fails to find an entry for a configuration.\n"
         "   --output-text-symbols\n"
         "       Generates a text file containing the resource symbols of the R class in the\n"
         "       specified folder.\n"
@@ -587,6 +589,8 @@
                     bundle.setAutoAddOverlay(true);
                 } else if (strcmp(cp, "-error-on-failed-insert") == 0) {
                     bundle.setErrorOnFailedInsert(true);
+                } else if (strcmp(cp, "-error-on-missing-config-entry") == 0) {
+                    bundle.setErrorOnMissingConfigEntry(true);
                 } else if (strcmp(cp, "-output-text-symbols") == 0) {
                     argc--;
                     argv++;
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index f2e5254..5c3019d 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -2971,13 +2971,21 @@
                 tHeader->header.size = htodl(data->getSize()-typeStart);
             }
 
+            bool missing_entry = false;
+            const char* log_prefix = bundle->getErrorOnMissingConfigEntry() ?
+                    "error" : "warning";
             for (size_t i = 0; i < N; ++i) {
                 if (!validResources[i]) {
                     sp<ConfigList> c = t->getOrderedConfigs().itemAt(i);
-                    fprintf(stderr, "warning: no entries written for %s/%s\n",
+                    fprintf(stderr, "%s: no entries written for %s/%s\n", log_prefix,
                             String8(typeName).string(), String8(c->getName()).string());
+                    missing_entry = true;
                 }
             }
+            if (bundle->getErrorOnMissingConfigEntry() && missing_entry) {
+                fprintf(stderr, "Error: Missing entries, quit!\n");
+                return NOT_ENOUGH_DATA;
+            }
         }
 
         // Fill in the rest of the package information.