MonkeyRunner.java revision 5bf37e37529cb8c9dbda7cce57dc46d43e2f30a0
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 */
16package com.android.monkeyrunner;
17
18import com.google.common.base.Functions;
19import com.google.common.base.Preconditions;
20import com.google.common.collect.Collections2;
21
22import com.android.monkeyrunner.doc.MonkeyRunnerExported;
23
24import org.python.core.ArgParser;
25import org.python.core.ClassDictInit;
26import org.python.core.PyException;
27import org.python.core.PyObject;
28
29import java.util.Collection;
30import java.util.logging.Level;
31import java.util.logging.Logger;
32
33import javax.swing.JOptionPane;
34
35/**
36 * This is the main interface class into the jython bindings.
37 */
38@MonkeyRunnerExported(doc = "Main entry point for MonkeyRunner")
39public class MonkeyRunner extends PyObject implements ClassDictInit {
40    private static final Logger LOG = Logger.getLogger(MonkeyRunner.class.getCanonicalName());
41    private static MonkeyRunnerBackend backend;
42
43    public static void classDictInit(PyObject dict) {
44        JythonUtils.convertDocAnnotationsForClass(MonkeyRunner.class, dict);
45    }
46
47    /**
48     * Set the backend MonkeyRunner is using.
49     *
50     * @param backend the backend to use.
51     */
52    /* package */ static void setBackend(MonkeyRunnerBackend backend) {
53        MonkeyRunner.backend = backend;
54    }
55
56    @MonkeyRunnerExported(doc = "Waits for the workstation to connect to the device.",
57            args = {"timeout", "deviceId"},
58            argDocs = {"The timeout in seconds to wait. The default is to wait indefinitely.",
59            "A regular expression that specifies the device name. See the documentation " +
60            "for 'adb' in the Developer Guide to learn more about device names."},
61            returns = "A MonkeyDevice object representing the connected device.")
62    public static MonkeyDevice waitForConnection(PyObject[] args, String[] kws) {
63        ArgParser ap = JythonUtils.createArgParser(args, kws);
64        Preconditions.checkNotNull(ap);
65
66        long timeoutMs;
67        try {
68            double timeoutInSecs = JythonUtils.getFloat(ap, 0);
69            timeoutMs = (long) (timeoutInSecs * 1000.0);
70        } catch (PyException e) {
71            timeoutMs = Long.MAX_VALUE;
72        }
73
74        return backend.waitForConnection(timeoutMs,
75                ap.getString(1, ".*"));
76    }
77
78    @MonkeyRunnerExported(doc = "Pause the currently running program for the specified " +
79            "number of seconds.",
80            args = {"seconds"},
81            argDocs = {"The number of seconds to pause."})
82    public static void sleep(PyObject[] args, String[] kws) {
83        ArgParser ap = JythonUtils.createArgParser(args, kws);
84        Preconditions.checkNotNull(ap);
85
86        double seconds = JythonUtils.getFloat(ap, 0);
87
88        long ms = (long) (seconds * 1000.0);
89
90        try {
91            Thread.sleep(ms);
92        } catch (InterruptedException e) {
93            LOG.log(Level.SEVERE, "Error sleeping", e);
94        }
95    }
96
97    @MonkeyRunnerExported(doc = "Format and display the API reference for MonkeyRunner.",
98            args = { "format" },
99            argDocs = {"The desired format for the output, either 'text' for plain text or " +
100            "'html' for HTML markup."},
101            returns = "A string containing the help text in the desired format.")
102    public static String help(PyObject[] args, String[] kws) {
103        ArgParser ap = JythonUtils.createArgParser(args, kws);
104        Preconditions.checkNotNull(ap);
105
106        String format = ap.getString(0, "text");
107
108        return MonkeyRunnerHelp.helpString(format);
109    }
110
111    @MonkeyRunnerExported(doc = "Display an alert dialog to the process running the current " +
112            "script.  The dialog is modal, so the script stops until the user dismisses the " +
113            "dialog.",
114            args = { "message", "title", "okTitle" },
115            argDocs = {
116            "The message to display in the dialog.",
117            "The dialog's title. The default value is 'Alert'.",
118            "The text to use in the dialog button. The default value is 'OK'."
119    })
120    public static void alert(PyObject[] args, String[] kws) {
121        ArgParser ap = JythonUtils.createArgParser(args, kws);
122        Preconditions.checkNotNull(ap);
123
124        String message = ap.getString(0);
125        String title = ap.getString(1, "Alert");
126        String buttonTitle = ap.getString(2, "OK");
127
128        alert(message, title, buttonTitle);
129    }
130
131    @MonkeyRunnerExported(doc = "Display a dialog that accepts input. The dialog is ," +
132            "modal, so the script stops until the user clicks one of the two dialog buttons. To " +
133            "enter a value, the user enters the value and clicks the 'OK' button. To quit the " +
134            "dialog without entering a value, the user clicks the 'Cancel' button. Use the " +
135            "supplied arguments for this method to customize the text for these buttons.",
136            args = {"message", "initialValue", "title", "okTitle", "cancelTitle"},
137            argDocs = {
138            "The prompt message to display in the dialog.",
139            "The initial value to supply to the user. The default is an empty string)",
140            "The dialog's title. The default is 'Input'",
141            "The text to use in the dialog's confirmation button. The default is 'OK'." +
142            "The text to use in the dialog's 'cancel' button. The default is 'Cancel'."
143    },
144    returns = "The test entered by the user, or None if the user canceled the input;"
145    )
146    public static String input(PyObject[] args, String[] kws) {
147        ArgParser ap = JythonUtils.createArgParser(args, kws);
148        Preconditions.checkNotNull(ap);
149
150        String message = ap.getString(0);
151        String initialValue = ap.getString(1, "");
152        String title = ap.getString(2, "Input");
153
154        return input(message, initialValue, title);
155    }
156
157    @MonkeyRunnerExported(doc = "Display a choice dialog that allows the user to select a single " +
158            "item from a list of items.",
159            args = {"message", "choices", "title"},
160            argDocs = {
161            "The prompt message to display in the dialog.",
162            "An iterable Python type containing a list of choices to display",
163            "The dialog's title. The default is 'Input'" },
164            returns = "The 0-based numeric offset of the selected item in the iterable.")
165    public static int choice(PyObject[] args, String kws[]) {
166        ArgParser ap = JythonUtils.createArgParser(args, kws);
167        Preconditions.checkNotNull(ap);
168
169        String message = ap.getString(0);
170        Collection<String> choices = Collections2.transform(JythonUtils.getList(ap, 1),
171                Functions.toStringFunction());
172        String title = ap.getString(2, "Input");
173
174        return choice(message, title, choices);
175    }
176
177    @MonkeyRunnerExported(doc = "Loads a MonkeyImage from a file.",
178            args = { "path" },
179            argDocs = {
180            "The path to the file to load.  This file path is in terms of the computer running " +
181            "MonkeyRunner and not a path on the Android Device. " },
182            returns = "A new MonkeyImage representing the specified file")
183    public static MonkeyImage loadImageFromFile(PyObject[] args, String kws[]) {
184        ArgParser ap = JythonUtils.createArgParser(args, kws);
185        Preconditions.checkNotNull(ap);
186
187        String path = ap.getString(0);
188
189        return MonkeyImage.loadImageFromFile(path);
190    }
191
192    /**
193     * Display an alert dialog.
194     *
195     * @param message the message to show.
196     * @param title the title of the dialog box.
197     * @param okTitle the title of the button.
198     */
199    public static void alert(String message, String title, String okTitle) {
200        Object[] options = { okTitle };
201        JOptionPane.showOptionDialog(null, message, title, JOptionPane.DEFAULT_OPTION,
202                JOptionPane.INFORMATION_MESSAGE, null, options, options[0]);
203    }
204
205    /**
206     * Display a dialog allow the user to pick a choice from a list of choices.
207     *
208     * @param message the message to show.
209     * @param title the title of the dialog box.
210     * @param choices the list of the choices to display.
211     * @return the index of the selected choice, or -1 if nothing was chosen.
212     */
213    public static int choice(String message, String title, Collection<String> choices) {
214        Object[] possibleValues = choices.toArray();
215        Object selectedValue = JOptionPane.showInputDialog(null, message, title,
216                JOptionPane.QUESTION_MESSAGE, null, possibleValues, possibleValues[0]);
217
218        for (int x = 0; x < possibleValues.length; x++) {
219            if (possibleValues[x].equals(selectedValue)) {
220                return x;
221            }
222        }
223        // Error
224        return -1;
225    }
226
227    /**
228     * Display a dialog that allows the user to input a text string.
229     *
230     * @param message the message to show.
231     * @param initialValue the initial value to display in the dialog
232     * @param title the title of the dialog box.
233     * @return the entered string, or null if cancelled
234     */
235    public static String input(String message, String initialValue, String title) {
236        return (String) JOptionPane.showInputDialog(null, message, title,
237                JOptionPane.QUESTION_MESSAGE, null, null, initialValue);
238    }
239}
240