Add an internal flag to ignore dex files in archives

Only accessible internally and only set bu ConpatDx.

Change-Id: I37df1eeb899f7c230b4512d14504d64e56641e93
diff --git a/src/main/java/com/android/tools/r8/BaseCommand.java b/src/main/java/com/android/tools/r8/BaseCommand.java
index 430624b..debe8a1 100644
--- a/src/main/java/com/android/tools/r8/BaseCommand.java
+++ b/src/main/java/com/android/tools/r8/BaseCommand.java
@@ -95,6 +95,9 @@
     private CompilationMode mode;
     private int minApiLevel = Constants.DEFAULT_ANDROID_API;
 
+    // Internal flag used by CompatDx to ignore dex files in archives.
+    protected boolean ignoreDexInArchive = false;
+
     protected Builder(CompilationMode mode) {
       this(AndroidApp.builder(), mode);
     }
@@ -108,6 +111,7 @@
       assert mode != null;
       this.app = builder;
       this.mode = mode;
+      app.setIgnoreDexInArchive(ignoreDexInArchive);
     }
 
     abstract B self();
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index 64a1a0e..cb8c170 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -36,7 +36,7 @@
 
     private boolean intermediate = false;
 
-    private Builder() {
+    protected Builder() {
       super(CompilationMode.DEBUG);
     }
 
diff --git a/src/main/java/com/android/tools/r8/compatdx/CompatDx.java b/src/main/java/com/android/tools/r8/compatdx/CompatDx.java
index 6750f4c..9bcf510 100644
--- a/src/main/java/com/android/tools/r8/compatdx/CompatDx.java
+++ b/src/main/java/com/android/tools/r8/compatdx/CompatDx.java
@@ -450,7 +450,7 @@
     ExecutorService executor = ThreadUtils.getExecutorService(numberOfThreads);
     D8Output result;
     try {
-      D8Command.Builder builder = D8Command.builder();
+      D8Command.Builder builder = new CompatDxCommandBuilder();
       builder
           .addProgramFiles(inputs)
           .setMode(mode)
diff --git a/src/main/java/com/android/tools/r8/compatdx/CompatDxCommandBuilder.java b/src/main/java/com/android/tools/r8/compatdx/CompatDxCommandBuilder.java
new file mode 100644
index 0000000..ba9daec
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/compatdx/CompatDxCommandBuilder.java
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.compatdx;
+
+import com.android.tools.r8.D8Command;
+
+public class CompatDxCommandBuilder extends D8Command.Builder {
+  CompatDxCommandBuilder() {
+    ignoreDexInArchive = true;
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApp.java b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
index 006dc1a..97a3679 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -423,6 +423,7 @@
     private List<Resource> mainDexListResources = new ArrayList<>();
     private List<String> mainDexListClasses = new ArrayList<>();
     private Resource mainDexListOutput;
+    private boolean ignoreDexInArchive = false;
 
     // See AndroidApp::builder().
     private Builder() {
@@ -671,6 +672,17 @@
     }
 
     /**
+     * Ignore dex resources in input archives.
+     *
+     * In some situations (e.g. AOSP framework build) the input archives include both class and
+     * dex resources. Setting this flag ignores the dex resources and reads the class resources
+     * only.
+     */
+    public void setIgnoreDexInArchive(boolean value) {
+      ignoreDexInArchive = value;
+    }
+
+    /**
      * Build final AndroidApp.
      */
     public AndroidApp build() {
@@ -697,7 +709,7 @@
       } else if (isClassFile(file)) {
         programResources.add(Resource.fromFile(Resource.Kind.CLASSFILE, file));
       } else if (isArchive(file)) {
-        programFileArchiveReaders.add(new ProgramFileArchiveReader(file));
+        programFileArchiveReaders.add(new ProgramFileArchiveReader(file, ignoreDexInArchive));
       } else {
         throw new CompilationError("Unsupported source file type for file: " + file);
       }
diff --git a/src/main/java/com/android/tools/r8/utils/ProgramFileArchiveReader.java b/src/main/java/com/android/tools/r8/utils/ProgramFileArchiveReader.java
index 814ffd1..8341921 100644
--- a/src/main/java/com/android/tools/r8/utils/ProgramFileArchiveReader.java
+++ b/src/main/java/com/android/tools/r8/utils/ProgramFileArchiveReader.java
@@ -25,11 +25,13 @@
 class ProgramFileArchiveReader {
 
   private final Path archive;
+  private boolean ignoreDexInArchive;
   private List<Resource> dexResources = null;
   private List<Resource> classResources = null;
 
-  ProgramFileArchiveReader(Path archive) {
+  ProgramFileArchiveReader(Path archive, boolean ignoreDexInArchive) {
     this.archive = archive;
+    this.ignoreDexInArchive = ignoreDexInArchive;
   }
 
   private void readArchive() throws IOException {
@@ -41,9 +43,11 @@
       while ((entry = stream.getNextEntry()) != null) {
         Path name = Paths.get(entry.getName());
         if (isDexFile(name)) {
-          Resource resource =
-              new OneShotByteResource(Resource.Kind.DEX, ByteStreams.toByteArray(stream), null);
-          dexResources.add(resource);
+          if (!ignoreDexInArchive) {
+            Resource resource =
+                new OneShotByteResource(Resource.Kind.DEX, ByteStreams.toByteArray(stream), null);
+            dexResources.add(resource);
+          }
         } else if (isClassFile(name)) {
           String descriptor = PreloadedClassFileProvider.guessTypeDescriptor(name);
           Resource resource = new OneShotByteResource(Resource.Kind.CLASSFILE,