Skip to content

Commit ce61d63

Browse files
kevin1e100buchgr
authored andcommitted
don't use methods and classes removed in upstream dx
RELNOTES: update dexing tools to Android SDK 26.0.1 PiperOrigin-RevId: 164278101
1 parent 2266a6f commit ce61d63

8 files changed

Lines changed: 63 additions & 36 deletions

File tree

src/test/java/com/google/devtools/build/android/dexer/DexBuilderTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public void testBuildDexArchive() throws Exception {
4343
options.outputZip =
4444
FileSystems.getDefault().getPath(System.getenv("TEST_TMPDIR"), "dex_builder_test.zip");
4545
options.maxThreads = 1;
46-
DexBuilder.buildDexArchive(options, new Dexing.DexingOptions());
46+
DexBuilder.buildDexArchive(options, new Dexing(new Dexing.DexingOptions()));
4747
assertThat(options.outputZip.toFile().exists()).isTrue();
4848

4949
HashSet<String> files = new HashSet<>();

src/test/java/com/google/devtools/build/android/dexer/DexConversionEnqueuerTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import static org.mockito.Mockito.when;
2121

2222
import com.android.dex.Dex;
23+
import com.android.dx.command.dexer.DxContext;
2324
import com.android.dx.dex.DexOptions;
2425
import com.android.dx.dex.cf.CfOptions;
2526
import com.google.common.cache.Cache;
@@ -64,7 +65,7 @@ private void makeStuffer() {
6465
new DexConversionEnqueuer(
6566
zip,
6667
newDirectExecutorService(),
67-
new DexConverter(new Dexing(new DexOptions(), new CfOptions())),
68+
new DexConverter(new Dexing(new DxContext(), new DexOptions(), new CfOptions())),
6869
cache);
6970
}
7071

src/test/java/com/google/devtools/build/android/dexer/DexFileAggregatorTest.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import static org.mockito.Mockito.verify;
2121

2222
import com.android.dex.Dex;
23+
import com.android.dx.command.dexer.DxContext;
2324
import com.android.dx.dex.DexOptions;
2425
import com.android.dx.dex.cf.CfOptions;
2526
import com.android.dx.dex.file.DexFile;
@@ -59,23 +60,24 @@ public void setUp() throws IOException {
5960
@Test
6061
public void testClose_emptyWritesNothing() throws Exception {
6162
DexFileAggregator dexer =
62-
new DexFileAggregator(dest, MultidexStrategy.MINIMAL, DEX_LIMIT, WASTE);
63+
new DexFileAggregator(new DxContext(), dest, MultidexStrategy.MINIMAL, DEX_LIMIT, WASTE);
6364
dexer.close();
6465
verify(dest, times(0)).addFile(any(ZipEntry.class), any(Dex.class));
6566
}
6667

6768
@Test
6869
public void testAddAndClose_singleInputWritesThatInput() throws Exception {
69-
DexFileAggregator dexer = new DexFileAggregator(dest, MultidexStrategy.MINIMAL, 0, WASTE);
70+
DexFileAggregator dexer =
71+
new DexFileAggregator(new DxContext(), dest, MultidexStrategy.MINIMAL, 0, WASTE);
7072
dexer.add(dex);
7173
dexer.close();
7274
verify(dest).addFile(any(ZipEntry.class), eq(dex));
7375
}
7476

7577
@Test
7678
public void testMultidex_underLimitWritesOneShard() throws Exception {
77-
DexFileAggregator dexer =
78-
new DexFileAggregator(dest, MultidexStrategy.BEST_EFFORT, DEX_LIMIT, WASTE);
79+
DexFileAggregator dexer = new DexFileAggregator(
80+
new DxContext(), dest, MultidexStrategy.BEST_EFFORT, DEX_LIMIT, WASTE);
7981
Dex dex2 = DexFiles.toDex(convertClass(ByteStreams.class));
8082
dexer.add(dex);
8183
dexer.add(dex2);
@@ -87,8 +89,8 @@ public void testMultidex_underLimitWritesOneShard() throws Exception {
8789

8890
@Test
8991
public void testMultidex_overLimitWritesSecondShard() throws Exception {
90-
DexFileAggregator dexer = new DexFileAggregator(dest, MultidexStrategy.BEST_EFFORT,
91-
2 /* dex has more than 2 methods and fields */, WASTE);
92+
DexFileAggregator dexer = new DexFileAggregator(new DxContext(), dest,
93+
MultidexStrategy.BEST_EFFORT, 2 /* dex has more than 2 methods and fields */, WASTE);
9294
Dex dex2 = DexFiles.toDex(convertClass(ByteStreams.class));
9395
dexer.add(dex); // classFile is already over limit but we take anything in empty shard
9496
dexer.add(dex2); // this should start a new shard
@@ -101,7 +103,7 @@ public void testMultidex_overLimitWritesSecondShard() throws Exception {
101103

102104
@Test
103105
public void testMonodex_alwaysWritesSingleShard() throws Exception {
104-
DexFileAggregator dexer = new DexFileAggregator(dest, MultidexStrategy.OFF,
106+
DexFileAggregator dexer = new DexFileAggregator(new DxContext(), dest, MultidexStrategy.OFF,
105107
2 /* dex has more than 2 methods and fields */, WASTE);
106108
Dex dex2 = DexFiles.toDex(convertClass(ByteStreams.class));
107109
dexer.add(dex);
@@ -116,7 +118,7 @@ private static DexFile convertClass(Class<?> clazz) throws IOException {
116118
String path = clazz.getName().replace('.', '/') + ".class";
117119
try (InputStream in =
118120
Thread.currentThread().getContextClassLoader().getResourceAsStream(path)) {
119-
return new DexConverter(new Dexing(new DexOptions(), new CfOptions()))
121+
return new DexConverter(new Dexing(new DxContext(), new DexOptions(), new CfOptions()))
120122
.toDexFile(ByteStreams.toByteArray(in), path);
121123
}
122124
}

src/test/java/com/google/devtools/build/android/dexer/DexFileMergerTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import com.android.dex.ClassDef;
2121
import com.android.dex.Dex;
22+
import com.android.dx.command.dexer.DxContext;
2223
import com.google.common.base.Function;
2324
import com.google.common.base.Predicates;
2425
import com.google.common.collect.HashMultimap;
@@ -259,7 +260,7 @@ private Path buildDexArchive() throws Exception {
259260
options.outputZip =
260261
FileSystems.getDefault().getPath(System.getenv("TEST_TMPDIR"), "libtests.dex.zip");
261262
options.maxThreads = 1;
262-
DexBuilder.buildDexArchive(options, new Dexing.DexingOptions());
263+
DexBuilder.buildDexArchive(options, new Dexing(new DxContext(), new Dexing.DexingOptions()));
263264
return options.outputZip;
264265
}
265266

src/tools/android/java/com/google/devtools/build/android/dexer/DexBuilder.java

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import static java.nio.charset.StandardCharsets.ISO_8859_1;
1818
import static java.util.concurrent.Executors.newFixedThreadPool;
1919

20-
import com.android.dx.command.DxConsole;
20+
import com.android.dx.command.dexer.DxContext;
2121
import com.google.common.annotations.VisibleForTesting;
2222
import com.google.common.cache.Cache;
2323
import com.google.common.cache.CacheBuilder;
@@ -120,21 +120,20 @@ public static void main(String[] args) throws Exception {
120120
if (options.persistentWorker) {
121121
runPersistentWorker();
122122
} else {
123-
buildDexArchive(options, optionsParser.getOptions(DexingOptions.class));
123+
buildDexArchive(options, new Dexing(optionsParser.getOptions(DexingOptions.class)));
124124
}
125125
}
126126

127127
@VisibleForTesting
128-
static void buildDexArchive(Options options, DexingOptions dexingOptions)
129-
throws Exception {
128+
static void buildDexArchive(Options options, Dexing dexing) throws Exception {
130129
checkArgument(options.maxThreads > 0,
131130
"--max_threads must be strictly positive, was: %s", options.maxThreads);
132131
try (ZipFile in = new ZipFile(options.inputJar.toFile())) {
133132
// Heuristic: use at most 1 thread per 1000 files in the input Jar
134133
int threads = Math.min(options.maxThreads, in.size() / 1000 + 1);
135134
ExecutorService executor = newFixedThreadPool(threads);
136135
try (ZipOutputStream out = createZipOutputStream(options.outputZip)) {
137-
produceDexArchive(in, out, executor, threads <= 1, dexingOptions, null);
136+
produceDexArchive(in, out, executor, threads <= 1, dexing, null);
138137
} finally {
139138
executor.shutdown();
140139
}
@@ -169,11 +168,11 @@ public int weigh(DexingKey key, byte[] value) {
169168
// Redirect dx's output so we can return it in response
170169
ByteArrayOutputStream baos = new ByteArrayOutputStream();
171170
PrintStream ps = new PrintStream(baos, /*autoFlush*/ true);
172-
DxConsole.out = DxConsole.err = ps;
171+
DxContext context = new DxContext(ps, ps);
173172
// Make sure that we exit nonzero in case uncaught errors occur during processRequest.
174173
int exitCode = 1;
175174
try {
176-
processRequest(executor, dexCache, request.getArgumentsList());
175+
processRequest(executor, dexCache, context, request.getArgumentsList());
177176
exitCode = 0; // success!
178177
} catch (Exception e) {
179178
// Deliberate catch-all so we can capture a stack trace.
@@ -206,7 +205,10 @@ public int weigh(DexingKey key, byte[] value) {
206205
}
207206

208207
private static void processRequest(
209-
ExecutorService executor, Cache<DexingKey, byte[]> dexCache, List<String> args)
208+
ExecutorService executor,
209+
Cache<DexingKey, byte[]> dexCache,
210+
DxContext context,
211+
List<String> args)
210212
throws OptionsParsingException, IOException, InterruptedException, ExecutionException {
211213
OptionsParser optionsParser =
212214
OptionsParser.newOptionsParser(Options.class, DexingOptions.class);
@@ -220,7 +222,7 @@ private static void processRequest(
220222
out,
221223
executor,
222224
/*convertOnReaderThread*/ false,
223-
optionsParser.getOptions(DexingOptions.class),
225+
new Dexing(context, optionsParser.getOptions(DexingOptions.class)),
224226
dexCache);
225227
}
226228
// Use input's timestamp for output file so the output file is stable.
@@ -236,7 +238,7 @@ private static void produceDexArchive(
236238
ZipOutputStream out,
237239
ExecutorService executor,
238240
boolean convertOnReaderThread,
239-
DexingOptions dexingOptions,
241+
Dexing dexing,
240242
@Nullable Cache<DexingKey, byte[]> dexCache)
241243
throws InterruptedException, ExecutionException, IOException {
242244
// If we only have one thread in executor, we give a "direct" executor to the stuffer, which
@@ -245,7 +247,7 @@ private static void produceDexArchive(
245247
// the stuffer is still working its way through the input.
246248
DexConversionEnqueuer enqueuer = new DexConversionEnqueuer(in,
247249
convertOnReaderThread ? MoreExecutors.newDirectExecutorService() : executor,
248-
new DexConverter(new Dexing(dexingOptions)),
250+
new DexConverter(dexing),
249251
dexCache);
250252
Future<?> enqueuerTask = executor.submit(enqueuer);
251253
while (true) {

src/tools/android/java/com/google/devtools/build/android/dexer/DexFileAggregator.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
import com.android.dex.DexFormat;
2020
import com.android.dex.FieldId;
2121
import com.android.dex.MethodId;
22+
import com.android.dex.ProtoId;
23+
import com.android.dex.TypeList;
24+
import com.android.dx.command.dexer.DxContext;
2225
import com.android.dx.merge.CollisionPolicy;
2326
import com.android.dx.merge.DexMerger;
2427
import com.google.auto.value.AutoValue;
@@ -55,14 +58,17 @@ class DexFileAggregator implements Closeable {
5558
private final int maxNumberOfIdxPerDex;
5659
private final int wasteThresholdPerDex;
5760
private final MultidexStrategy multidex;
61+
private final DxContext context;
5862
private DexFileArchive dest;
5963
private int nextDexFileIndex = 0;
6064

6165
public DexFileAggregator(
66+
DxContext context,
6267
DexFileArchive dest,
6368
MultidexStrategy multidex,
6469
int maxNumberOfIdxPerDex,
6570
int wasteThresholdPerDex) {
71+
this.context = context;
6672
this.dest = dest;
6773
this.multidex = multidex;
6874
this.maxNumberOfIdxPerDex = maxNumberOfIdxPerDex;
@@ -145,7 +151,7 @@ private Dex merge(Dex... dexes) throws IOException {
145151
return dexes[0];
146152
default:
147153
try {
148-
DexMerger dexMerger = new DexMerger(dexes, CollisionPolicy.FAIL);
154+
DexMerger dexMerger = new DexMerger(dexes, CollisionPolicy.FAIL, context);
149155
dexMerger.setCompactWasteThreshold(wasteThresholdPerDex);
150156
return dexMerger.merge();
151157
} catch (BufferOverflowException e) {
@@ -195,12 +201,13 @@ static FieldDescriptor fromDex(Dex dex, int fieldIndex) {
195201
abstract static class MethodDescriptor {
196202
static MethodDescriptor fromDex(Dex dex, int methodIndex) {
197203
MethodId method = dex.methodIds().get(methodIndex);
204+
ProtoId proto = dex.protoIds().get(method.getProtoIndex());
198205
String name = dex.strings().get(method.getNameIndex());
199206
String declaringClass = typeName(dex, method.getDeclaringClassIndex());
200-
String returnType = typeName(dex, dex.returnTypeIndexFromMethodIndex(methodIndex));
201-
short[] parameterTypeIndices = dex.parameterTypeIndicesFromMethodIndex(methodIndex);
207+
String returnType = typeName(dex, proto.getReturnTypeIndex());
208+
TypeList parameterTypeIndices = dex.readTypeList(proto.getParametersOffset());
202209
ImmutableList.Builder<String> parameterTypes = ImmutableList.builder();
203-
for (short parameterTypeIndex : parameterTypeIndices) {
210+
for (short parameterTypeIndex : parameterTypeIndices.getTypes()) {
204211
parameterTypes.add(typeName(dex, parameterTypeIndex & 0xFFFF));
205212
}
206213
return new AutoValue_DexFileAggregator_MethodDescriptor(

src/tools/android/java/com/google/devtools/build/android/dexer/DexFileMerger.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
import com.android.dex.Dex;
2121
import com.android.dex.DexFormat;
22-
import com.android.dx.command.DxConsole;
22+
import com.android.dx.command.dexer.DxContext;
2323
import com.google.common.annotations.VisibleForTesting;
2424
import com.google.common.base.Predicate;
2525
import com.google.common.base.Predicates;
@@ -188,9 +188,10 @@ static void buildMergedDexFiles(Options options) throws IOException {
188188
DexFileAggregator out = createDexFileAggregator(options)) {
189189
checkForUnprocessedClasses(zip);
190190
if (!options.verbose) {
191-
// com.android.dx.merge.DexMerger prints tons of debug information to System.out that we
192-
// silence here unless it was explicitly requested.
193-
System.setOut(DxConsole.noop);
191+
// com.android.dx.merge.DexMerger prints status information to System.out that we silence
192+
// here unless it was explicitly requested. (It also prints debug info to DxContext.out,
193+
// which we populate accordingly below.)
194+
System.setOut(Dexing.nullout);
194195
}
195196

196197
if (classesInMainDex == null) {
@@ -262,6 +263,7 @@ private static void checkForUnprocessedClasses(ZipFile zip) {
262263

263264
private static DexFileAggregator createDexFileAggregator(Options options) throws IOException {
264265
return new DexFileAggregator(
266+
new DxContext(options.verbose ? System.out : ByteStreams.nullOutputStream(), System.err),
265267
new DexFileArchive(
266268
new ZipOutputStream(
267269
new BufferedOutputStream(Files.newOutputStream(options.outputArchive)))),

src/tools/android/java/com/google/devtools/build/android/dexer/Dexing.java

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
import com.android.dx.cf.direct.DirectClassFile;
1717
import com.android.dx.cf.direct.StdAttributeFactory;
18-
import com.android.dx.command.DxConsole;
18+
import com.android.dx.command.dexer.DxContext;
1919
import com.android.dx.dex.DexOptions;
2020
import com.android.dx.dex.cf.CfOptions;
2121
import com.android.dx.dex.cf.CfTranslator;
@@ -25,16 +25,20 @@
2525
import com.android.dx.util.ByteArray;
2626
import com.google.auto.value.AutoValue;
2727
import com.google.common.annotations.VisibleForTesting;
28+
import com.google.common.io.ByteStreams;
2829
import com.google.devtools.common.options.Option;
2930
import com.google.devtools.common.options.OptionDocumentationCategory;
3031
import com.google.devtools.common.options.OptionEffectTag;
3132
import com.google.devtools.common.options.OptionsBase;
33+
import java.io.PrintStream;
3234

3335
/**
3436
* Common helper class that encodes Java classes into {@link DexFile}s.
3537
*/
3638
class Dexing {
3739

40+
static final PrintStream nullout = new PrintStream(ByteStreams.nullOutputStream());
41+
3842
/**
3943
* Common command line options for use with {@link Dexing}.
4044
*/
@@ -73,11 +77,11 @@ public static class DexingOptions extends OptionsBase {
7377
)
7478
public boolean printWarnings;
7579

76-
public CfOptions toCfOptions() {
80+
public CfOptions toCfOptions(DxContext context) {
7781
CfOptions result = new CfOptions();
7882
result.localInfo = this.localInfo;
7983
result.optimize = this.optimize;
80-
result.warn = printWarnings ? DxConsole.err : DxConsole.noop;
84+
result.warn = printWarnings ? context.err : Dexing.nullout;
8185
// Use dx's defaults
8286
result.optimizeListFile = null;
8387
result.dontOptimizeListFile = null;
@@ -114,15 +118,21 @@ static DexingKey create(boolean localInfo, boolean optimize, byte[] classfileCon
114118
@SuppressWarnings("mutable") abstract byte[] classfileContent();
115119
}
116120

121+
private final DxContext context;
117122
private final DexOptions dexOptions;
118123
private final CfOptions cfOptions;
119124

120125
public Dexing(DexingOptions options) {
121-
this(options.toDexOptions(), options.toCfOptions());
126+
this(new DxContext(), options);
127+
}
128+
129+
public Dexing(DxContext context, DexingOptions options) {
130+
this(context, options.toDexOptions(), options.toCfOptions(context));
122131
}
123132

124133
@VisibleForTesting
125-
Dexing(DexOptions dexOptions, CfOptions cfOptions) {
134+
Dexing(DxContext context, DexOptions dexOptions, CfOptions cfOptions) {
135+
this.context = context;
126136
this.dexOptions = dexOptions;
127137
this.cfOptions = cfOptions;
128138
}
@@ -140,7 +150,9 @@ public DexFile newDexFile() {
140150
}
141151

142152
public ClassDefItem addToDexFile(DexFile dest, DirectClassFile classFile) {
143-
ClassDefItem result = CfTranslator.translate(classFile,
153+
ClassDefItem result = CfTranslator.translate(
154+
context,
155+
classFile,
144156
(byte[]) null /*ignored*/,
145157
cfOptions,
146158
dest.getDexOptions(),

0 commit comments

Comments
 (0)