1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 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 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 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. 15 */ 16 17 package vogar.android; 18 19 import com.google.common.collect.Iterables; 20 21 import java.io.File; 22 import java.util.ArrayList; 23 import java.util.Collections; 24 import java.util.HashSet; 25 import java.util.List; 26 import java.util.Set; 27 28 import vogar.Action; 29 import vogar.Classpath; 30 import vogar.Mode; 31 import vogar.ModeId; 32 import vogar.Run; 33 import vogar.Toolchain; 34 import vogar.Variant; 35 import vogar.commands.VmCommandBuilder; 36 import vogar.tasks.MkdirTask; 37 import vogar.tasks.RunActionTask; 38 import vogar.tasks.Task; 39 40 /** 41 * Executes actions on a Dalvik or ART runtime on a Linux desktop. 42 */ 43 public final class HostRuntime implements Mode { 44 private final Run run; 45 private final ModeId modeId; 46 private final Variant variant; 47 HostRuntime(Run run, ModeId modeId, Variant variant)48 public HostRuntime(Run run, ModeId modeId, Variant variant) { 49 if (!modeId.isHost() || !modeId.supportsVariant(variant)) { 50 throw new IllegalArgumentException("Unsupported mode:" + modeId + 51 " or variant: " + variant); 52 } 53 this.run = run; 54 this.modeId = modeId; 55 this.variant = variant; 56 } 57 executeActionTask(Action action, boolean useLargeTimeout)58 @Override public Task executeActionTask(Action action, boolean useLargeTimeout) { 59 return new RunActionTask(run, action, useLargeTimeout); 60 } 61 dalvikCache()62 private File dalvikCache() { 63 return run.localFile("android-data", run.dalvikCache); 64 } 65 installTasks()66 @Override public Set<Task> installTasks() { 67 Set<Task> result = new HashSet<Task>(); 68 for (File classpathElement : run.classpath.getElements()) { 69 // Libraries need to be dex'ed and put in the temporary directory. 70 String name = run.basenameOfJar(classpathElement); 71 File localDex = run.localDexFile(name); 72 File localTempDir = run.localDir(name); 73 result.add(createCreateDexJarTask(run.classpath, classpathElement, name, 74 null /* action */, localDex, localTempDir)); 75 } 76 result.add(new MkdirTask(run.mkdir, dalvikCache())); 77 return result; 78 } 79 cleanupTasks(Action action)80 @Override public Set<Task> cleanupTasks(Action action) { 81 return Collections.emptySet(); 82 } 83 installActionTasks(Action action, File jar)84 @Override public Set<Task> installActionTasks(Action action, File jar) { 85 File localDexFile = run.localDexFile(action.getName()); 86 File localTempDir = run.localDir(action.getName()); 87 Task createDexJarTask = createCreateDexJarTask(Classpath.of(jar), jar, action.getName(), 88 action, localDexFile, localTempDir); 89 return Collections.singleton(createDexJarTask); 90 } 91 newVmCommandBuilder(Action action, File workingDirectory)92 @Override public VmCommandBuilder newVmCommandBuilder(Action action, File workingDirectory) { 93 String hostOut = System.getenv("ANDROID_HOST_OUT"); 94 if (hostOut == null || hostOut.length() == 0) { 95 hostOut = System.getenv("ANDROID_BUILD_TOP"); 96 if (hostOut == null) { 97 hostOut = ""; 98 } else { 99 hostOut += "/"; 100 } 101 hostOut += "out/host/linux-x86"; 102 } 103 104 List<File> jars = new ArrayList<File>(); 105 for (String jar : modeId.getJarNames()) { 106 jars.add(new File(hostOut, "framework/" + jar + ".jar")); 107 } 108 Classpath bootClasspath = Classpath.of(jars); 109 110 String libDir = hostOut; 111 if (variant == Variant.X32) { 112 libDir += "/lib"; 113 } else if (variant == Variant.DEFAULT || variant == Variant.X64) { 114 libDir += "/lib64"; 115 } else { 116 throw new AssertionError("Unsupported variant:" + variant); 117 } 118 119 List<String> vmCommand = new ArrayList<String>(); 120 Iterables.addAll(vmCommand, run.invokeWith()); 121 vmCommand.add(hostOut + "/bin/" + run.vmCommand); 122 123 // If you edit this, see also DeviceRuntime... 124 VmCommandBuilder builder = new VmCommandBuilder(run.log) 125 .env("ANDROID_PRINTF_LOG", "tag") 126 .env("ANDROID_LOG_TAGS", "*:i") 127 .env("ANDROID_DATA", dalvikCache().getParent()) 128 .env("ANDROID_ROOT", hostOut) 129 .env("ANDROID_RUNTIME_ROOT", hostOut + "/com.android.runtime") 130 .env("ANDROID_TZDATA_ROOT", hostOut + "/com.android.tzdata") 131 .env("LD_LIBRARY_PATH", libDir) 132 .env("DYLD_LIBRARY_PATH", libDir) 133 // This is needed on the host so that the linker loads core.oat at the necessary 134 // address. 135 .env("LD_USE_LOAD_BIAS", "1") 136 .vmCommand(vmCommand) 137 .vmArgs("-Xbootclasspath:" + bootClasspath.toString()) 138 .vmArgs("-Duser.language=en") 139 .vmArgs("-Duser.region=US"); 140 if (run.debugPort != null) { 141 builder.vmArgs( 142 "-Xcompiler-option", "--debuggable", "-Xplugin:libopenjdkjvmti.so", 143 "-agentpath:libjdwp.so=transport=dt_socket,address=" + run.debugPort 144 + ",server=y,suspend=y"); 145 } 146 if (!run.benchmark && run.checkJni) { 147 builder.vmArgs("-Xcheck:jni"); 148 } 149 // dalvikvm defaults to no limit, but the framework sets the limit at 2000. 150 builder.vmArgs("-Xjnigreflimit:2000"); 151 return builder; 152 } 153 getRuntimeClasspath(Action action)154 @Override public Classpath getRuntimeClasspath(Action action) { 155 Classpath result = new Classpath(); 156 result.addAll(run.localDexFile(action.getName())); 157 for (File classpathElement : run.classpath.getElements()) { 158 result.addAll(run.localDexFile(run.basenameOfJar(classpathElement))); 159 } 160 result.addAll(run.resourceClasspath); 161 return result; 162 } 163 createCreateDexJarTask(Classpath classpath, File classpathElement, String name, Action action, File localDex, File localTempDir)164 private Task createCreateDexJarTask(Classpath classpath, File classpathElement, String name, 165 Action action, File localDex, File localTempDir) { 166 return new DexTask(run.toolchain.getDexer(), run.androidSdk, classpath, run.benchmark, name, 167 classpathElement, action, localDex, localTempDir, run.multidex); 168 } 169 } 170