diff options
author | Bill Napier <napier@google.com> | 2009-08-17 11:20:15 -0700 |
---|---|---|
committer | Bill Napier <napier@google.com> | 2009-08-17 11:20:15 -0700 |
commit | f94816017efd272dca6fb29f4b90e549e05cc6e2 (patch) | |
tree | de4e6c1f784373a16e6f3b84aacd4daf94fbe1ec | |
parent | 12ad9fb10e1be799fa47a56ee1f1429b761db6e6 (diff) | |
download | development-f94816017efd272dca6fb29f4b90e549e05cc6e2.tar.gz |
Add getvar and listvar commands to monkey to allow inspection of properties on the device.
4 files changed, 393 insertions, 81 deletions
diff --git a/cmds/monkey/README.NETWORK.txt b/cmds/monkey/README.NETWORK.txt index 51b56c87d..4e78b6c8b 100644 --- a/cmds/monkey/README.NETWORK.txt +++ b/cmds/monkey/README.NETWORK.txt @@ -27,14 +27,20 @@ COMMAND LIST Individual commands are separated by newlines. The Monkey will respond to every command with a line starting with OK for commands that executed without a problem, or a line starting with ERROR for -commands that had problems being run. The Monkey may decide to return -more information about command execution. That information would come -on the same line after the OK or ERROR. A possible example: +commands that had problems being run. For commands that return a +value, that value is returned on the same line as the OK or ERROR +response. The value is everything after (but not include) the colon +on that line. For ERROR values, this could be a message indicating +what happened. A possible example: key down menu OK touch monkey ERROR: monkey not a number +getvar sdk +OK: donut +getvar foo +ERROR: no such var The complete list of commands follows: @@ -92,6 +98,16 @@ type string This command will simulate a user typing the given string on the keyboard by generating the proper KeyEvents. +listvar + +This command lists all the vars that the monkey knows about. They are +returned as a whitespace separated list. + +getvar varname + +This command returns the value of the given var. listvar can be used +to find out what vars are supported. + quit Fully quit the monkey and accept no new sessions. diff --git a/cmds/monkey/src/com/android/commands/monkey/Monkey.java b/cmds/monkey/src/com/android/commands/monkey/Monkey.java index 709a70c1a..521de16d6 100644 --- a/cmds/monkey/src/com/android/commands/monkey/Monkey.java +++ b/cmds/monkey/src/com/android/commands/monkey/Monkey.java @@ -135,6 +135,10 @@ public class Monkey { MonkeyEventSource mEventSource; private MonkeyNetworkMonitor mNetworkMonitor = new MonkeyNetworkMonitor(); + // information on the current activity. + public static Intent currentIntent; + public static String currentPackage; + /** * Monitor operations happening in the system. */ @@ -145,6 +149,8 @@ public class Monkey { System.out.println(" // " + (allow ? "Allowing" : "Rejecting") + " start of " + intent + " in package " + pkg); } + currentPackage = pkg; + currentIntent = intent; return allow; } @@ -154,9 +160,10 @@ public class Monkey { if (!allow) { if (mVerbose > 0) { System.out.println(" // " + (allow ? "Allowing" : "Rejecting") - + " resume of package " + pkg); + + " resume of package " + pkg); } } + currentPackage = pkg; return allow; } diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceNetwork.java b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceNetwork.java index 7a2bccd30..a9a1db416 100644 --- a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceNetwork.java +++ b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceNetwork.java @@ -49,8 +49,55 @@ import java.util.StringTokenizer; public class MonkeySourceNetwork implements MonkeyEventSource { private static final String TAG = "MonkeyStub"; - private interface MonkeyCommand { - MonkeyEvent translateCommand(List<String> command, CommandQueue queue); + /** + * ReturnValue from the MonkeyCommand that indicates whether the + * command was sucessful or not. + */ + public static class MonkeyCommandReturn { + private final boolean success; + private final String message; + + public MonkeyCommandReturn(boolean success) { + this.success = success; + this.message = null; + } + + public MonkeyCommandReturn(boolean success, + String message) { + this.success = success; + this.message = message; + } + + boolean hasMessage() { + return message != null; + } + + String getMessage() { + return message; + } + + boolean wasSuccessful() { + return success; + } + } + + public final static MonkeyCommandReturn OK = new MonkeyCommandReturn(true); + public final static MonkeyCommandReturn ERROR = new MonkeyCommandReturn(false); + public final static MonkeyCommandReturn EARG = new MonkeyCommandReturn(false, + "Invalid Argument"); + + /** + * Interface that MonkeyCommands must implement. + */ + public interface MonkeyCommand { + /** + * Translate the command line into a sequence of MonkeyEvents. + * + * @param command the command line. + * @param queue the command queue. + * @returs MonkeyCommandReturn indicating what happened. + */ + MonkeyCommandReturn translateCommand(List<String> command, CommandQueue queue); } /** @@ -59,17 +106,19 @@ public class MonkeySourceNetwork implements MonkeyEventSource { private static class FlipCommand implements MonkeyCommand { // flip open // flip closed - public MonkeyEvent translateCommand(List<String> command, - CommandQueue queue) { + public MonkeyCommandReturn translateCommand(List<String> command, + CommandQueue queue) { if (command.size() > 1) { String direction = command.get(1); if ("open".equals(direction)) { - return new MonkeyFlipEvent(true); + queue.enqueueEvent(new MonkeyFlipEvent(true)); + return OK; } else if ("close".equals(direction)) { - return new MonkeyFlipEvent(false); + queue.enqueueEvent(new MonkeyFlipEvent(false)); + return OK; } } - return null; + return EARG; } } @@ -81,8 +130,8 @@ public class MonkeySourceNetwork implements MonkeyEventSource { // touch down 120 120 // touch move 140 140 // touch up 140 140 - public MonkeyEvent translateCommand(List<String> command, - CommandQueue queue) { + public MonkeyCommandReturn translateCommand(List<String> command, + CommandQueue queue) { if (command.size() == 4) { String actionName = command.get(1); int x = 0; @@ -93,7 +142,7 @@ public class MonkeySourceNetwork implements MonkeyEventSource { } catch (NumberFormatException e) { // Ok, it wasn't a number Log.e(TAG, "Got something that wasn't a number", e); - return null; + return EARG; } // figure out the action @@ -107,14 +156,14 @@ public class MonkeySourceNetwork implements MonkeyEventSource { } if (action == -1) { Log.e(TAG, "Got a bad action: " + actionName); - return null; + return EARG; } - return new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER, - -1, action, x, y, 0); + queue.enqueueEvent(new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER, + -1, action, x, y, 0)); + return OK; } - return null; - + return EARG; } } @@ -125,8 +174,8 @@ public class MonkeySourceNetwork implements MonkeyEventSource { // trackball [dx] [dy] // trackball 1 0 -- move right // trackball -1 0 -- move left - public MonkeyEvent translateCommand(List<String> command, - CommandQueue queue) { + public MonkeyCommandReturn translateCommand(List<String> command, + CommandQueue queue) { if (command.size() == 3) { int dx = 0; int dy = 0; @@ -136,13 +185,14 @@ public class MonkeySourceNetwork implements MonkeyEventSource { } catch (NumberFormatException e) { // Ok, it wasn't a number Log.e(TAG, "Got something that wasn't a number", e); - return null; + return EARG; } - return new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, -1, - MotionEvent.ACTION_MOVE, dx, dy, 0); + queue.enqueueEvent(new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, -1, + MotionEvent.ACTION_MOVE, dx, dy, 0)); + return OK; } - return null; + return EARG; } } @@ -153,14 +203,14 @@ public class MonkeySourceNetwork implements MonkeyEventSource { // key [down|up] [keycode] // key down 82 // key up 82 - public MonkeyEvent translateCommand(List<String> command, - CommandQueue queue) { + public MonkeyCommandReturn translateCommand(List<String> command, + CommandQueue queue) { if (command.size() == 3) { int keyCode = getKeyCode(command.get(2)); if (keyCode < 0) { // Ok, you gave us something bad. Log.e(TAG, "Can't find keyname: " + command.get(2)); - return null; + return EARG; } Log.d(TAG, "keycode: " + keyCode); int action = -1; @@ -171,11 +221,12 @@ public class MonkeySourceNetwork implements MonkeyEventSource { } if (action == -1) { Log.e(TAG, "got unknown action."); - return null; + return EARG; } - return new MonkeyKeyEvent(action, keyCode); + queue.enqueueEvent(new MonkeyKeyEvent(action, keyCode)); + return OK; } - return null; + return EARG; } } @@ -210,19 +261,21 @@ public class MonkeySourceNetwork implements MonkeyEventSource { */ private static class SleepCommand implements MonkeyCommand { // sleep 2000 - public MonkeyEvent translateCommand(List<String> command, - CommandQueue queue) { + public MonkeyCommandReturn translateCommand(List<String> command, + CommandQueue queue) { if (command.size() == 2) { int sleep = -1; String sleepStr = command.get(1); try { sleep = Integer.parseInt(sleepStr); } catch (NumberFormatException e) { - Log.e(TAG, "Not a number: " + sleepStr, e); + Log.e(TAG, "Not a number: " + sleepStr, e); + return EARG; } - return new MonkeyThrottleEvent(sleep); + queue.enqueueEvent(new MonkeyThrottleEvent(sleep)); + return OK; } - return null; + return EARG; } } @@ -231,8 +284,8 @@ public class MonkeySourceNetwork implements MonkeyEventSource { */ private static class TypeCommand implements MonkeyCommand { // wake - public MonkeyEvent translateCommand(List<String> command, - CommandQueue queue) { + public MonkeyCommandReturn translateCommand(List<String> command, + CommandQueue queue) { if (command.size() == 2) { String str = command.get(1); @@ -248,9 +301,9 @@ public class MonkeySourceNetwork implements MonkeyEventSource { for (KeyEvent event : events) { queue.enqueueEvent(new MonkeyKeyEvent(event)); } - return new MonkeyNoopEvent(); + return OK; } - return null; + return EARG; } } @@ -259,12 +312,12 @@ public class MonkeySourceNetwork implements MonkeyEventSource { */ private static class WakeCommand implements MonkeyCommand { // wake - public MonkeyEvent translateCommand(List<String> command, - CommandQueue queue) { + public MonkeyCommandReturn translateCommand(List<String> command, + CommandQueue queue) { if (!wake()) { - return null; + return ERROR; } - return new MonkeyNoopEvent(); + return OK; } } @@ -274,8 +327,8 @@ public class MonkeySourceNetwork implements MonkeyEventSource { */ private static class TapCommand implements MonkeyCommand { // tap x y - public MonkeyEvent translateCommand(List<String> command, - CommandQueue queue) { + public MonkeyCommandReturn translateCommand(List<String> command, + CommandQueue queue) { if (command.size() == 3) { int x = 0; int y = 0; @@ -285,7 +338,7 @@ public class MonkeySourceNetwork implements MonkeyEventSource { } catch (NumberFormatException e) { // Ok, it wasn't a number Log.e(TAG, "Got something that wasn't a number", e); - return null; + return EARG; } queue.enqueueEvent(new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER, @@ -294,9 +347,9 @@ public class MonkeySourceNetwork implements MonkeyEventSource { queue.enqueueEvent(new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER, -1, MotionEvent.ACTION_UP, x, y, 0)); - return new MonkeyNoopEvent(); + return OK; } - return null; + return EARG; } } @@ -305,22 +358,22 @@ public class MonkeySourceNetwork implements MonkeyEventSource { */ private static class PressCommand implements MonkeyCommand { // press keycode - public MonkeyEvent translateCommand(List<String> command, - CommandQueue queue) { + public MonkeyCommandReturn translateCommand(List<String> command, + CommandQueue queue) { if (command.size() == 2) { int keyCode = getKeyCode(command.get(1)); if (keyCode < 0) { // Ok, you gave us something bad. Log.e(TAG, "Can't find keyname: " + command.get(1)); - return null; + return EARG; } queue.enqueueEvent(new MonkeyKeyEvent(KeyEvent.ACTION_DOWN, keyCode)); queue.enqueueEvent(new MonkeyKeyEvent(KeyEvent.ACTION_UP, keyCode)); - return new MonkeyNoopEvent(); + return OK; } - return null; + return EARG; } } @@ -355,6 +408,8 @@ public class MonkeySourceNetwork implements MonkeyEventSource { COMMAND_MAP.put("tap", new TapCommand()); COMMAND_MAP.put("press", new PressCommand()); COMMAND_MAP.put("type", new TypeCommand()); + COMMAND_MAP.put("listvar", new MonkeySourceNetworkVars.ListVarCommand()); + COMMAND_MAP.put("getvar", new MonkeySourceNetworkVars.GetVarCommand()); } // QUIT command @@ -363,10 +418,10 @@ public class MonkeySourceNetwork implements MonkeyEventSource { private static final String DONE = "done"; // command response strings - private static final String OK = "OK"; - private static final String ERROR = "ERROR"; + private static final String OK_STR = "OK"; + private static final String ERROR_STR = "ERROR"; - private static interface CommandQueue { + public static interface CommandQueue { /** * Enqueue an event to be returned later. This allows a * command to return multiple events. Commands using the @@ -499,21 +554,30 @@ public class MonkeySourceNetwork implements MonkeyEventSource { * Translate the given command line into a MonkeyEvent. * * @param commandLine the full command line given. - * @returns the MonkeyEvent corresponding to the command, or null - * if there was an issue. */ - private MonkeyEvent translateCommand(String commandLine) { + private void translateCommand(String commandLine) { Log.d(TAG, "translateCommand: " + commandLine); List<String> parts = commandLineSplit(commandLine); if (parts.size() > 0) { MonkeyCommand command = COMMAND_MAP.get(parts.get(0)); if (command != null) { - return command.translateCommand(parts, - commandQueue); + MonkeyCommandReturn ret = command.translateCommand(parts, + commandQueue); + if (ret.wasSuccessful()) { + if (ret.hasMessage()) { + returnOk(ret.getMessage()); + } else { + returnOk(); + } + } else { + if (ret.hasMessage()) { + returnError(ret.getMessage()); + } else { + returnError(); + } + } } - return null; } - return null; } public MonkeyEvent getNextEvent() { @@ -548,16 +612,16 @@ public class MonkeySourceNetwork implements MonkeyEventSource { } if (DONE.equals(command)) { - // stop the server so it can accept new connections + // stop the server so it can accept new connections try { stopServer(); } catch (IOException e) { Log.e(TAG, "Got IOException shutting down!", e); return null; } - // return a noop event so we keep executing the main - // loop - return new MonkeyNoopEvent(); + // return a noop event so we keep executing the main + // loop + return new MonkeyNoopEvent(); } // Do quit checking here @@ -565,7 +629,7 @@ public class MonkeySourceNetwork implements MonkeyEventSource { // then we're done Log.d(TAG, "Quit requested"); // let the host know the command ran OK - output.println(OK); + returnOk(); return null; } @@ -573,20 +637,12 @@ public class MonkeySourceNetwork implements MonkeyEventSource { // command, so we don't echo anything back to the // user. if (command.startsWith("#")) { - // keep going - continue; + // keep going + continue; } - // Translate the command line - MonkeyEvent event = translateCommand(command); - if (event != null) { - // let the host know the command ran OK - output.println(OK); - return event; - } - // keep going. maybe the next command will make more sense - Log.e(TAG, "Got unknown command! \"" + command + "\""); - output.println(ERROR); + // Translate the command line. This will handle returning error/ok to the user + translateCommand(command); } } catch (IOException e) { Log.e(TAG, "Exception: ", e); @@ -594,6 +650,42 @@ public class MonkeySourceNetwork implements MonkeyEventSource { } } + /** + * Returns ERROR to the user. + */ + private void returnError() { + output.println(ERROR_STR); + } + + /** + * Returns ERROR to the user. + * + * @param msg the error message to include + */ + private void returnError(String msg) { + output.print(ERROR_STR); + output.print(":"); + output.println(msg); + } + + /** + * Returns OK to the user. + */ + private void returnOk() { + output.println(OK_STR); + } + + /** + * Returns OK to the user. + * + * @param returnValue the value to return from this command. + */ + private void returnOk(String returnValue) { + output.print(OK_STR); + output.print(":"); + output.println(returnValue); + } + public void setVerbose(int verbose) { // We're not particualy verbose } diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceNetworkVars.java b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceNetworkVars.java new file mode 100644 index 000000000..e9890ad2b --- /dev/null +++ b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceNetworkVars.java @@ -0,0 +1,197 @@ +/* + * Copyright 2009, 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 com.android.commands.monkey; + +import android.os.Build; +import android.os.SystemClock; +import android.view.Display; +import android.view.WindowManagerImpl; +import android.util.DisplayMetrics; + +import com.android.commands.monkey.MonkeySourceNetwork.CommandQueue; +import com.android.commands.monkey.MonkeySourceNetwork.MonkeyCommand; +import com.android.commands.monkey.MonkeySourceNetwork.MonkeyCommandReturn; + +import java.lang.Integer; +import java.lang.Float; +import java.lang.Long; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +public class MonkeySourceNetworkVars { + /** + * Interface to get the value of a var. + */ + private static interface VarGetter { + /** + * Get the value of the var. + * @returns the value of the var. + */ + public String get(); + } + + private static class StaticVarGetter implements VarGetter { + private final String value; + + public StaticVarGetter(String value) { + this.value = value; + } + + public String get() { + return value; + } + } + + // Use a TreeMap to keep the keys sorted so they get displayed nicely in listvar + private static final Map<String, VarGetter> VAR_MAP = new TreeMap<String, VarGetter>(); + + static { + VAR_MAP.put("build.board", new StaticVarGetter(Build.BOARD)); + VAR_MAP.put("build.brand", new StaticVarGetter(Build.BRAND)); + VAR_MAP.put("build.device", new StaticVarGetter(Build.DEVICE)); + VAR_MAP.put("build.display", new StaticVarGetter(Build.DISPLAY)); + VAR_MAP.put("build.fingerprint", new StaticVarGetter(Build.FINGERPRINT)); + VAR_MAP.put("build.host", new StaticVarGetter(Build.HOST)); + VAR_MAP.put("build.id", new StaticVarGetter(Build.ID)); + VAR_MAP.put("build.model", new StaticVarGetter(Build.MODEL)); + VAR_MAP.put("build.product", new StaticVarGetter(Build.PRODUCT)); + VAR_MAP.put("build.tags", new StaticVarGetter(Build.TAGS)); + VAR_MAP.put("build.brand", new StaticVarGetter(Long.toString(Build.TIME))); + VAR_MAP.put("build.type", new StaticVarGetter(Build.TYPE)); + VAR_MAP.put("build.user", new StaticVarGetter(Build.USER)); + VAR_MAP.put("build.cpu_abi", new StaticVarGetter(Build.CPU_ABI)); + VAR_MAP.put("build.manufacturer", new StaticVarGetter(Build.MANUFACTURER)); + VAR_MAP.put("build.version.incremental", new StaticVarGetter(Build.VERSION.INCREMENTAL)); + VAR_MAP.put("build.version.release", new StaticVarGetter(Build.VERSION.RELEASE)); + VAR_MAP.put("build.version.sdk", new StaticVarGetter(Integer.toString(Build.VERSION.SDK_INT))); + VAR_MAP.put("build.version.codename", new StaticVarGetter(Build.VERSION.CODENAME)); + + // Display + Display display = WindowManagerImpl.getDefault().getDefaultDisplay(); + VAR_MAP.put("display.width", new StaticVarGetter(Integer.toString(display.getWidth()))); + VAR_MAP.put("display.height", new StaticVarGetter(Integer.toString(display.getHeight()))); + + DisplayMetrics dm = new DisplayMetrics(); + display.getMetrics(dm); + VAR_MAP.put("display.density", new StaticVarGetter(Float.toString(dm.density))); + + // am. note that the current activity information isn't valid + // until the first activity gets launched after the monkey has + // been started. + VAR_MAP.put("am.current.package", new VarGetter() { + public String get() { + return Monkey.currentPackage; + } + }); + VAR_MAP.put("am.current.action", new VarGetter() { + public String get() { + if (Monkey.currentIntent == null) { + return null; + } + return Monkey.currentIntent.getAction(); + } + }); + VAR_MAP.put("am.current.comp.class", new VarGetter() { + public String get() { + if (Monkey.currentIntent == null) { + return null; + } + return Monkey.currentIntent.getComponent().getClassName(); + } + }); + VAR_MAP.put("am.current.comp.package", new VarGetter() { + public String get() { + if (Monkey.currentIntent == null) { + return null; + } + return Monkey.currentIntent.getComponent().getPackageName(); + } + }); + VAR_MAP.put("am.current.data", new VarGetter() { + public String get() { + if (Monkey.currentIntent == null) { + return null; + } + return Monkey.currentIntent.getDataString(); + } + }); + VAR_MAP.put("am.current.categories", new VarGetter() { + public String get() { + if (Monkey.currentIntent == null) { + return null; + } + StringBuffer sb = new StringBuffer(); + for (String cat : Monkey.currentIntent.getCategories()) { + sb.append(cat).append(" "); + } + return sb.toString(); + } + }); + + // clock + VAR_MAP.put("clock.realtime", new VarGetter() { + public String get() { + return Long.toString(SystemClock.elapsedRealtime()); + } + }); + VAR_MAP.put("clock.uptime", new VarGetter() { + public String get() { + return Long.toString(SystemClock.uptimeMillis()); + } + }); + VAR_MAP.put("clock.millis", new VarGetter() { + public String get() { + return Long.toString(System.currentTimeMillis()); + } + }); + } + + /** + * Command to list the "vars" that the monkey knows about. + */ + public static class ListVarCommand implements MonkeySourceNetwork.MonkeyCommand { + // listvar + public MonkeyCommandReturn translateCommand(List<String> command, + CommandQueue queue) { + Set<String> keys = VAR_MAP.keySet(); + StringBuffer sb = new StringBuffer(); + for (String key : keys) { + sb.append(key).append(" "); + } + return new MonkeyCommandReturn(true, sb.toString()); + } + } + + /** + * Command to get the value of a var. + */ + public static class GetVarCommand implements MonkeyCommand { + // getvar varname + public MonkeyCommandReturn translateCommand(List<String> command, + CommandQueue queue) { + if (command.size() == 2) { + VarGetter getter = VAR_MAP.get(command.get(1)); + if (getter == null) { + return new MonkeyCommandReturn(false, "unknown var"); + } + return new MonkeyCommandReturn(true, getter.get()); + } + return MonkeySourceNetwork.EARG; + } + } +} |