Home | History | Annotate | Download | only in android
      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 
     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 
     58     @Override public Task executeActionTask(Action action, boolean useLargeTimeout) {
     59         return new RunActionTask(run, action, useLargeTimeout);
     60     }
     61 
     62     private File dalvikCache() {
     63         return run.localFile("android-data", run.dalvikCache);
     64     }
     65 
     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 
     80     @Override public Set<Task> cleanupTasks(Action action) {
     81         return Collections.emptySet();
     82     }
     83 
     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 
     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.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("LD_LIBRARY_PATH", libDir)
    130                 .env("DYLD_LIBRARY_PATH", libDir)
    131                 // This is needed on the host so that the linker loads core.oat at the necessary
    132                 // address.
    133                 .env("LD_USE_LOAD_BIAS", "1")
    134                 .vmCommand(vmCommand)
    135                 .vmArgs("-Xbootclasspath:" + bootClasspath.toString())
    136                 .vmArgs("-Duser.language=en")
    137                 .vmArgs("-Duser.region=US");
    138         if (run.debugPort != null) {
    139             builder.vmArgs(
    140                     "-Xcompiler-option", "--debuggable", "-Xplugin:libopenjdkjvmti.so",
    141                     "-agentpath:libjdwp.so=transport=dt_socket,address=" + run.debugPort
    142                             + ",server=y,suspend=y");
    143         }
    144         if (!run.benchmark && run.checkJni) {
    145             builder.vmArgs("-Xcheck:jni");
    146         }
    147         // dalvikvm defaults to no limit, but the framework sets the limit at 2000.
    148         builder.vmArgs("-Xjnigreflimit:2000");
    149         return builder;
    150     }
    151 
    152     @Override public Classpath getRuntimeClasspath(Action action) {
    153         Classpath result = new Classpath();
    154         result.addAll(run.localDexFile(action.getName()));
    155         for (File classpathElement : run.classpath.getElements()) {
    156             result.addAll(run.localDexFile(run.basenameOfJar(classpathElement)));
    157         }
    158         result.addAll(run.resourceClasspath);
    159         return result;
    160     }
    161 
    162     private Task createCreateDexJarTask(Classpath classpath, File classpathElement, String name,
    163             Action action, File localDex, File localTempDir) {
    164         return new DexTask(run.toolchain.getDexer(), run.androidSdk, classpath, run.benchmark, name,
    165                 classpathElement, action, localDex, localTempDir, run.multidex);
    166     }
    167 }
    168