17850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com/*
27850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * Copyright (C) 2009 The Android Open Source Project
37850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com *
47850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * Licensed under the Apache License, Version 2.0 (the "License");
57850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * you may not use this file except in compliance with the License.
67850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * You may obtain a copy of the License at
77850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com *
87850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com *      http://www.apache.org/licenses/LICENSE-2.0
97850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com *
107850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * Unless required by applicable law or agreed to in writing, software
117850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * distributed under the License is distributed on an "AS IS" BASIS,
127850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * See the License for the specific language governing permissions and
147850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * limitations under the License.
157850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com */
167850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
17969d5622a380e2f2f9ebdfbf7a22cbb3e031125bjessewilson@google.compackage vogar.android;
187850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
197029503206e4c89fe167c3389c1062d89cf35c52Paul Duffinimport com.google.common.base.Supplier;
205b644afaebd7afc43f75010b7c32f02129638a49bdc@google.comimport com.google.common.collect.Iterables;
217850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.io.File;
225b644afaebd7afc43f75010b7c32f02129638a49bdc@google.comimport java.util.ArrayList;
236a0f4cdb51f57b4b38f9ee1ed9f44f1afc9f6da6jessewilson@google.comimport java.util.Collections;
246a0f4cdb51f57b4b38f9ee1ed9f44f1afc9f6da6jessewilson@google.comimport java.util.HashSet;
255b644afaebd7afc43f75010b7c32f02129638a49bdc@google.comimport java.util.List;
26f83be5e4273263df2bb9ef609946b911695b3996jessewilson@google.comimport java.util.Set;
27969d5622a380e2f2f9ebdfbf7a22cbb3e031125bjessewilson@google.comimport vogar.Action;
28c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.comimport vogar.Variant;
29969d5622a380e2f2f9ebdfbf7a22cbb3e031125bjessewilson@google.comimport vogar.Classpath;
30f83be5e4273263df2bb9ef609946b911695b3996jessewilson@google.comimport vogar.Mode;
31c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.comimport vogar.ModeId;
32f83be5e4273263df2bb9ef609946b911695b3996jessewilson@google.comimport vogar.Run;
33f83be5e4273263df2bb9ef609946b911695b3996jessewilson@google.comimport vogar.commands.VmCommandBuilder;
34db82cde9016d812b26b6c79e375fdf60ead1d9fajessewilson@google.comimport vogar.tasks.RunActionTask;
352c37ef5a628067f4d7e5a5c69a7314647939a5e1jessewilson@google.comimport vogar.tasks.Task;
367850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
377850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com/**
38c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.com * Execute actions on an Android device or emulator using "app_process" or the runtime directly.
397850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com */
40c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.compublic final class DeviceRuntime implements Mode {
41c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.com    private final Run run;
42c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.com    private final ModeId modeId;
437029503206e4c89fe167c3389c1062d89cf35c52Paul Duffin    private final Supplier<String> deviceUserNameSupplier;
44db82cde9016d812b26b6c79e375fdf60ead1d9fajessewilson@google.com
457029503206e4c89fe167c3389c1062d89cf35c52Paul Duffin    public DeviceRuntime(Run run, ModeId modeId, Variant variant,
467029503206e4c89fe167c3389c1062d89cf35c52Paul Duffin                         Supplier<String> deviceUserNameSupplier) {
477029503206e4c89fe167c3389c1062d89cf35c52Paul Duffin        this.deviceUserNameSupplier = deviceUserNameSupplier;
48c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.com        if (!modeId.isDevice() || !modeId.supportsVariant(variant)) {
49c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.com            throw new IllegalArgumentException("Unsupported mode:" + modeId +
50c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.com                    " or variant: " + variant);
51c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.com        }
52db82cde9016d812b26b6c79e375fdf60ead1d9fajessewilson@google.com        this.run = run;
53c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.com        this.modeId = modeId;
54d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    }
55d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
56db82cde9016d812b26b6c79e375fdf60ead1d9fajessewilson@google.com    @Override public Set<Task> installTasks() {
576a0f4cdb51f57b4b38f9ee1ed9f44f1afc9f6da6jessewilson@google.com        Set<Task> result = new HashSet<Task>();
587850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        // dex everything on the classpath and push it to the device.
59f83be5e4273263df2bb9ef609946b911695b3996jessewilson@google.com        for (File classpathElement : run.classpath.getElements()) {
604b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller            addCreateDexJarAndPushTasks(result, run.basenameOfJar(classpathElement),
612c37ef5a628067f4d7e5a5c69a7314647939a5e1jessewilson@google.com                    classpathElement, null);
627850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
636a0f4cdb51f57b4b38f9ee1ed9f44f1afc9f6da6jessewilson@google.com        return result;
647850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
657850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
666a0f4cdb51f57b4b38f9ee1ed9f44f1afc9f6da6jessewilson@google.com    @Override public Set<Task> installActionTasks(Action action, File jar) {
676a0f4cdb51f57b4b38f9ee1ed9f44f1afc9f6da6jessewilson@google.com        Set<Task> result = new HashSet<Task>();
684b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller        addCreateDexJarAndPushTasks(result, action.getName(), jar, action);
696a0f4cdb51f57b4b38f9ee1ed9f44f1afc9f6da6jessewilson@google.com        return result;
706a0f4cdb51f57b4b38f9ee1ed9f44f1afc9f6da6jessewilson@google.com    }
716a0f4cdb51f57b4b38f9ee1ed9f44f1afc9f6da6jessewilson@google.com
72db82cde9016d812b26b6c79e375fdf60ead1d9fajessewilson@google.com    @Override public Task executeActionTask(Action action, boolean useLargeTimeout) {
73db82cde9016d812b26b6c79e375fdf60ead1d9fajessewilson@google.com        return new RunActionTask(run, action, useLargeTimeout);
74db82cde9016d812b26b6c79e375fdf60ead1d9fajessewilson@google.com    }
75db82cde9016d812b26b6c79e375fdf60ead1d9fajessewilson@google.com
76f83be5e4273263df2bb9ef609946b911695b3996jessewilson@google.com    @Override public VmCommandBuilder newVmCommandBuilder(Action action, File workingDirectory) {
775b644afaebd7afc43f75010b7c32f02129638a49bdc@google.com        List<String> vmCommand = new ArrayList<String>();
78db82cde9016d812b26b6c79e375fdf60ead1d9fajessewilson@google.com        Iterables.addAll(vmCommand, run.invokeWith());
79f1622c3bd3278fefaab9fa78aca445908362a74abdc@google.com        vmCommand.add(run.vmCommand);
805762c9cb967f90629e48ba67e6ff03ce7c48c834enh@google.com
81c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.com        // If you edit this, see also HostRuntime...
82f83be5e4273263df2bb9ef609946b911695b3996jessewilson@google.com        VmCommandBuilder vmCommandBuilder = new VmCommandBuilder(run.log)
83411cb1fb67241125203629229600ecbd821eb9c7Paul Duffin                .env("ANDROID_DATA", run.getAndroidDataPath())
84411cb1fb67241125203629229600ecbd821eb9c7Paul Duffin                .workingDirectory(workingDirectory)
855b644afaebd7afc43f75010b7c32f02129638a49bdc@google.com                .vmCommand(vmCommand)
86f83be5e4273263df2bb9ef609946b911695b3996jessewilson@google.com                .vmArgs("-Duser.home=" + run.deviceUserHome)
870e5c70d64d0a68bd48f6389563565290bbff4914Roland Levillain                // Use the same command line limit (4096) as adb (see
880e5c70d64d0a68bd48f6389563565290bbff4914Roland Levillain                // _adb_connect in system/core/adb/adb_client.cpp).
890e5c70d64d0a68bd48f6389563565290bbff4914Roland Levillain                .maxLength(4096);
909712658a463c437f5437bcd981e7e6beacac0dc5Neil Fuller        if (run.debugPort != null) {
919712658a463c437f5437bcd981e7e6beacac0dc5Neil Fuller            vmCommandBuilder.vmArgs("-Xcompiler-option", "--debuggable");
929712658a463c437f5437bcd981e7e6beacac0dc5Neil Fuller        }
939712658a463c437f5437bcd981e7e6beacac0dc5Neil Fuller
94c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.com        if (modeId == ModeId.APP_PROCESS) {
95c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.com            return vmCommandBuilder
96c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.com                .vmArgs(action.getUserDir().getPath())
97c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.com                .classpathViaProperty(true);
98c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.com        }
99c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.com
100c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.com        vmCommandBuilder
1017029503206e4c89fe167c3389c1062d89cf35c52Paul Duffin                .vmArgs("-Duser.name=" + deviceUserNameSupplier.get())
1027850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                .vmArgs("-Duser.language=en")
103c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.com                .vmArgs("-Duser.region=US");
104c620846e4044b3b3a8abfc42ddba4adca4e545d9nfuller@google.com
105f76a1e929a3ad46e7612a9307efffffc47222cc4Rayhaan Jaufeerally        if (!run.benchmark && run.checkJni) {
1065762c9cb967f90629e48ba67e6ff03ce7c48c834enh@google.com            vmCommandBuilder.vmArgs("-Xcheck:jni");
107e5dfbecbaa8568c2885a4cb859c8afa8b6a08d5bjsharpe@google.com        }
1085762c9cb967f90629e48ba67e6ff03ce7c48c834enh@google.com        // dalvikvm defaults to no limit, but the framework sets the limit at 2000.
1095762c9cb967f90629e48ba67e6ff03ce7c48c834enh@google.com        vmCommandBuilder.vmArgs("-Xjnigreflimit:2000");
110e5dfbecbaa8568c2885a4cb859c8afa8b6a08d5bjsharpe@google.com        return vmCommandBuilder;
1117850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
1127850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
1136a0f4cdb51f57b4b38f9ee1ed9f44f1afc9f6da6jessewilson@google.com    @Override public Set<Task> cleanupTasks(Action action) {
1140eb0936e90bf11463c8ee937ca996d7bd654a098jessewilson@google.com        return Collections.singleton(run.target.rmTask(action.getUserDir()));
1156a0f4cdb51f57b4b38f9ee1ed9f44f1afc9f6da6jessewilson@google.com    }
1166a0f4cdb51f57b4b38f9ee1ed9f44f1afc9f6da6jessewilson@google.com
117f83be5e4273263df2bb9ef609946b911695b3996jessewilson@google.com    @Override public Classpath getRuntimeClasspath(Action action) {
1187850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        Classpath result = new Classpath();
1190eb0936e90bf11463c8ee937ca996d7bd654a098jessewilson@google.com        result.addAll(run.targetDexFile(action.getName()));
120f83be5e4273263df2bb9ef609946b911695b3996jessewilson@google.com        if (!run.benchmark) {
121f83be5e4273263df2bb9ef609946b911695b3996jessewilson@google.com            for (File classpathElement : run.classpath.getElements()) {
1220eb0936e90bf11463c8ee937ca996d7bd654a098jessewilson@google.com                result.addAll(run.targetDexFile(run.basenameOfJar(classpathElement)));
123e5dfbecbaa8568c2885a4cb859c8afa8b6a08d5bjsharpe@google.com            }
1247850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
125f39d9a39bc81bc5750c53fabd2bb9d3bdd1e389abdc@google.com        // Note we intentionally do not add run.resourceClasspath on
126f39d9a39bc81bc5750c53fabd2bb9d3bdd1e389abdc@google.com        // the device since it contains host path names.
1277850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        return result;
1287850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
1294b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller
1304b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller    private void addCreateDexJarAndPushTasks(
1314b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller            Set<Task> tasks, String name, File jar, Action action) {
1324b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller        File localDex = run.localDexFile(name);
1334b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller        File deviceDex = run.targetDexFile(name);
1344b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller        Task createDexJarTask = newCreateDexJarTask(run.classpath, jar, name, action, localDex);
1354b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller        tasks.add(createDexJarTask);
1364b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller        tasks.add(run.target.pushTask(localDex, deviceDex).afterSuccess(createDexJarTask));
1374b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller    }
1384b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller
1394b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller    private Task newCreateDexJarTask(Classpath classpath, File classpathElement, String name,
1404b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller            Action action, File localDex) {
1414b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller        Task dex;
1424b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller        if (run.useJack) {
1434b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller            dex = new JackDexTask(run, classpath, run.benchmark, name, classpathElement,
14439f93c4843a86ba62c7c9bd975911562b8a298f9Neil Fuller                    action, localDex);
1454b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller        } else {
1464b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller            dex = new DexTask(run.androidSdk, classpath, run.benchmark, name, classpathElement,
147388fcad5269758e893c6982fa9e4c2fbb474460aNeil Fuller                    action, localDex, run.multidex);
1484b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller        }
1494b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller        return dex;
1504b2e7ab15323b2b057e8bb7b0cf361bb2ab880e0Neil Fuller    }
1517850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com}
152