Allow to disable forced keep of annotated

We force all classes annotated with runtime annotation to be kept
in the main dex list. This allow to workaround a Dalvik bug when
accessing the annotations. But this increase the pressure in the
main dex indexes. The new option is to allow to disable this
workaround for application facing the index limit in their main
dex and that don't access annotation at runtime or that have only
annotations not subject to the resolution bug.

Bug: 18928046
Change-Id: Ibcd7e579a7fef3451ec8aeb266ea67514d82cd50
diff --git a/dx/etc/mainDexClasses b/dx/etc/mainDexClasses
index 28c0f0c..178ab18 100755
--- a/dx/etc/mainDexClasses
+++ b/dx/etc/mainDexClasses
@@ -137,10 +137,19 @@
     jarpath="$libdir/$jarfile"
 fi
 
+disableKeepAnnotated=
+
+while true; do
 if expr "x$1" : 'x--output' >/dev/null; then
     exec 1>$2
     shift 2
+elif expr "x$1" : 'x--disable-annotation-resolution-workaround' >/dev/null; then
+    disableKeepAnnotated=$1
+    shift 1
+else
+    break
 fi
+done
 
 if [ $# -ne 1 ]; then
   echo "Usage : $0 [--output <output file>] <application path>" 1>&2
@@ -155,4 +164,4 @@
   -libraryjars "${shrinkedAndroidJar}" -dontoptimize -dontobfuscate -dontpreverify \
   -include "${baserules}" 1>/dev/null || exit 10
 
-java -cp "$jarpath" com.android.multidex.MainDexListBuilder "${tmpOut}" ${@} ||  exit 11
+java -cp "$jarpath" com.android.multidex.MainDexListBuilder ${disableKeepAnnotated} "${tmpOut}" ${@} ||  exit 11
diff --git a/dx/etc/mainDexClasses.bat b/dx/etc/mainDexClasses.bat
index f6a4b56..1923ee4 100755
--- a/dx/etc/mainDexClasses.bat
+++ b/dx/etc/mainDexClasses.bat
@@ -67,6 +67,7 @@
 set params=

 

 set output=

+set disableKeepAnnotated=

 

 :firstArg

 if [%1]==[] goto endArgs

@@ -78,6 +79,13 @@
         goto firstArg

 

 :notOut

+

+    if %1 NEQ --disable-annotation-resolution-workaround goto notDisable

+        set "disableKeepAnnotated=%1"

+        shift

+        goto firstArg

+

+:notDisable

     if defined params goto usage

     set params=%1

     shift

@@ -96,10 +104,10 @@
 call "%proguard%" -injars %params% -dontwarn -forceprocessing  -outjars "%tmpJar%" -libraryjars "%shrinkedAndroidJar%" -dontoptimize -dontobfuscate -dontpreverify -include "%baserules%" 1>nul

 

 if DEFINED output goto redirect

-call "%java_exe%" -Djava.ext.dirs="%frameworkdir%" com.android.multidex.MainDexListBuilder "%tmpJar%" "%params%"

+call "%java_exe%" -Djava.ext.dirs="%frameworkdir%" com.android.multidex.MainDexListBuilder "%disableKeepAnnotated%" "%tmpJar%" "%params%"

 goto afterClassReferenceListBuilder

 :redirect

-call "%java_exe%" -Djava.ext.dirs="%frameworkdir%" com.android.multidex.MainDexListBuilder "%tmpJar%" "%params%" 1>"%output%"

+call "%java_exe%" -Djava.ext.dirs="%frameworkdir%" com.android.multidex.MainDexListBuilder "%disableKeepAnnotated%" "%tmpJar%" "%params%" 1>"%output%"

 :afterClassReferenceListBuilder

 

 del %tmpJar%

diff --git a/dx/src/com/android/multidex/MainDexListBuilder.java b/dx/src/com/android/multidex/MainDexListBuilder.java
index c9e1a18..7fed119 100644
--- a/dx/src/com/android/multidex/MainDexListBuilder.java
+++ b/dx/src/com/android/multidex/MainDexListBuilder.java
@@ -53,18 +53,43 @@
             "Slightly longer version: This tool is used by mainDexClasses script to build" + EOL +
             "the main dex list." + EOL;
 
+    /**
+     * By default we force all classes annotated with runtime annotation to be kept in the
+     * main dex list. This option disable the workaround, limiting the index pressure in the main
+     * dex but exposing to the Dalvik resolution bug. The resolution bug occurs when accessing
+     * annotations of a class that is not in the main dex and one of the annotations as an enum
+     * parameter.
+     *
+     * @see <a href="https://code.google.com/p/android/issues/detail?id=78144">bug discussion</a>
+     *
+     */
+    private static final String DISABLE_ANNOTATION_RESOLUTION_WORKAROUND =
+            "--disable-annotation-resolution-workaround";
+
     private Set<String> filesToKeep = new HashSet<String>();
 
     public static void main(String[] args) {
 
-        if (args.length != 2) {
+        int argIndex = 0;
+        boolean keepAnnotated = true;
+        while (argIndex < args.length -2) {
+            if (args[argIndex].equals(DISABLE_ANNOTATION_RESOLUTION_WORKAROUND)) {
+                keepAnnotated = false;
+            } else {
+                System.err.println("Invalid option " + args[argIndex]);
+                printUsage();
+                System.exit(STATUS_ERROR);
+            }
+            argIndex++;
+        }
+        if (args.length - argIndex != 2) {
             printUsage();
             System.exit(STATUS_ERROR);
         }
 
         try {
-
-            MainDexListBuilder builder = new MainDexListBuilder(args[0], args[1]);
+            MainDexListBuilder builder = new MainDexListBuilder(keepAnnotated, args[argIndex],
+                    args[argIndex + 1]);
             Set<String> toKeep = builder.getMainDexList();
             printList(toKeep);
         } catch (IOException e) {
@@ -74,7 +99,8 @@
         }
     }
 
-    public MainDexListBuilder(String rootJar, String pathString) throws IOException {
+    public MainDexListBuilder(boolean keepAnnotated, String rootJar, String pathString)
+            throws IOException {
         ZipFile jarOfRoots = null;
         Path path = null;
         try {
@@ -91,7 +117,9 @@
             for (String className : mainListBuilder.getClassNames()) {
                 filesToKeep.add(className + CLASS_EXTENSION);
             }
-            keepAnnotated(path);
+            if (keepAnnotated) {
+                keepAnnotated(path);
+            }
         } finally {
             try {
                 jarOfRoots.close();