diff --git a/cmds/monkey/src/com/android/commands/monkey/Monkey.java b/cmds/monkey/src/com/android/commands/monkey/Monkey.java index 838f274d3..431032362 100644 --- a/cmds/monkey/src/com/android/commands/monkey/Monkey.java +++ b/cmds/monkey/src/com/android/commands/monkey/Monkey.java @@ -144,8 +144,11 @@ public class Monkey { long mDroppedFlipEvents = 0; - /** a filename to the script (if any) **/ - private String mScriptFileName = null; + /** a filename to the setup script (if any) */ + private String mSetupFileName = null; + + /** filenames of the script (if any) */ + private ArrayList mScriptFileNames = new ArrayList(); /** a TCP port to listen on for remote commands. */ private int mServerPort = -1; @@ -398,11 +401,21 @@ public class Monkey { return -4; } - if (mScriptFileName != null) { + if (mScriptFileNames != null && mScriptFileNames.size() == 1) { // script mode, ignore other options - mEventSource = new MonkeySourceScript(mScriptFileName, mThrottle); + mEventSource = new MonkeySourceScript(mScriptFileNames.get(0), mThrottle); mEventSource.setVerbose(mVerbose); + mCountEvents = false; + } else if (mScriptFileNames != null) { + if (mSetupFileName != null) { + mEventSource = new MonkeySourceRandomScript(mSetupFileName, mScriptFileNames, + mThrottle, mSeed); + mCount++; + } else { + mEventSource = new MonkeySourceRandomScript(mScriptFileNames, mThrottle, mSeed); + } + mEventSource.setVerbose(mVerbose); mCountEvents = false; } else if (mServerPort != -1) { try { @@ -568,8 +581,10 @@ public class Monkey { mSendNoEvents = true; } else if (opt.equals("--port")) { mServerPort = (int) nextOptionLong("Server port to listen on for commands"); + } else if (opt.equals("--setup")) { + mSetupFileName = nextOptionData(); } else if (opt.equals("-f")) { - mScriptFileName = nextOptionData(); + mScriptFileNames.add(nextOptionData()); } else if (opt.equals("-h")) { showUsage(); return false; @@ -967,7 +982,8 @@ public class Monkey { usage.append(" [--pct-nav PERCENT] [--pct-majornav PERCENT]\n"); usage.append(" [--pct-appswitch PERCENT] [--pct-flip PERCENT]\n"); usage.append(" [--pct-anyevent PERCENT]\n"); - usage.append(" [--wait-dbg] [--dbg-no-events] [-f scriptfile]\n"); + usage.append(" [--wait-dbg] [--dbg-no-events]\n"); + usage.append(" [--setup scriptfile] [-f scriptfile [-f scriptfile] ...]\n"); usage.append(" [--port port]\n"); usage.append(" [-s SEED] [-v [-v] ...] [--throttle MILLISEC]\n"); usage.append(" COUNT"); diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandomScript.java b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandomScript.java new file mode 100644 index 000000000..a937398b2 --- /dev/null +++ b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandomScript.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2008 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 java.security.SecureRandom; +import java.util.ArrayList; + +/** + * Class for generating MonkeyEvents from multiple scripts. + */ +public class MonkeySourceRandomScript implements MonkeyEventSource { + /** The verbose level of the source (currently not used) */ + private int mVerbose = 0; + + /** The source for the setup script if it exists */ + private MonkeySourceScript mSetupSource = null; + + /** The list of MonkeySourceScript instances to be played in random order */ + private ArrayList mScriptSources = new ArrayList(); + + /** The current source, set to the setup source and then a random script */ + private MonkeySourceScript mCurrentSource = null; + + /** The random number generator */ + private SecureRandom mRandom; + + /** + * Creates a MonkeySourceRandomScript instance with an additional setup script. + * + * @param setupFileName The name of the setup script file on the device. + * @param scriptFileNames An ArrayList of the names of the script files to be run randomly. + * @param throttle The amount of time to sleep in ms between events. + * @param seed The seed of the random number generator. + */ + public MonkeySourceRandomScript(String setupFileName, ArrayList scriptFileNames, + long throttle, long seed) { + if (setupFileName != null) { + mSetupSource = new MonkeySourceScript(setupFileName, throttle); + mCurrentSource = mSetupSource; + } + + for (String fileName: scriptFileNames) { + mScriptSources.add(new MonkeySourceScript(fileName, throttle)); + } + + mRandom = new SecureRandom(); + mRandom.setSeed((seed == 0) ? -1 : seed); + } + + /** + * Creates a MonkeySourceRandomScript instance without an additional setup script. + * + * @param scriptFileNames An ArrayList of the names of the script files to be run randomly. + * @param throttle The amount of time to sleep in ms between events. + * @param seed The seed of the random number generator. + */ + public MonkeySourceRandomScript(ArrayList scriptFileNames, long throttle, long seed) { + this(null, scriptFileNames, throttle, seed); + } + + /** + * Gets the next event from the current event source. If the event source is null, a new + * script event source is chosen randomly from the list of script sources and the next event is + * chosen from that. + * + * @return The first event in the event queue or null if the end of the file + * is reached or if an error is encountered reading the file. + */ + public MonkeyEvent getNextEvent() { + if (mCurrentSource == null) { + int numSources = mScriptSources.size(); + if (numSources == 1) { + mCurrentSource = mScriptSources.get(0); + } else if (numSources > 1) { + mCurrentSource = mScriptSources.get(mRandom.nextInt(numSources)); + } + } + + if (mCurrentSource != null) { + MonkeyEvent nextEvent = mCurrentSource.getNextEvent(); + if (nextEvent == null) { + mCurrentSource = null; + } + return nextEvent; + } + return null; + } + + /** + * Sets the verbosity for the source as well as all sub event sources. + * + * @param verbose The verbose level. + */ + public void setVerbose(int verbose) { + mVerbose = verbose; + + if (mSetupSource != null) { + mSetupSource.setVerbose(verbose); + } + + for (MonkeySourceScript source: mScriptSources) { + source.setVerbose(verbose); + } + } + + /** + * Validates that all the underlying event sources are valid + * + * @return True if all the script files are valid. + * + * @see MonkeySourceScript#validate() + */ + public boolean validate() { + if (mSetupSource != null && !mSetupSource.validate()) { + return false; + } + + for (MonkeySourceScript source: mScriptSources) { + if (!source.validate()) { + return false; + } + } + + return true; + } +}