/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package vogar.android; import com.google.common.collect.Iterables; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import vogar.Action; import vogar.Classpath; import vogar.Mode; import vogar.ModeId; import vogar.Run; import vogar.Toolchain; import vogar.Variant; import vogar.commands.VmCommandBuilder; import vogar.tasks.MkdirTask; import vogar.tasks.RunActionTask; import vogar.tasks.Task; /** * Executes actions on a Dalvik or ART runtime on a Linux desktop. */ public final class HostRuntime implements Mode { private final Run run; private final ModeId modeId; private final Variant variant; public HostRuntime(Run run, ModeId modeId, Variant variant) { if (!modeId.isHost() || !modeId.supportsVariant(variant)) { throw new IllegalArgumentException("Unsupported mode:" + modeId + " or variant: " + variant); } this.run = run; this.modeId = modeId; this.variant = variant; } @Override public Task executeActionTask(Action action, boolean useLargeTimeout) { return new RunActionTask(run, action, useLargeTimeout); } private File dalvikCache() { return run.localFile("android-data", run.dalvikCache); } @Override public Set installTasks() { Set result = new HashSet(); for (File classpathElement : run.classpath.getElements()) { // Libraries need to be dex'ed and put in the temporary directory. String name = run.basenameOfJar(classpathElement); File localDex = run.localDexFile(name); File localTempDir = run.localDir(name); result.add(createCreateDexJarTask(run.classpath, classpathElement, name, null /* action */, localDex, localTempDir)); } result.add(new MkdirTask(run.mkdir, dalvikCache())); return result; } @Override public Set cleanupTasks(Action action) { return Collections.emptySet(); } @Override public Set installActionTasks(Action action, File jar) { File localDexFile = run.localDexFile(action.getName()); File localTempDir = run.localDir(action.getName()); Task createDexJarTask = createCreateDexJarTask(Classpath.of(jar), jar, action.getName(), action, localDexFile, localTempDir); return Collections.singleton(createDexJarTask); } @Override public VmCommandBuilder newVmCommandBuilder(Action action, File workingDirectory) { String hostOut = System.getenv("ANDROID_HOST_OUT"); if (hostOut == null || hostOut.length() == 0) { hostOut = System.getenv("ANDROID_BUILD_TOP"); if (hostOut == null) { hostOut = ""; } else { hostOut += "/"; } hostOut += "out/host/linux-x86"; } List jars = new ArrayList(); for (String jar : modeId.getJarNames()) { jars.add(new File(hostOut, "framework/" + jar + ".jar")); } Classpath bootClasspath = Classpath.of(jars); String libDir = hostOut; if (variant == Variant.X32) { libDir += "/lib"; } else if (variant == Variant.DEFAULT || variant == Variant.X64) { libDir += "/lib64"; } else { throw new AssertionError("Unsupported variant:" + variant); } List vmCommand = new ArrayList(); Iterables.addAll(vmCommand, run.invokeWith()); vmCommand.add(hostOut + "/bin/" + run.vmCommand); // If you edit this, see also DeviceRuntime... VmCommandBuilder builder = new VmCommandBuilder(run.log) .env("ANDROID_PRINTF_LOG", "tag") .env("ANDROID_LOG_TAGS", "*:i") .env("ANDROID_DATA", dalvikCache().getParent()) .env("ANDROID_ROOT", hostOut) .env("ANDROID_RUNTIME_ROOT", hostOut + "/com.android.runtime") .env("ANDROID_TZDATA_ROOT", hostOut + "/com.android.tzdata") .env("LD_LIBRARY_PATH", libDir) .env("DYLD_LIBRARY_PATH", libDir) // This is needed on the host so that the linker loads core.oat at the necessary // address. .env("LD_USE_LOAD_BIAS", "1") .vmCommand(vmCommand) .vmArgs("-Xbootclasspath:" + bootClasspath.toString()) .vmArgs("-Duser.language=en") .vmArgs("-Duser.region=US"); if (run.debugPort != null) { builder.vmArgs( "-Xcompiler-option", "--debuggable", "-Xplugin:libopenjdkjvmti.so", "-agentpath:libjdwp.so=transport=dt_socket,address=" + run.debugPort + ",server=y,suspend=y"); } if (!run.benchmark && run.checkJni) { builder.vmArgs("-Xcheck:jni"); } // dalvikvm defaults to no limit, but the framework sets the limit at 2000. builder.vmArgs("-Xjnigreflimit:2000"); return builder; } @Override public Classpath getRuntimeClasspath(Action action) { Classpath result = new Classpath(); result.addAll(run.localDexFile(action.getName())); for (File classpathElement : run.classpath.getElements()) { result.addAll(run.localDexFile(run.basenameOfJar(classpathElement))); } result.addAll(run.resourceClasspath); return result; } private Task createCreateDexJarTask(Classpath classpath, File classpathElement, String name, Action action, File localDex, File localTempDir) { return new DexTask(run.toolchain.getDexer(), run.androidSdk, classpath, run.benchmark, name, classpathElement, action, localDex, localTempDir, run.multidex); } }