2 * Copyright (C) 2009 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package dalvik.runner;
20 import java.io.PrintStream;
21 import java.util.List;
22 import java.util.logging.Logger;
25 * Execute tests on a Dalvik VM using an Android device or emulator.
27 final class DeviceDalvikVm extends Vm {
28 private static final Logger logger = Logger.getLogger(DeviceDalvikVm.class.getName());
30 DeviceDalvikVm(Integer debugPort, long timeoutSeconds, File sdkJar, PrintStream tee,
31 File localTemp, List<String> additionalVmArgs,
32 boolean cleanBefore, boolean cleanAfter, File runnerDir) {
33 super(new EnvironmentDevice(cleanBefore, cleanAfter, debugPort, localTemp, runnerDir),
34 timeoutSeconds, sdkJar, tee, additionalVmArgs);
37 private EnvironmentDevice getEnvironmentDevice() {
38 return (EnvironmentDevice) environment;
41 @Override protected void postCompileTestRunner() {
42 // TODO: does this really need to be a special case?
43 postCompile("testrunner", environment.testRunnerClassesDir());
45 // dex everything on the classpath and push it to the device.
46 for (File classpathElement : testClasspath.getElements()) {
47 String name = basenameOfJar(classpathElement);
48 logger.fine("dex and push " + name);
49 // make the local dex (inside a jar)
50 // TODO: this is *really* expensive. we need a cache!
51 File outputFile = getEnvironmentDevice().testDir(name + ".jar");
52 new Dx().dex(outputFile, Classpath.of(classpathElement));
53 // push the local dex to the device
54 getEnvironmentDevice().adb.push(outputFile, deviceDexFile(name));
58 private String basenameOfJar(File jarFile) {
59 return jarFile.getName().replaceAll("\\.jar$", "");
62 @Override protected void postCompileTest(TestRun testRun) {
63 postCompile(testRun.getQualifiedName(), environment.testClassesDir(testRun));
66 private void postCompile(String name, File dir) {
67 logger.fine("dex and push " + name);
69 // make the local dex (inside a jar)
70 File localDex = new File(dir.getPath() + ".jar");
71 new Dx().dex(localDex, Classpath.of(dir));
73 // post the local dex to the device
74 File deviceDex = deviceDexFile(name);
75 getEnvironmentDevice().adb.push(localDex, deviceDex);
78 private File deviceDexFile(String name) {
79 return new File(getEnvironmentDevice().runnerDir, name + ".jar");
82 @Override protected VmCommandBuilder newVmCommandBuilder(
83 File workingDirectory) {
84 // ignore the working directory; it's device-local and we can't easily
85 // set the working directory for commands run via adb shell.
86 // TODO: we only *need* to set ANDROID_DATA on production devices.
87 // We set "user.home" to /sdcard because code might reasonably assume it can write to
89 return new VmCommandBuilder()
90 .vmCommand("adb", "shell", "ANDROID_DATA=/sdcard", "dalvikvm")
91 .vmArgs("-Duser.home=/sdcard")
92 .vmArgs("-Duser.name=root")
93 .vmArgs("-Duser.language=en")
94 .vmArgs("-Duser.region=US")
95 .vmArgs("-Djavax.net.ssl.trustStore=/system/etc/security/cacerts.bks")
96 .temp(getEnvironmentDevice().testTemp);
99 @Override protected Classpath getRuntimeSupportClasspath(TestRun testRun) {
100 Classpath classpath = new Classpath();
101 classpath.addAll(deviceDexFile(testRun.getQualifiedName()));
102 classpath.addAll(deviceDexFile("testrunner"));
103 for (File testClasspathElement : testClasspath.getElements()) {
104 classpath.addAll(deviceDexFile(basenameOfJar(testClasspathElement)));