aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/android/tools/r8/utils/AndroidAppOutputSink.java
blob: 914428404eab6ba4aae745ed0ac5b143655aa2ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// 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.utils;

import com.android.tools.r8.OutputSink;
import java.io.IOException;
import java.util.Set;
import java.util.TreeMap;

public class AndroidAppOutputSink extends ForwardingOutputSink {

  private final AndroidApp.Builder builder = AndroidApp.builder();
  private final TreeMap<String, DescriptorsWithContents> dexFilesWithPrimary = new TreeMap<>();
  private final TreeMap<Integer, DescriptorsWithContents> dexFilesWithId = new TreeMap<>();
  private boolean closed = false;

  public AndroidAppOutputSink(OutputSink forwardTo) {
    super(forwardTo);
  }

  public AndroidAppOutputSink() {
    super(new IgnoreContentsOutputSink());
  }

  @Override
  public synchronized void writeDexFile(byte[] contents, Set<String> classDescriptors, int fileId)
      throws IOException {
    // Sort the files by id so that their order is deterministic. Some tests depend on this.
    dexFilesWithId.put(fileId, new DescriptorsWithContents(classDescriptors, contents));
    super.writeDexFile(contents, classDescriptors, fileId);
  }

  @Override
  public synchronized void writeDexFile(byte[] contents, Set<String> classDescriptors,
      String primaryClassName)
      throws IOException {
    // Sort the files by their name for good measure.
    dexFilesWithPrimary
        .put(primaryClassName, new DescriptorsWithContents(classDescriptors, contents));
    super.writeDexFile(contents, classDescriptors, primaryClassName);
  }

  @Override
  public void writePrintUsedInformation(byte[] contents) throws IOException {
    builder.setDeadCode(contents);
    super.writePrintUsedInformation(contents);
  }

  @Override
  public void writeProguardMapFile(byte[] contents) throws IOException {
    builder.setProguardMapData(contents);
    super.writeProguardMapFile(contents);
  }

  @Override
  public void writeProguardSeedsFile(byte[] contents) throws IOException {
    builder.setProguardSeedsData(contents);
    super.writeProguardSeedsFile(contents);
  }

  @Override
  public void writeMainDexListFile(byte[] contents) throws IOException {
    builder.setMainDexListOutputData(contents);
    super.writeMainDexListFile(contents);
  }

  @Override
  public void close() throws IOException {
    assert !closed;
    assert dexFilesWithId.isEmpty() || dexFilesWithPrimary.isEmpty();
    dexFilesWithPrimary.forEach((v, d) -> builder.addDexProgramData(d.contents, d.descriptors, v));
    dexFilesWithId.forEach((v, d) -> builder.addDexProgramData(d.contents, d.descriptors));
    closed = true;
    super.close();
  }

  public AndroidApp build() {
    assert closed;
    return builder.build();
  }

  private static class DescriptorsWithContents {

    final Set<String> descriptors;
    final byte[] contents;

    private DescriptorsWithContents(Set<String> descriptors, byte[] contents) {
      this.descriptors = descriptors;
      this.contents = contents;
    }
  }
}