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