Home | History | Annotate | Download | only in android
      1 /*
      2  * Copyright (C) 2009 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.base.Supplier;
     20 import com.google.common.collect.Iterables;
     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 import vogar.Action;
     28 import vogar.Toolchain;
     29 import vogar.Variant;
     30 import vogar.Classpath;
     31 import vogar.Mode;
     32 import vogar.ModeId;
     33 import vogar.Run;
     34 import vogar.commands.VmCommandBuilder;
     35 import vogar.tasks.RunActionTask;
     36 import vogar.tasks.Task;
     37 
     38 /**
     39  * Execute actions on an Android device or emulator using "app_process" or the runtime directly.
     40  */
     41 public final class DeviceRuntime implements Mode {
     42     private final Run run;
     43     private final ModeId modeId;
     44     private final Supplier<String> deviceUserNameSupplier;
     45 
     46     public DeviceRuntime(Run run, ModeId modeId, Variant variant,
     47                          Supplier<String> deviceUserNameSupplier) {
     48         this.deviceUserNameSupplier = deviceUserNameSupplier;
     49         if (!modeId.isDevice() || !modeId.supportsVariant(variant)) {
     50             throw new IllegalArgumentException("Unsupported mode:" + modeId +
     51                     " or variant: " + variant);
     52         }
     53         this.run = run;
     54         this.modeId = modeId;
     55     }
     56 
     57     @Override public Set<Task> installTasks() {
     58         Set<Task> result = new HashSet<Task>();
     59         // dex everything on the classpath and push it to the device.
     60         for (File classpathElement : run.classpath.getElements()) {
     61             addCreateDexJarAndPushTasks(result, run.basenameOfJar(classpathElement),
     62                     classpathElement, null);
     63         }
     64         return result;
     65     }
     66 
     67     @Override public Set<Task> installActionTasks(Action action, File jar) {
     68         Set<Task> result = new HashSet<Task>();
     69         addCreateDexJarAndPushTasks(result, action.getName(), jar, action);
     70         return result;
     71     }
     72 
     73     @Override public Task executeActionTask(Action action, boolean useLargeTimeout) {
     74         return new RunActionTask(run, action, useLargeTimeout);
     75     }
     76 
     77     @Override public VmCommandBuilder newVmCommandBuilder(Action action, File workingDirectory) {
     78         List<String> vmCommand = new ArrayList<String>();
     79         Iterables.addAll(vmCommand, run.invokeWith());
     80         vmCommand.add(run.vmCommand);
     81 
     82         // If you edit this, see also HostRuntime...
     83         VmCommandBuilder vmCommandBuilder = new VmCommandBuilder(run.log)
     84                 .env("ANDROID_DATA", run.getAndroidDataPath())
     85                 .workingDirectory(workingDirectory)
     86                 .vmCommand(vmCommand)
     87                 .vmArgs("-Duser.home=" + run.deviceUserHome)
     88                 // Use the same command line limit (4096) as adb (see
     89                 // _adb_connect in system/core/adb/adb_client.cpp).
     90                 .maxLength(4096);
     91         if (run.debugPort != null) {
     92             vmCommandBuilder.vmArgs(
     93                     "-Xcompiler-option", "--debuggable", "-Xplugin:libopenjdkjvmti.so",
     94                     "-agentpath:libjdwp.so=transport=dt_socket,address=" + run.debugPort
     95                             + ",server=y,suspend=y");
     96         }
     97 
     98         if (modeId == ModeId.APP_PROCESS) {
     99             return vmCommandBuilder
    100                 .vmArgs(action.getUserDir().getPath())
    101                 .classpathViaProperty(true);
    102         }
    103 
    104         vmCommandBuilder
    105                 .vmArgs("-Duser.name=" + deviceUserNameSupplier.get())
    106                 .vmArgs("-Duser.language=en")
    107                 .vmArgs("-Duser.region=US");
    108 
    109         if (!run.benchmark && run.checkJni) {
    110             vmCommandBuilder.vmArgs("-Xcheck:jni");
    111         }
    112         // dalvikvm defaults to no limit, but the framework sets the limit at 2000.
    113         vmCommandBuilder.vmArgs("-Xjnigreflimit:2000");
    114         return vmCommandBuilder;
    115     }
    116 
    117     @Override public Set<Task> cleanupTasks(Action action) {
    118         return Collections.singleton(run.target.rmTask(action.getUserDir()));
    119     }
    120 
    121     @Override public Classpath getRuntimeClasspath(Action action) {
    122         Classpath result = new Classpath();
    123         result.addAll(run.targetDexFile(action.getName()));
    124         if (!run.benchmark) {
    125             for (File classpathElement : run.classpath.getElements()) {
    126                 result.addAll(run.targetDexFile(run.basenameOfJar(classpathElement)));
    127             }
    128         }
    129         // Note we intentionally do not add run.resourceClasspath on
    130         // the device since it contains host path names.
    131         return result;
    132     }
    133 
    134     private void addCreateDexJarAndPushTasks(
    135             Set<Task> tasks, String name, File jar, Action action) {
    136         File localDex = run.localDexFile(name);
    137         File localTempDir = run.localDir(name);
    138         File deviceDex = run.targetDexFile(name);
    139         Task createDexJarTask = newCreateDexJarTask(run.classpath, jar, name, action, localDex,
    140                 localTempDir);
    141         tasks.add(createDexJarTask);
    142         tasks.add(run.target.pushTask(localDex, deviceDex).afterSuccess(createDexJarTask));
    143     }
    144 
    145     private Task newCreateDexJarTask(Classpath classpath, File classpathElement, String name,
    146             Action action, File localDex, File localTempDir) {
    147         return new DexTask(run.toolchain.getDexer(), run.androidSdk, classpath, run.benchmark,
    148                 name, classpathElement, action, localDex, localTempDir, run.multidex);
    149     }
    150 }
    151