diff options
| author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:16 -0800 |
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:16 -0800 |
| commit | d4aee0c0caa00aa02d4c50ed28151591ac0456b5 (patch) | |
| tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /cmds | |
| parent | d2f2b1d7b77d06bce8cf9340171cf6c25cd720c4 (diff) | |
| download | android_development-d4aee0c0caa00aa02d4c50ed28151591ac0456b5.tar.gz android_development-d4aee0c0caa00aa02d4c50ed28151591ac0456b5.tar.bz2 android_development-d4aee0c0caa00aa02d4c50ed28151591ac0456b5.zip | |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'cmds')
| -rw-r--r-- | cmds/monkey/Android.mk | 13 | ||||
| -rw-r--r-- | cmds/monkey/MODULE_LICENSE_APACHE2 | 0 | ||||
| -rw-r--r-- | cmds/monkey/NOTICE | 190 | ||||
| -rwxr-xr-x | cmds/monkey/monkey | 7 | ||||
| -rw-r--r-- | cmds/monkey/src/com/android/commands/monkey/Monkey.java | 906 | ||||
| -rw-r--r-- | cmds/monkey/src/com/android/commands/monkey/MonkeyActivityEvent.java | 68 | ||||
| -rw-r--r-- | cmds/monkey/src/com/android/commands/monkey/MonkeyEvent.java | 61 | ||||
| -rw-r--r-- | cmds/monkey/src/com/android/commands/monkey/MonkeyEventSource.java | 41 | ||||
| -rw-r--r-- | cmds/monkey/src/com/android/commands/monkey/MonkeyFlipEvent.java | 76 | ||||
| -rw-r--r-- | cmds/monkey/src/com/android/commands/monkey/MonkeyKeyEvent.java | 125 | ||||
| -rw-r--r-- | cmds/monkey/src/com/android/commands/monkey/MonkeyMotionEvent.java | 156 | ||||
| -rw-r--r-- | cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java | 467 | ||||
| -rw-r--r-- | cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java | 427 |
13 files changed, 0 insertions, 2537 deletions
diff --git a/cmds/monkey/Android.mk b/cmds/monkey/Android.mk deleted file mode 100644 index 6bedc43e8..000000000 --- a/cmds/monkey/Android.mk +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2008 The Android Open Source Project -# -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := $(call all-subdir-java-files) -LOCAL_MODULE := monkey -include $(BUILD_JAVA_LIBRARY) - -include $(CLEAR_VARS) -ALL_PREBUILT += $(TARGET_OUT)/bin/monkey -$(TARGET_OUT)/bin/monkey : $(LOCAL_PATH)/monkey | $(ACP) - $(transform-prebuilt-to-target) diff --git a/cmds/monkey/MODULE_LICENSE_APACHE2 b/cmds/monkey/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29bb..000000000 --- a/cmds/monkey/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/cmds/monkey/NOTICE b/cmds/monkey/NOTICE deleted file mode 100644 index c5b1efa7a..000000000 --- a/cmds/monkey/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-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. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/cmds/monkey/monkey b/cmds/monkey/monkey deleted file mode 100755 index 45f43a45c..000000000 --- a/cmds/monkey/monkey +++ /dev/null @@ -1,7 +0,0 @@ -# Script to start "monkey" on the device, which has a very rudimentary -# shell. -# -base=/system -export CLASSPATH=$base/framework/monkey.jar -exec app_process $base/bin com.android.commands.monkey.Monkey $* - diff --git a/cmds/monkey/src/com/android/commands/monkey/Monkey.java b/cmds/monkey/src/com/android/commands/monkey/Monkey.java deleted file mode 100644 index f6ab19d73..000000000 --- a/cmds/monkey/src/com/android/commands/monkey/Monkey.java +++ /dev/null @@ -1,906 +0,0 @@ -/** -** Copyright 2007, 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.app.ActivityManagerNative; -import android.app.IActivityManager; -import android.app.IActivityWatcher; -import android.content.ComponentName; -import android.content.Intent; -import android.content.pm.IPackageManager; -import android.content.pm.ResolveInfo; -import android.os.Debug; -import android.os.Process; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.server.data.CrashData; -import android.view.IWindowManager; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; - -/** - * Application that injects random key events and other actions into the system. - */ -public class Monkey { - - /** - * Monkey Debugging/Dev Support - * - * All values should be zero when checking in. - */ - private final static int DEBUG_ALLOW_ANY_STARTS = 0; - private final static int DEBUG_ALLOW_ANY_RESTARTS = 0; - private IActivityManager mAm; - private IWindowManager mWm; - private IPackageManager mPm; - - /** Command line arguments */ - private String[] mArgs; - /** Current argument being parsed */ - private int mNextArg; - /** Data of current argument */ - private String mCurArgData; - - /** Running in verbose output mode? 1= verbose, 2=very verbose */ - private int mVerbose; - - /** Ignore any application crashes while running? */ - private boolean mIgnoreCrashes; - - /** Ignore any not responding timeouts while running? */ - private boolean mIgnoreTimeouts; - - /** Ignore security exceptions when launching activities */ - /** (The activity launch still fails, but we keep pluggin' away) */ - private boolean mIgnoreSecurityExceptions; - - /** Monitor /data/tombstones and stop the monkey if new files appear. */ - private boolean mMonitorNativeCrashes; - - /** Send no events. Use with long throttle-time to watch user operations */ - private boolean mSendNoEvents; - - /** This is set when we would like to abort the running of the monkey. */ - private boolean mAbort; - - /** This is set by the ActivityWatcher thread to request collection of ANR trace files */ - private boolean mRequestAnrTraces = false; - - /** This is set by the ActivityWatcher thread to request a "dumpsys meminfo" */ - private boolean mRequestDumpsysMemInfo = false; - - /** Kill the process after a timeout or crash. */ - private boolean mKillProcessAfterError; - - /** Generate hprof reports before/after monkey runs */ - private boolean mGenerateHprof; - - /** Packages we are allowed to run, or empty if no restriction. */ - private HashSet<String> mValidPackages = new HashSet<String>(); - /** Categories we are allowed to launch **/ - ArrayList<String> mMainCategories = new ArrayList<String>(); - /** Applications we can switch to. */ - private ArrayList<ComponentName> mMainApps = new ArrayList<ComponentName>(); - - /** The delay between event inputs **/ - long mThrottle = 0; - - /** The number of iterations **/ - int mCount = 1000; - - /** The random number seed **/ - long mSeed = 0; - - /** Dropped-event statistics **/ - long mDroppedKeyEvents = 0; - long mDroppedPointerEvents = 0; - long mDroppedTrackballEvents = 0; - long mDroppedFlipEvents = 0; - - /** a filename to the script (if any) **/ - private String mScriptFileName = null; - - private static final File TOMBSTONES_PATH = new File("/data/tombstones"); - private HashSet<String> mTombstones = null; - - float[] mFactors = new float[MonkeySourceRandom.FACTORZ_COUNT]; - MonkeyEventSource mEventSource; - - /** - * Monitor operations happening in the system. - */ - private class ActivityWatcher extends IActivityWatcher.Stub { - public boolean activityStarting(Intent intent, String pkg) { - boolean allow = checkEnteringPackage(pkg) || (DEBUG_ALLOW_ANY_STARTS != 0); - if (mVerbose > 0) { - System.out.println(" // " + (allow ? "Allowing" : "Rejecting") - + " start of " + intent + " in package " + pkg); - } - return allow; - } - - public boolean activityResuming(String pkg) { - System.out.println(" // activityResuming(" + pkg + ")"); - boolean allow = checkEnteringPackage(pkg) || (DEBUG_ALLOW_ANY_RESTARTS != 0); - if (!allow) { - if (mVerbose > 0) { - System.out.println(" // " + (allow ? "Allowing" : "Rejecting") - + " resume of package " + pkg); - } - } - return allow; - } - - private boolean checkEnteringPackage(String pkg) { - if (pkg == null) { - return true; - } - // preflight the hash lookup to avoid the cost of hash key generation - if (mValidPackages.size() == 0) { - return true; - } else { - return mValidPackages.contains(pkg); - } - } - - public boolean appCrashed(String processName, int pid, String shortMsg, - String longMsg, byte[] crashData) { - System.err.println("// CRASH: " + processName + " (pid " + pid - + ")"); - System.err.println("// Short Msg: " + shortMsg); - System.err.println("// Long Msg: " + longMsg); - if (crashData != null) { - try { - CrashData cd = new CrashData(new DataInputStream( - new ByteArrayInputStream(crashData))); - System.err.println("// Build Label: " - + cd.getBuildData().getFingerprint()); - System.err.println("// Build Changelist: " - + cd.getBuildData().getIncrementalVersion()); - System.err.println("// Build Time: " - + cd.getBuildData().getTime()); - System.err.println("// ID: " + cd.getId()); - System.err.println("// Tag: " + cd.getActivity()); - System.err.println(cd.getThrowableData().toString( - "// ")); - } catch (IOException e) { - System.err.println("// BAD STACK CRAWL"); - } - } - - if (!mIgnoreCrashes) { - synchronized (Monkey.this) { - mAbort = true; - } - - return !mKillProcessAfterError; - } - return false; - } - - public int appNotResponding(String processName, int pid, - String processStats) { - System.err.println("// NOT RESPONDING: " + processName - + " (pid " + pid + ")"); - System.err.println(processStats); - reportProcRank(); - synchronized (Monkey.this) { - mRequestAnrTraces = true; - mRequestDumpsysMemInfo = true; - } - if (!mIgnoreTimeouts) { - synchronized (Monkey.this) { - mAbort = true; - } - return (mKillProcessAfterError) ? -1 : 1; - } - return 1; - } - } - - /** - * Run the procrank tool to insert system status information into the debug report. - */ - private void reportProcRank() { - commandLineReport("procrank", "procrank"); - } - - /** - * Run "cat /data/anr/traces.txt". Wait about 5 seconds first, to let the asynchronous - * report writing complete. - */ - private void reportAnrTraces() { - try { - Thread.sleep(5 * 1000); - } catch (InterruptedException e) { - } - commandLineReport("anr traces", "cat /data/anr/traces.txt"); - } - - /** - * Run "dumpsys meminfo" - * - * NOTE: You cannot perform a dumpsys call from the ActivityWatcher callback, as it will - * deadlock. This should only be called from the main loop of the monkey. - */ - private void reportDumpsysMemInfo() { - commandLineReport("meminfo", "dumpsys meminfo"); - } - - /** - * Print report from a single command line. - * @param reportName Simple tag that will print before the report and in various annotations. - * @param command Command line to execute. - * TODO: Use ProcessBuilder & redirectErrorStream(true) to capture both streams (might be - * important for some command lines) - */ - private void commandLineReport(String reportName, String command) { - System.err.println(reportName + ":"); - Runtime rt = Runtime.getRuntime(); - try { - // Process must be fully qualified here because android.os.Process is used elsewhere - java.lang.Process p = Runtime.getRuntime().exec(command); - - // pipe everything from process stdout -> System.err - InputStream inStream = p.getInputStream(); - InputStreamReader inReader = new InputStreamReader(inStream); - BufferedReader inBuffer = new BufferedReader(inReader); - String s; - while ((s = inBuffer.readLine()) != null) { - System.err.println(s); - } - - int status = p.waitFor(); - System.err.println("// " + reportName + " status was " + status); - } catch (Exception e) { - System.err.println("// Exception from " + reportName + ":"); - System.err.println(e.toString()); - } - } - - /** - * Command-line entry point. - * - * @param args The command-line arguments - */ - public static void main(String[] args) { - int resultCode = (new Monkey()).run(args); - System.exit(resultCode); - } - - /** - * Run the command! - * - * @param args The command-line arguments - * @return Returns a posix-style result code. 0 for no error. - */ - private int run(String[] args) { - // Super-early debugger wait - for (String s : args) { - if ("--wait-dbg".equals(s)) { - Debug.waitForDebugger(); - } - } - - // Default values for some command-line options - mVerbose = 0; - mCount = 1000; - mSeed = 0; - mThrottle = 0; - - // prepare for command-line processing - mArgs = args; - mNextArg = 0; - - //set a positive value, indicating none of the factors is provided yet - for (int i = 0; i < MonkeySourceRandom.FACTORZ_COUNT; i++) { - mFactors[i] = 1.0f; - } - - if (!processOptions()) { - return -1; - } - - // now set up additional data in preparation for launch - if (mMainCategories.size() == 0) { - mMainCategories.add(Intent.CATEGORY_LAUNCHER); - mMainCategories.add(Intent.CATEGORY_MONKEY); - } - - if (mVerbose > 0) { - System.out.println(":Monkey: seed=" + mSeed + " count=" + mCount); - if (mValidPackages.size() > 0) { - Iterator<String> it = mValidPackages.iterator(); - while (it.hasNext()) { - System.out.println(":AllowPackage: " + it.next()); - } - } - if (mMainCategories.size() != 0) { - Iterator<String> it = mMainCategories.iterator(); - while (it.hasNext()) { - System.out.println(":IncludeCategory: " + it.next()); - } - } - } - - if (!checkInternalConfiguration()) { - return -2; - } - - if (!getSystemInterfaces()) { - return -3; - } - - if (!getMainApps()) { - return -4; - } - - if (mScriptFileName != null) { - // script mode, ignore other options - mEventSource = new MonkeySourceScript(mScriptFileName); - mEventSource.setVerbose(mVerbose); - } else { - // random source by default - if (mVerbose >= 2) { // check seeding performance - System.out.println("// Seeded: " + mSeed); - } - mEventSource = new MonkeySourceRandom(mSeed, mMainApps); - mEventSource.setVerbose(mVerbose); - //set any of the factors that has been set - for (int i = 0; i < MonkeySourceRandom.FACTORZ_COUNT; i++) { - if (mFactors[i] <= 0.0f) { - ((MonkeySourceRandom) mEventSource).setFactors(i, mFactors[i]); - } - } - - //in random mode, we start with a random activity - ((MonkeySourceRandom) mEventSource).generateActivity(); - } - - //validate source generator - if (!mEventSource.validate()) { - return -5; - } - - if (mScriptFileName != null) { - // in random mode, count is the number of single events - // while in script mode, count is the number of repetition - // for a sequence of events, so we need do multiply the length of - // that sequence - mCount = mCount * ((MonkeySourceScript) mEventSource) - .getOneRoundEventCount(); - } - - // If we're profiling, do it immediately before/after the main monkey loop - if (mGenerateHprof) { - signalPersistentProcesses(); - } - - int crashedAtCycle = runMonkeyCycles(); - - synchronized (this) { - if (mRequestAnrTraces) { - reportAnrTraces(); - mRequestAnrTraces = false; - } - if (mRequestDumpsysMemInfo) { - reportDumpsysMemInfo(); - mRequestDumpsysMemInfo = false; - } - } - - if (mGenerateHprof) { - signalPersistentProcesses(); - if (mVerbose > 0) { - System.out.println("// Generated profiling reports in /data/misc"); - } - } - - try { - mAm.setActivityWatcher(null); - } catch (RemoteException e) { - // just in case this was latent (after mCount cycles), make sure - // we report it - if (crashedAtCycle >= mCount) { - crashedAtCycle = mCount - 1; - } - } - - // report dropped event stats - if (mVerbose > 0) { - System.out.print(":Dropped: keys="); - System.out.print(mDroppedKeyEvents); - System.out.print(" pointers="); - System.out.print(mDroppedPointerEvents); - System.out.print(" trackballs="); - System.out.print(mDroppedTrackballEvents); - System.out.print(" flips="); - System.out.println(mDroppedFlipEvents); - } - - if (crashedAtCycle < mCount - 1) { - System.err.println("** System appears to have crashed at event " - + crashedAtCycle + " of " + mCount + " using seed " + mSeed); - return crashedAtCycle; - } else { - if (mVerbose > 0) { - System.out.println("// Monkey finished"); - } - return 0; - } - } - - /** - * Process the command-line options - * - * @return Returns true if options were parsed with no apparent errors. - */ - private boolean processOptions() { - // quick (throwaway) check for unadorned command - if (mArgs.length < 1) { - showUsage(); - return false; - } - - try { - String opt; - while ((opt = nextOption()) != null) { - if (opt.equals("-s")) { - mSeed = nextOptionLong("Seed"); - } else if (opt.equals("-p")) { - mValidPackages.add(nextOptionData()); - } else if (opt.equals("-c")) { - mMainCategories.add(nextOptionData()); - } else if (opt.equals("-v")) { - mVerbose += 1; - } else if (opt.equals("--ignore-crashes")) { - mIgnoreCrashes = true; - } else if (opt.equals("--ignore-timeouts")) { - mIgnoreTimeouts = true; - } else if (opt.equals("--ignore-security-exceptions")) { - mIgnoreSecurityExceptions = true; - } else if (opt.equals("--monitor-native-crashes")) { - mMonitorNativeCrashes = true; - } else if (opt.equals("--kill-process-after-error")) { - mKillProcessAfterError = true; - } else if (opt.equals("--hprof")) { - mGenerateHprof = true; - } else if (opt.equals("--pct-touch")) { - mFactors[MonkeySourceRandom.FACTOR_TOUCH] = - -nextOptionLong("touch events percentage"); - } else if (opt.equals("--pct-motion")) { - mFactors[MonkeySourceRandom.FACTOR_MOTION] = - -nextOptionLong("motion events percentage"); - } else if (opt.equals("--pct-trackball")) { - mFactors[MonkeySourceRandom.FACTOR_TRACKBALL] = - -nextOptionLong("trackball events percentage"); - } else if (opt.equals("--pct-nav")) { - mFactors[MonkeySourceRandom.FACTOR_NAV] = - -nextOptionLong("nav events percentage"); - } else if (opt.equals("--pct-majornav")) { - mFactors[MonkeySourceRandom.FACTOR_MAJORNAV] = - -nextOptionLong("major nav events percentage"); - } else if (opt.equals("--pct-appswitch")) { - mFactors[MonkeySourceRandom.FACTOR_APPSWITCH] = - -nextOptionLong("app switch events percentage"); - } else if (opt.equals("--pct-flip")) { - mFactors[MonkeySourceRandom.FACTOR_FLIP] = - -nextOptionLong("keyboard flip percentage"); - } else if (opt.equals("--pct-anyevent")) { - mFactors[MonkeySourceRandom.FACTOR_ANYTHING] = - -nextOptionLong("any events percentage"); - } else if (opt.equals("--throttle")) { - mThrottle = nextOptionLong("delay (in milliseconds) to wait between events"); - } else if (opt.equals("--wait-dbg")) { - // do nothing - it's caught at the very start of run() - } else if (opt.equals("--dbg-no-events")) { - mSendNoEvents = true; - } else if (opt.equals("-f")) { - mScriptFileName = nextOptionData(); - } else if (opt.equals("-h")) { - showUsage(); - return false; - } else { - System.err.println("** Error: Unknown option: " + opt); - showUsage(); - return false; - } - } - } catch (RuntimeException ex) { - System.err.println("** Error: " + ex.toString()); - showUsage(); - return false; - } - - String countStr = nextArg(); - if (countStr == null) { - System.err.println("** Error: Count not specified"); - showUsage(); - return false; - } - - try { - mCount = Integer.parseInt(countStr); - } catch (NumberFormatException e) { - System.err.println("** Error: Count is not a number"); - showUsage(); - return false; - } - - return true; - } - - /** - * Check for any internal configuration (primarily build-time) errors. - * - * @return Returns true if ready to rock. - */ - private boolean checkInternalConfiguration() { - // Check KEYCODE name array, make sure it's up to date. - - String lastKeyName = null; - try { - lastKeyName = MonkeySourceRandom.getLastKeyName(); - } catch (RuntimeException e) { - } - if (!"TAG_LAST_KEYCODE".equals(lastKeyName)) { - System.err.println("** Error: Key names array malformed (internal error)."); - return false; - } - - return true; - } - - /** - * Attach to the required system interfaces. - * - * @return Returns true if all system interfaces were available. - */ - private boolean getSystemInterfaces() { - mAm = ActivityManagerNative.getDefault(); - if (mAm == null) { - System.err.println("** Error: Unable to connect to activity manager; is the system running?"); - return false; - } - - mWm = IWindowManager.Stub.asInterface(ServiceManager.getService("window")); - if (mWm == null) { - System.err.println("** Error: Unable to connect to window manager; is the system running?"); - return false; - } - - mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); - if (mPm == null) { - System.err.println("** Error: Unable to connect to package manager; is the system running?"); - return false; - } - - try { - mAm.setActivityWatcher(new ActivityWatcher()); - } catch (RemoteException e) { - System.err.println("** Failed talking with activity manager!"); - return false; - } - - return true; - } - - /** - * Using the restrictions provided (categories & packages), generate a list of activities - * that we can actually switch to. - * - * @return Returns true if it could successfully build a list of target activities - */ - private boolean getMainApps() { - try { - final int N = mMainCategories.size(); - for (int i = 0; i< N; i++) { - Intent intent = new Intent(Intent.ACTION_MAIN); - String category = mMainCategories.get(i); - if (category.length() > 0) { - intent.addCategory(category); - } - List<ResolveInfo> mainApps = mPm.queryIntentActivities(intent, null, 0); - if (mainApps == null || mainApps.size() == 0) { - System.err.println("// Warning: no activities found for category " + category); - continue; - } - if (mVerbose >= 2) { // very verbose - System.out.println("// Selecting main activities from category " + category); - } - final int NA = mainApps.size(); - for (int a = 0; a < NA; a++) { - ResolveInfo r = mainApps.get(a); - if (mValidPackages.size() == 0 || - mValidPackages.contains(r.activityInfo.applicationInfo.packageName)) { - if (mVerbose >= 2) { // very verbose - System.out.println("// + Using main activity " - + r.activityInfo.name - + " (from package " - + r.activityInfo.applicationInfo.packageName - + ")"); - } - mMainApps.add(new ComponentName( - r.activityInfo.applicationInfo.packageName, - r.activityInfo.name)); - } else { - if (mVerbose >= 3) { // very very verbose - System.out.println("// - NOT USING main activity " - + r.activityInfo.name - + " (from package " - + r.activityInfo.applicationInfo.packageName - + ")"); - } - } - } - } - } catch (RemoteException e) { - System.err.println("** Failed talking with package manager!"); - return false; - } - - if (mMainApps.size() == 0) { - System.out.println("** No activities found to run, monkey aborted."); - return false; - } - - return true; - } - - /** - * Run mCount cycles and see if we hit any crashers. - * - * TODO: Meta state on keys - * - * @return Returns the last cycle which executed. If the value == mCount, no errors detected. - */ - private int runMonkeyCycles() { - int i = 0; - int lastKey = 0; - - boolean systemCrashed = false; - - while (!systemCrashed && i < mCount) { - synchronized (this) { - if (mRequestAnrTraces) { - reportAnrTraces(); - mRequestAnrTraces = false; - } - if (mRequestDumpsysMemInfo) { - reportDumpsysMemInfo(); - mRequestDumpsysMemInfo = false; - } - if (mMonitorNativeCrashes) { - // first time through, when i == 0, just set up the watcher (ignore the error) - if (checkNativeCrashes() && (i > 0)) { - System.out.println("** New native crash detected."); - mAbort = mAbort || mKillProcessAfterError; - } - } - if (mAbort) { - System.out.println("** Monkey aborted due to error."); - System.out.println("Events injected: " + i); - return i; - } - } - - try { - Thread.sleep(mThrottle); - } catch (InterruptedException e1) { - System.out.println("** Monkey interrupted in sleep."); - return i; - } - - // In this debugging mode, we never send any events. This is primarily - // here so you can manually test the package or category limits, while manually - // exercising the system. - if (mSendNoEvents) { - i++; - continue; - } - - if ((mVerbose > 0) && (i % 100) == 0 && i != 0 && lastKey == 0) { - System.out.println(" // Sending event #" + i); - } - - MonkeyEvent ev = mEventSource.getNextEvent(); - if (ev != null) { - i++; - int injectCode = ev.injectEvent(mWm, mAm, mVerbose); - if (injectCode == MonkeyEvent.INJECT_FAIL) { - if (ev instanceof MonkeyKeyEvent) { - mDroppedKeyEvents++; - } else if (ev instanceof MonkeyMotionEvent) { - mDroppedPointerEvents++; - } else if (ev instanceof MonkeyFlipEvent) { - mDroppedFlipEvents++; - } - } else if (injectCode == MonkeyEvent.INJECT_ERROR_REMOTE_EXCEPTION) { - systemCrashed = true; - } else if (injectCode == MonkeyEvent.INJECT_ERROR_SECURITY_EXCEPTION) { - systemCrashed = !mIgnoreSecurityExceptions; - } - } - } - - // If we got this far, we succeeded! - return mCount; - } - - /** - * Send SIGNAL_USR1 to all processes. This will generate large (5mb) profiling reports - * in data/misc, so use with care. - */ - private void signalPersistentProcesses() { - try { - mAm.signalPersistentProcesses(Process.SIGNAL_USR1); - - synchronized (this) { - wait(2000); - } - } catch (RemoteException e) { - System.err.println("** Failed talking with activity manager!"); - } catch (InterruptedException e) { - } - } - - /** - * Watch for appearance of new tombstone files, which indicate native crashes. - * - * @return Returns true if new files have appeared in the list - */ - private boolean checkNativeCrashes() { - String[] tombstones = TOMBSTONES_PATH.list(); - - // shortcut path for usually empty directory, so we don't waste even more objects - if ((tombstones == null) || (tombstones.length == 0)) { - mTombstones = null; - return false; - } - - // use set logic to look for new files - HashSet<String> newStones = new HashSet<String>(); - for (String x : tombstones) { - newStones.add(x); - } - - boolean result = (mTombstones == null) || !mTombstones.containsAll(newStones); - - // keep the new list for the next time - mTombstones = newStones; - - return result; - } - - /** - * Return the next command line option. This has a number of special cases which - * closely, but not exactly, follow the POSIX command line options patterns: - * - * -- means to stop processing additional options - * -z means option z - * -z ARGS means option z with (non-optional) arguments ARGS - * -zARGS means option z with (optional) arguments ARGS - * --zz means option zz - * --zz ARGS means option zz with (non-optional) arguments ARGS - * - * Note that you cannot combine single letter options; -abc != -a -b -c - * - * @return Returns the option string, or null if there are no more options. - */ - private String nextOption() { - if (mNextArg >= mArgs.length) { - return null; - } - String arg = mArgs[mNextArg]; - if (!arg.startsWith("-")) { - return null; - } - mNextArg++; - if (arg.equals("--")) { - return null; - } - if (arg.length() > 1 && arg.charAt(1) != '-') { - if (arg.length() > 2) { - mCurArgData = arg.substring(2); - return arg.substring(0, 2); - } else { - mCurArgData = null; - return arg; - } - } - mCurArgData = null; - return arg; - } - - /** - * Return the next data associated with the current option. - * - * @return Returns the data string, or null of there are no more arguments. - */ - private String nextOptionData() { - if (mCurArgData != null) { - return mCurArgData; - } - if (mNextArg >= mArgs.length) { - return null; - } - String data = mArgs[mNextArg]; - mNextArg++; - return data; - } - - /** - * Returns a long converted from the next data argument, with error handling if not available. - * - * @param opt The name of the option. - * @return Returns a long converted from the argument. - */ - private long nextOptionLong(final String opt) { - long result; - try { - result = Long.parseLong(nextOptionData()); - } catch (NumberFormatException e) { - System.err.println("** Error: " + opt + " is not a number"); - throw e; - } - return result; - } - - /** - * Return the next argument on the command line. - * - * @return Returns the argument string, or null if we have reached the end. - */ - private String nextArg() { - if (mNextArg >= mArgs.length) { - return null; - } - String arg = mArgs[mNextArg]; - mNextArg++; - return arg; - } - - /** - * Print how to use this command. - */ - private void showUsage() { - System.err.println("usage: monkey [-p ALLOWED_PACKAGE [-p ALLOWED_PACKAGE] ...]"); - System.err.println(" [-c MAIN_CATEGORY [-c MAIN_CATEGORY] ...]"); - System.err.println(" [--ignore-crashes] [--ignore-timeouts]"); - System.err.println(" [--ignore-security-exceptions] [--monitor-native-crashes]"); - System.err.println(" [--kill-process-after-error] [--hprof]"); - System.err.println(" [--pct-touch PERCENT] [--pct-motion PERCENT]"); - System.err.println(" [--pct-trackball PERCENT] [--pct-syskeys PERCENT]"); - System.err.println(" [--pct-nav PERCENT] [--pct-majornav PERCENT]"); - System.err.println(" [--pct-appswitch PERCENT] [--pct-flip PERCENT]"); - System.err.println(" [--pct-anyevent PERCENT]"); - System.err.println(" [--wait-dbg] [--dbg-no-events] [-f scriptfile]"); - System.err.println(" [-s SEED] [-v [-v] ...] [--throttle MILLISEC]"); - System.err.println(" COUNT"); - } -} diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyActivityEvent.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyActivityEvent.java deleted file mode 100644 index 68e6e6d7f..000000000 --- a/cmds/monkey/src/com/android/commands/monkey/MonkeyActivityEvent.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 android.app.IActivityManager; -import android.content.ComponentName; -import android.content.Intent; -import android.os.RemoteException; -import android.view.IWindowManager; - -/** - * monkey activity event - */ -public class MonkeyActivityEvent extends MonkeyEvent { - private ComponentName mApp; - - public MonkeyActivityEvent(ComponentName app) { - super(EVENT_TYPE_ACTIVITY); - mApp = app; - } - - /** - * @return Intent for the new activity - */ - private Intent getEvent() { - Intent intent = new Intent(Intent.ACTION_MAIN); - intent.addCategory(Intent.CATEGORY_LAUNCHER); - intent.setComponent(mApp); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - return intent; - } - - @Override - public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) { - Intent intent = getEvent(); - if (verbose > 0) { - System.out.println(":Switch: " + intent.toURI()); - } - try { - iam.startActivity(null, intent, null, null, 0, null, null, 0, - false, false); - } catch (RemoteException e) { - System.err.println("** Failed talking with activity manager!"); - return MonkeyEvent.INJECT_ERROR_REMOTE_EXCEPTION; - } catch (SecurityException e) { - if (verbose > 0) { - System.out.println("** Permissions error starting activity " - + intent.toURI()); - } - return MonkeyEvent.INJECT_ERROR_SECURITY_EXCEPTION; - } - return MonkeyEvent.INJECT_SUCCESS; - } -} diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyEvent.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyEvent.java deleted file mode 100644 index ff99f5f06..000000000 --- a/cmds/monkey/src/com/android/commands/monkey/MonkeyEvent.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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 android.app.IActivityManager; -import android.view.IWindowManager; - -/** - * abstract class for monkey event - */ -public abstract class MonkeyEvent { - protected int eventType; - public static final int EVENT_TYPE_KEY = 0; - public static final int EVENT_TYPE_POINTER = 1; - public static final int EVENT_TYPE_TRACKBALL = 2; - public static final int EVENT_TYPE_ACTIVITY = 3; - public static final int EVENT_TYPE_FLIP = 4; // Keyboard flip - - public static final int INJECT_SUCCESS = 1; - public static final int INJECT_FAIL = 0; - - // error code for remote exception during injection - public static final int INJECT_ERROR_REMOTE_EXCEPTION = -1; - // error code for security exception during injection - public static final int INJECT_ERROR_SECURITY_EXCEPTION = -2; - - public MonkeyEvent(int type) { - eventType = type; - } - - /** - * @return event type - */ - public int getEventType() { - return eventType; - } - - /** - * a method for injecting event - * @param iwm wires to current window manager - * @param iam wires to current activity manager - * @param verbose a log switch - * @return INJECT_SUCCESS if it goes through, and INJECT_FAIL if it fails - * in the case of exceptions, return its corresponding error code - */ - public abstract int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose); -} diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyEventSource.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyEventSource.java deleted file mode 100644 index a236554a5..000000000 --- a/cmds/monkey/src/com/android/commands/monkey/MonkeyEventSource.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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; - -/** - * event source interface - */ -public interface MonkeyEventSource { - /** - * - * @return the next monkey event from the source - */ - public MonkeyEvent getNextEvent(); - - /** - * set verbose to allow different level of log - * @param verbose output mode? 1= verbose, 2=very verbose - */ - public void setVerbose(int verbose); - - /** - * check whether precondition is satisfied - * @return false if something fails, e.g. factor failure in random source - * or file can not open from script source etc - */ - public boolean validate(); -} diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyFlipEvent.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyFlipEvent.java deleted file mode 100644 index 08fbedbc3..000000000 --- a/cmds/monkey/src/com/android/commands/monkey/MonkeyFlipEvent.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2008 Google Inc. - * - * 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.io.FileOutputStream; -import java.io.IOException; - -import android.app.IActivityManager; -import android.view.IWindowManager; -/** - * monkey keyboard flip event - */ -public class MonkeyFlipEvent extends MonkeyEvent { - - // Raw keyboard flip event data - // Works on emulator and dream - - private static final byte[] FLIP_0 = { - 0x7f, 0x06, - 0x00, 0x00, - (byte) 0xe0, 0x39, - 0x01, 0x00, - 0x05, 0x00, - 0x00, 0x00, - 0x01, 0x00, - 0x00, 0x00 }; - - private static final byte[] FLIP_1 = { - (byte) 0x85, 0x06, - 0x00, 0x00, - (byte) 0x9f, (byte) 0xa5, - 0x0c, 0x00, - 0x05, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00 }; - - private final boolean mKeyboardOpen; - - public MonkeyFlipEvent(boolean keyboardOpen) { - super(EVENT_TYPE_FLIP); - mKeyboardOpen = keyboardOpen; - } - - @Override - public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) { - if (verbose > 0) { - System.out.println(":Sending Flip keyboardOpen=" + mKeyboardOpen); - } - - // inject flip event - try { - FileOutputStream f = new FileOutputStream("/dev/input/event0"); - f.write(mKeyboardOpen ? FLIP_0 : FLIP_1); - f.close(); - return MonkeyEvent.INJECT_SUCCESS; - } catch (IOException e) { - System.out.println("Got IOException performing flip" + e); - return MonkeyEvent.INJECT_FAIL; - } - } -} diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyKeyEvent.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyKeyEvent.java deleted file mode 100644 index c1e0ffce7..000000000 --- a/cmds/monkey/src/com/android/commands/monkey/MonkeyKeyEvent.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * 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 android.app.IActivityManager; -import android.os.RemoteException; -import android.view.IWindowManager; -import android.view.KeyEvent; -/** - * monkey key event - */ -public class MonkeyKeyEvent extends MonkeyEvent { - private long mDownTime = -1; - private int mMetaState = -1; - private int mAction = -1; - private int mKeyCode = -1; - private int mScancode = -1; - private int mRepeatCount = -1; - private int mDeviceId = -1; - private long mEventTime = -1; - - public MonkeyKeyEvent(int action, int keycode) { - super(EVENT_TYPE_KEY); - mAction = action; - mKeyCode = keycode; - } - - public MonkeyKeyEvent(long downTime, long eventTime, int action, - int code, int repeat, int metaState, - int device, int scancode) { - super(EVENT_TYPE_KEY); - - mAction = action; - mKeyCode = code; - mMetaState = metaState; - mScancode = scancode; - mRepeatCount = repeat; - mDeviceId = device; - mDownTime = downTime; - mEventTime = eventTime; - } - - public int getKeyCode() { - return mKeyCode; - } - - public int getAction() { - return mAction; - } - - public long getDownTime() { - return mDownTime; - } - - public long getEventTime() { - return mEventTime; - } - - public void setDownTime(long downTime) { - mDownTime = downTime; - } - - public void setEventTime(long eventTime) { - mEventTime = eventTime; - } - - /** - * @return the key event - */ - private KeyEvent getEvent() { - if (mDeviceId < 0) { - return new KeyEvent(mAction, mKeyCode); - } - - // for scripts - return new KeyEvent(mDownTime, mEventTime, mAction, - mKeyCode, mRepeatCount, mMetaState, mDeviceId, mScancode); - } - - @Override - public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) { - if (verbose > 1) { - String note; - if (mAction == KeyEvent.ACTION_UP) { - note = "ACTION_UP"; - } else { - note = "ACTION_DOWN"; - } - - try { - System.out.println(":SendKey (" + note + "): " - + mKeyCode + " // " - + MonkeySourceRandom.getKeyName(mKeyCode)); - } catch (ArrayIndexOutOfBoundsException e) { - System.out.println(":SendKey (ACTION_UP): " - + mKeyCode + " // Unknown key event"); - } - } - - // inject key event - try { - if (!iwm.injectKeyEvent(getEvent(), false)) { - return MonkeyEvent.INJECT_FAIL; - } - } catch (RemoteException ex) { - return MonkeyEvent.INJECT_ERROR_REMOTE_EXCEPTION; - } - - return MonkeyEvent.INJECT_SUCCESS; - } -} diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyMotionEvent.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyMotionEvent.java deleted file mode 100644 index 2657061be..000000000 --- a/cmds/monkey/src/com/android/commands/monkey/MonkeyMotionEvent.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * 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 android.app.IActivityManager; -import android.os.RemoteException; -import android.os.SystemClock; -import android.view.IWindowManager; -import android.view.MotionEvent; - - -/** - * monkey motion event - */ -public class MonkeyMotionEvent extends MonkeyEvent { - private long mDownTime = -1; - private long mEventTime = -1; - private int mAction = -1; - private float mX = -1; - private float mY = -1; - private float mPressure = -1; - private float mSize = -1; - private int mMetaState = -1; - private float mXPrecision = -1; - private float mYPrecision = -1; - private int mDeviceId = -1; - private int mEdgeFlags = -1; - - //If true, this is an intermediate step (more verbose logging, only) - private boolean mIntermediateNote; - - public MonkeyMotionEvent(int type, long downAt, int action, - float x, float y, int metaState) { - super(type); - mDownTime = downAt; - mAction = action; - mX = x; - mY = y; - mMetaState = metaState; - } - - public MonkeyMotionEvent(int type, long downTime, long eventTime, int action, - float x, float y, float pressure, float size, int metaState, - float xPrecision, float yPrecision, int deviceId, int edgeFlags) { - super(type); - mDownTime = downTime; - mEventTime = eventTime; - mAction = action; - mX = x; - mY = y; - mPressure = pressure; - mSize = size; - mMetaState = metaState; - mXPrecision = xPrecision; - mYPrecision = yPrecision; - mDeviceId = deviceId; - mEdgeFlags = edgeFlags; - } - - public void setIntermediateNote(boolean b) { - mIntermediateNote = b; - } - - public boolean getIntermediateNote() { - return mIntermediateNote; - } - - public float getX() { - return mX; - } - - public float getY() { - return mY; - } - - public int getAction() { - return mAction; - } - - public long getDownTime() { - return mDownTime; - } - - public long getEventTime() { - return mEventTime; - } - - public void setDownTime(long downTime) { - mDownTime = downTime; - } - - public void setEventTime(long eventTime) { - mEventTime = eventTime; - } - - /** - * - * @return instance of a motion event - */ - private MotionEvent getEvent() { - if (mDeviceId < 0) { - return MotionEvent.obtain(mDownTime, SystemClock.uptimeMillis(), - mAction, mX, mY, mMetaState); - } - - // for scripts - return MotionEvent.obtain(mDownTime, mEventTime, - mAction, mX, mY, mPressure, mSize, mMetaState, - mXPrecision, mYPrecision, mDeviceId, mEdgeFlags); - } - - @Override - public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) { - - String note; - if ((verbose > 0 && !mIntermediateNote) || verbose > 1) { - if (mAction == MotionEvent.ACTION_DOWN) { - note = "DOWN"; - } else if (mAction == MotionEvent.ACTION_UP) { - note = "UP"; - } else { - note = "MOVE"; - } - System.out.println(":Sending Pointer ACTION_" + note + - " x=" + mX + " y=" + mY); - } - try { - int type = this.getEventType(); - MotionEvent me = getEvent(); - - if ((type == MonkeyEvent.EVENT_TYPE_POINTER && - !iwm.injectPointerEvent(me, false)) - || (type == MonkeyEvent.EVENT_TYPE_TRACKBALL && - !iwm.injectTrackballEvent(me, false))) { - return MonkeyEvent.INJECT_FAIL; - } - } catch (RemoteException ex) { - return MonkeyEvent.INJECT_ERROR_REMOTE_EXCEPTION; - } - return MonkeyEvent.INJECT_SUCCESS; - } -} diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java deleted file mode 100644 index 3dbb575aa..000000000 --- a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java +++ /dev/null @@ -1,467 +0,0 @@ -/* - * 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 android.content.ComponentName; -import android.os.SystemClock; -import android.view.Display; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.WindowManagerImpl; - -import java.security.SecureRandom; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.Random; - -/** - * monkey event queue - */ -public class MonkeySourceRandom implements MonkeyEventSource{ - /** Key events that move around the UI. */ - private static final int[] NAV_KEYS = { - KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN, - KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT, - }; - /** - * Key events that perform major navigation options (so shouldn't be sent - * as much). - */ - private static final int[] MAJOR_NAV_KEYS = { - KeyEvent.KEYCODE_MENU, /*KeyEvent.KEYCODE_SOFT_RIGHT,*/ - KeyEvent.KEYCODE_DPAD_CENTER, - }; - /** Key events that perform system operations. */ - private static final int[] SYS_KEYS = { - KeyEvent.KEYCODE_HOME, KeyEvent.KEYCODE_BACK, - KeyEvent.KEYCODE_CALL, KeyEvent.KEYCODE_ENDCALL, - KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_VOLUME_DOWN, - KeyEvent.KEYCODE_MUTE, - }; - /** Nice names for all key events. */ - private static final String[] KEY_NAMES = { - "KEYCODE_UNKNOWN", - "KEYCODE_MENU", - "KEYCODE_SOFT_RIGHT", - "KEYCODE_HOME", - "KEYCODE_BACK", - "KEYCODE_CALL", - "KEYCODE_ENDCALL", - "KEYCODE_0", - "KEYCODE_1", - "KEYCODE_2", - "KEYCODE_3", - "KEYCODE_4", - "KEYCODE_5", - "KEYCODE_6", - "KEYCODE_7", - "KEYCODE_8", - "KEYCODE_9", - "KEYCODE_STAR", - "KEYCODE_POUND", - "KEYCODE_DPAD_UP", - "KEYCODE_DPAD_DOWN", - "KEYCODE_DPAD_LEFT", - "KEYCODE_DPAD_RIGHT", - "KEYCODE_DPAD_CENTER", - "KEYCODE_VOLUME_UP", - "KEYCODE_VOLUME_DOWN", - "KEYCODE_POWER", - "KEYCODE_CAMERA", - "KEYCODE_CLEAR", - "KEYCODE_A", - "KEYCODE_B", - "KEYCODE_C", - "KEYCODE_D", - "KEYCODE_E", - "KEYCODE_F", - "KEYCODE_G", - "KEYCODE_H", - "KEYCODE_I", - "KEYCODE_J", - "KEYCODE_K", - "KEYCODE_L", - "KEYCODE_M", - "KEYCODE_N", - "KEYCODE_O", - "KEYCODE_P", - "KEYCODE_Q", - "KEYCODE_R", - "KEYCODE_S", - "KEYCODE_T", - "KEYCODE_U", - "KEYCODE_V", - "KEYCODE_W", - "KEYCODE_X", - "KEYCODE_Y", - "KEYCODE_Z", - "KEYCODE_COMMA", - "KEYCODE_PERIOD", - "KEYCODE_ALT_LEFT", - "KEYCODE_ALT_RIGHT", - "KEYCODE_SHIFT_LEFT", - "KEYCODE_SHIFT_RIGHT", - "KEYCODE_TAB", - "KEYCODE_SPACE", - "KEYCODE_SYM", - "KEYCODE_EXPLORER", - "KEYCODE_ENVELOPE", - "KEYCODE_ENTER", - "KEYCODE_DEL", - "KEYCODE_GRAVE", - "KEYCODE_MINUS", - "KEYCODE_EQUALS", - "KEYCODE_LEFT_BRACKET", - "KEYCODE_RIGHT_BRACKET", - "KEYCODE_BACKSLASH", - "KEYCODE_SEMICOLON", - "KEYCODE_APOSTROPHE", - "KEYCODE_SLASH", - "KEYCODE_AT", - "KEYCODE_NUM", - "KEYCODE_HEADSETHOOK", - "KEYCODE_FOCUS", - "KEYCODE_PLUS", - "KEYCODE_MENU", - "KEYCODE_NOTIFICATION", - "KEYCODE_SEARCH", - "KEYCODE_PLAYPAUSE", - "KEYCODE_STOP", - "KEYCODE_NEXTSONG", - "KEYCODE_PREVIOUSSONG", - "KEYCODE_REWIND", - "KEYCODE_FORWARD", - "KEYCODE_MUTE", - - "TAG_LAST_KEYCODE" // EOL. used to keep the lists in sync - }; - - public static final int FACTOR_TOUCH = 0; - public static final int FACTOR_MOTION = 1; - public static final int FACTOR_TRACKBALL = 2; - public static final int FACTOR_NAV = 3; - public static final int FACTOR_MAJORNAV = 4; - public static final int FACTOR_SYSOPS = 5; - public static final int FACTOR_APPSWITCH = 6; - public static final int FACTOR_FLIP = 7; - public static final int FACTOR_ANYTHING = 8; - public static final int FACTORZ_COUNT = 9; // should be last+1 - - - /** percentages for each type of event. These will be remapped to working - * values after we read any optional values. - **/ - private float[] mFactors = new float[FACTORZ_COUNT]; - private ArrayList<ComponentName> mMainApps; - private int mEventCount = 0; //total number of events generated so far - private LinkedList<MonkeyEvent> mQ = new LinkedList<MonkeyEvent>(); - private Random mRandom; - private int mVerbose = 0; - - private boolean mKeyboardOpen = false; - - /** - * @return the last name in the key list - */ - public static String getLastKeyName() { - return KEY_NAMES[KeyEvent.getMaxKeyCode() + 1]; - } - - public static String getKeyName(int keycode) { - return KEY_NAMES[keycode]; - } - - public MonkeySourceRandom(long seed, ArrayList<ComponentName> MainApps) { - // default values for random distributions - // note, these are straight percentages, to match user input (cmd line args) - // but they will be converted to 0..1 values before the main loop runs. - mFactors[FACTOR_TOUCH] = 15.0f; - mFactors[FACTOR_MOTION] = 10.0f; - mFactors[FACTOR_TRACKBALL] = 15.0f; - mFactors[FACTOR_NAV] = 25.0f; - mFactors[FACTOR_MAJORNAV] = 15.0f; - mFactors[FACTOR_SYSOPS] = 2.0f; - mFactors[FACTOR_APPSWITCH] = 2.0f; - mFactors[FACTOR_FLIP] = 1.0f; - mFactors[FACTOR_ANYTHING] = 15.0f; - - mRandom = new SecureRandom(); - mRandom.setSeed((seed == 0) ? -1 : seed); - mMainApps = MainApps; - } - - /** - * Adjust the percentages (after applying user values) and then normalize to a 0..1 scale. - */ - private boolean adjustEventFactors() { - // go through all values and compute totals for user & default values - float userSum = 0.0f; - float defaultSum = 0.0f; - int defaultCount = 0; - for (int i = 0; i < FACTORZ_COUNT; ++i) { - if (mFactors[i] <= 0.0f) { // user values are zero or negative - userSum -= mFactors[i]; - } else { - defaultSum += mFactors[i]; - ++defaultCount; - } - } - - // if the user request was > 100%, reject it - if (userSum > 100.0f) { - System.err.println("** Event weights > 100%"); - return false; - } - - // if the user specified all of the weights, then they need to be 100% - if (defaultCount == 0 && (userSum < 99.9f || userSum > 100.1f)) { - System.err.println("** Event weights != 100%"); - return false; - } - - // compute the adjustment necessary - float defaultsTarget = (100.0f - userSum); - float defaultsAdjustment = defaultsTarget / defaultSum; - - // fix all values, by adjusting defaults, or flipping user values back to >0 - for (int i = 0; i < FACTORZ_COUNT; ++i) { - if (mFactors[i] <= 0.0f) { // user values are zero or negative - mFactors[i] = -mFactors[i]; - } else { - mFactors[i] *= defaultsAdjustment; - } - } - - // if verbose, show factors - - if (mVerbose > 0) { - System.out.println("// Event percentages:"); - for (int i = 0; i < FACTORZ_COUNT; ++i) { - System.out.println("// " + i + ": " + mFactors[i] + "%"); - } - } - - // finally, normalize and convert to running sum - float sum = 0.0f; - for (int i = 0; i < FACTORZ_COUNT; ++i) { - sum += mFactors[i] / 100.0f; - mFactors[i] = sum; - } - return true; - } - - /** - * set the factors - * - * @param factors: percentages for each type of event - */ - public void setFactors(float factors[]) { - int c = FACTORZ_COUNT; - if (factors.length < c) { - c = factors.length; - } - for (int i = 0; i < c; i++) - mFactors[i] = factors[i]; - } - - public void setFactors(int index, float v) { - mFactors[index] = v; - } - - /** - * Generates a random motion event. This method counts a down, move, and up as multiple events. - * - * TODO: Test & fix the selectors when non-zero percentages - * TODO: Longpress. - * TODO: Fling. - * TODO: Meta state - * TODO: More useful than the random walk here would be to pick a single random direction - * and distance, and divvy it up into a random number of segments. (This would serve to - * generate fling gestures, which are important). - * - * @param random Random number source for positioning - * @param motionEvent If false, touch/release. If true, touch/move/release. - * - */ - private void generateMotionEvent(Random random, boolean motionEvent){ - - Display display = WindowManagerImpl.getDefault().getDefaultDisplay(); - - float x = Math.abs(random.nextInt() % display.getWidth()); - float y = Math.abs(random.nextInt() % display.getHeight()); - long downAt = SystemClock.uptimeMillis(); - long eventTime = SystemClock.uptimeMillis(); - if (downAt == -1) { - downAt = eventTime; - } - - MonkeyMotionEvent e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER, - downAt, MotionEvent.ACTION_DOWN, x, y, 0); - e.setIntermediateNote(false); - mQ.addLast(e); - - // sometimes we'll move during the touch - if (motionEvent) { - int count = random.nextInt(10); - for (int i = 0; i < count; i++) { - // generate some slop in the up event - x = (x + (random.nextInt() % 10)) % display.getWidth(); - y = (y + (random.nextInt() % 10)) % display.getHeight(); - - e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER, - downAt, MotionEvent.ACTION_MOVE, x, y, 0); - e.setIntermediateNote(true); - mQ.addLast(e); - } - } - - // TODO generate some slop in the up event - e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_POINTER, - downAt, MotionEvent.ACTION_UP, x, y, 0); - e.setIntermediateNote(false); - mQ.addLast(e); - } - - /** - * Generates a random trackball event. This consists of a sequence of small moves, followed by - * an optional single click. - * - * TODO: Longpress. - * TODO: Meta state - * TODO: Parameterize the % clicked - * TODO: More useful than the random walk here would be to pick a single random direction - * and distance, and divvy it up into a random number of segments. (This would serve to - * generate fling gestures, which are important). - * - * @param random Random number source for positioning - * - */ - private void generateTrackballEvent(Random random) { - Display display = WindowManagerImpl.getDefault().getDefaultDisplay(); - - boolean drop = false; - int count = random.nextInt(10); - MonkeyMotionEvent e; - for (int i = 0; i < 10; ++i) { - // generate a small random step - int dX = random.nextInt(10) - 5; - int dY = random.nextInt(10) - 5; - - - e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, -1, - MotionEvent.ACTION_MOVE, dX, dY, 0); - e.setIntermediateNote(i > 0); - mQ.addLast(e); - } - - // 10% of trackball moves end with a click - if (0 == random.nextInt(10)) { - long downAt = SystemClock.uptimeMillis(); - - - e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, downAt, - MotionEvent.ACTION_DOWN, 0, 0, 0); - e.setIntermediateNote(true); - mQ.addLast(e); - - - e = new MonkeyMotionEvent(MonkeyEvent.EVENT_TYPE_TRACKBALL, downAt, - MotionEvent.ACTION_UP, 0, 0, 0); - e.setIntermediateNote(false); - mQ.addLast(e); - } - } - - /** - * generate a random event based on mFactor - */ - private void generateEvents() { - float cls = mRandom.nextFloat(); - int lastKey = 0; - - boolean touchEvent = cls < mFactors[FACTOR_TOUCH]; - boolean motionEvent = !touchEvent && (cls < mFactors[FACTOR_MOTION]); - if (touchEvent || motionEvent) { - generateMotionEvent(mRandom, motionEvent); - return; - } - - if (cls < mFactors[FACTOR_TRACKBALL]) { - generateTrackballEvent(mRandom); - return; - } - - // The remaining event categories are injected as key events - if (cls < mFactors[FACTOR_NAV]) { - lastKey = NAV_KEYS[mRandom.nextInt(NAV_KEYS.length)]; - } else if (cls < mFactors[FACTOR_MAJORNAV]) { - lastKey = MAJOR_NAV_KEYS[mRandom.nextInt(MAJOR_NAV_KEYS.length)]; - } else if (cls < mFactors[FACTOR_SYSOPS]) { - lastKey = SYS_KEYS[mRandom.nextInt(SYS_KEYS.length)]; - } else if (cls < mFactors[FACTOR_APPSWITCH]) { - MonkeyActivityEvent e = new MonkeyActivityEvent(mMainApps.get( - mRandom.nextInt(mMainApps.size()))); - mQ.addLast(e); - return; - } else if (cls < mFactors[FACTOR_FLIP]) { - MonkeyFlipEvent e = new MonkeyFlipEvent(mKeyboardOpen); - mKeyboardOpen = !mKeyboardOpen; - mQ.addLast(e); - return; - } else { - lastKey = 1 + mRandom.nextInt(KeyEvent.getMaxKeyCode() - 1); - } - - MonkeyKeyEvent e = new MonkeyKeyEvent(KeyEvent.ACTION_DOWN, lastKey); - mQ.addLast(e); - - e = new MonkeyKeyEvent(KeyEvent.ACTION_UP, lastKey); - mQ.addLast(e); - } - - public boolean validate() { - //check factors - return adjustEventFactors(); - } - - public void setVerbose(int verbose) { - mVerbose = verbose; - } - - /** - * generate an activity event - */ - public void generateActivity() { - MonkeyActivityEvent e = new MonkeyActivityEvent(mMainApps.get( - mRandom.nextInt(mMainApps.size()))); - mQ.addLast(e); - } - - /** - * if the queue is empty, we generate events first - * @return the first event in the queue - */ - public MonkeyEvent getNextEvent() { - if (mQ.isEmpty()) { - generateEvents(); - } - mEventCount++; - MonkeyEvent e = mQ.getFirst(); - mQ.removeFirst(); - return e; - } -} diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java deleted file mode 100644 index aadda9f62..000000000 --- a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java +++ /dev/null @@ -1,427 +0,0 @@ -/* - * 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 android.os.SystemClock; -import android.view.KeyEvent; - -import java.io.BufferedReader; -import java.io.DataInputStream; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.LinkedList; -import java.util.StringTokenizer; - -/** - * monkey event queue. It takes a script to produce events - * - * sample script format: - * type= raw events - * count= 10 - * speed= 1.0 - * captureDispatchPointer(5109520,5109520,0,230.75429,458.1814,0.20784314, - * 0.06666667,0,0.0,0.0,65539,0) - * captureDispatchKey(5113146,5113146,0,20,0,0,0,0) - * captureDispatchFlip(true) - * ... - */ -public class MonkeySourceScript implements MonkeyEventSource{ - private int mEventCountInScript = 0; //total number of events in the file - private int mVerbose = 0; - private double mSpeed = 1.0; - private String mScriptFileName; - private LinkedList<MonkeyEvent> mQ = new LinkedList<MonkeyEvent>(); - - private static final String HEADER_TYPE = "type="; - private static final String HEADER_COUNT = "count="; - private static final String HEADER_SPEED = "speed="; - - private long mLastRecordedDownTimeKey = 0; - private long mLastRecordedDownTimeMotion = 0; - private long mLastExportDownTimeKey = 0; - private long mLastExportDownTimeMotion = 0; - private long mLastExportEventTime = -1; - private long mLastRecordedEventTime = -1; - - private static final boolean THIS_DEBUG = false; - // a parameter that compensates the difference of real elapsed time and - // time in theory - private static final long SLEEP_COMPENSATE_DIFF = 16; - - // maximum number of events that we read at one time - private static final int MAX_ONE_TIME_READS = 100; - - // number of additional events added to the script - // add HOME_KEY down and up events to make start UI consistent in each round - private static final int POLICY_ADDITIONAL_EVENT_COUNT = 2; - - // event key word in the capture log - private static final String EVENT_KEYWORD_POINTER = "DispatchPointer"; - private static final String EVENT_KEYWORD_TRACKBALL = "DispatchTrackball"; - private static final String EVENT_KEYWORD_KEY = "DispatchKey"; - private static final String EVENT_KEYWORD_FLIP = "DispatchFlip"; - - // a line at the end of the header - private static final String STARTING_DATA_LINE = "start data >>"; - private boolean mFileOpened = false; - FileInputStream mFStream; - DataInputStream mInputStream; - BufferedReader mBufferReader; - - public MonkeySourceScript(String filename) { - mScriptFileName = filename; - } - - /** - * - * @return the number of total events that will be generated in a round - */ - public int getOneRoundEventCount() { - //plus one home key down and up event - return mEventCountInScript + POLICY_ADDITIONAL_EVENT_COUNT; - } - - private void resetValue() { - mLastRecordedDownTimeKey = 0; - mLastRecordedDownTimeMotion = 0; - mLastExportDownTimeKey = 0; - mLastExportDownTimeMotion = 0; - mLastRecordedEventTime = -1; - mLastExportEventTime = -1; - } - - private boolean readScriptHeader() { - mEventCountInScript = -1; - mFileOpened = false; - try { - if (THIS_DEBUG) { - System.out.println("reading script header"); - } - - mFStream = new FileInputStream(mScriptFileName); - mInputStream = new DataInputStream(mFStream); - mBufferReader = new BufferedReader( - new InputStreamReader(mInputStream)); - String sLine; - while ((sLine = mBufferReader.readLine()) != null) { - sLine = sLine.trim(); - if (sLine.indexOf(HEADER_TYPE) >= 0) { - // at this point, we only have one type of script - } else if (sLine.indexOf(HEADER_COUNT) >= 0) { - try { - mEventCountInScript = Integer.parseInt(sLine.substring( - HEADER_COUNT.length() + 1).trim()); - } catch (NumberFormatException e) { - System.err.println(e); - } - } else if (sLine.indexOf(HEADER_SPEED) >= 0) { - try { - mSpeed = Double.parseDouble(sLine.substring( - HEADER_SPEED.length() + 1).trim()); - - } catch (NumberFormatException e) { - System.err.println(e); - } - } else if (sLine.indexOf(STARTING_DATA_LINE) >= 0) { - // header ends until we read the start data mark - mFileOpened = true; - if (THIS_DEBUG) { - System.out.println("read script header success"); - } - return true; - } - } - } catch (FileNotFoundException e) { - System.err.println(e); - } catch (IOException e) { - System.err.println(e); - } - - if (THIS_DEBUG) { - System.out.println("Error in reading script header"); - } - return false; - } - - private void processLine(String s) { - int index1 = s.indexOf('('); - int index2 = s.indexOf(')'); - - if (index1 < 0 || index2 < 0) { - return; - } - - StringTokenizer st = new StringTokenizer( - s.substring(index1 + 1, index2), ","); - - if (s.indexOf(EVENT_KEYWORD_KEY) >= 0) { - // key events - try { - long downTime = Long.parseLong(st.nextToken()); - long eventTime = Long.parseLong(st.nextToken()); - int action = Integer.parseInt(st.nextToken()); - int code = Integer.parseInt(st.nextToken()); - int repeat = Integer.parseInt(st.nextToken()); - int metaState = Integer.parseInt(st.nextToken()); - int device = Integer.parseInt(st.nextToken()); - int scancode = Integer.parseInt(st.nextToken()); - - MonkeyKeyEvent e = new MonkeyKeyEvent(downTime, eventTime, - action, code, repeat, metaState, device, scancode); - mQ.addLast(e); - - } catch (NumberFormatException e) { - // something wrong with this line in the script - } - } else if (s.indexOf(EVENT_KEYWORD_POINTER) >= 0 || - s.indexOf(EVENT_KEYWORD_TRACKBALL) >= 0) { - // trackball/pointer event - try { - long downTime = Long.parseLong(st.nextToken()); - long eventTime = Long.parseLong(st.nextToken()); - int action = Integer.parseInt(st.nextToken()); - float x = Float.parseFloat(st.nextToken()); - float y = Float.parseFloat(st.nextToken()); - float pressure = Float.parseFloat(st.nextToken()); - float size = Float.parseFloat(st.nextToken()); - int metaState = Integer.parseInt(st.nextToken()); - float xPrecision = Float.parseFloat(st.nextToken()); - float yPrecision = Float.parseFloat(st.nextToken()); - int device = Integer.parseInt(st.nextToken()); - int edgeFlags = Integer.parseInt(st.nextToken()); - - int type = MonkeyEvent.EVENT_TYPE_TRACKBALL; - if (s.indexOf("Pointer") > 0) { - type = MonkeyEvent.EVENT_TYPE_POINTER; - } - MonkeyMotionEvent e = new MonkeyMotionEvent(type, downTime, eventTime, - action, x, y, pressure, size, metaState, xPrecision, yPrecision, - device, edgeFlags); - mQ.addLast(e); - } catch (NumberFormatException e) { - // we ignore this event - } - } else if (s.indexOf(EVENT_KEYWORD_FLIP) >= 0) { - boolean keyboardOpen = Boolean.parseBoolean(st.nextToken()); - MonkeyFlipEvent e = new MonkeyFlipEvent(keyboardOpen); - mQ.addLast(e); - } - } - - private void closeFile() { - mFileOpened = false; - if (THIS_DEBUG) { - System.out.println("closing script file"); - } - - try { - mFStream.close(); - mInputStream.close(); - } catch (IOException e) { - System.out.println(e); - } - } - - /** - * add home key press/release event to the queue - */ - private void addHomeKeyEvent() { - MonkeyKeyEvent e = new MonkeyKeyEvent(KeyEvent.ACTION_DOWN, - KeyEvent.KEYCODE_HOME); - mQ.addLast(e); - e = new MonkeyKeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HOME); - mQ.addLast(e); - } - - /** - * read next batch of events from the provided script file - * @return true if success - */ - private boolean readNextBatch() { - String sLine = null; - int readCount = 0; - - if (THIS_DEBUG) { - System.out.println("readNextBatch(): reading next batch of events"); - } - - if (!mFileOpened) { - if (!readScriptHeader()) { - closeFile(); - return false; - } - resetValue(); - - /* - * In order to allow the Monkey to replay captured events multiple times - * we need to define a default start UI, which is the home screen - * Otherwise, it won't be accurate since the captured events - * could end anywhere - */ - addHomeKeyEvent(); - } - - try { - while (readCount++ < MAX_ONE_TIME_READS && - (sLine = mBufferReader.readLine()) != null) { - sLine = sLine.trim(); - processLine(sLine); - } - } catch (IOException e) { - System.err.println(e); - return false; - } - - if (sLine == null) { - // to the end of the file - if (THIS_DEBUG) { - System.out.println("readNextBatch(): to the end of file"); - } - closeFile(); - } - return true; - } - - /** - * sleep for a period of given time, introducing latency among events - * @param time to sleep in millisecond - */ - private void needSleep(long time) { - if (time < 1) { - return; - } - try { - Thread.sleep(time); - } catch (InterruptedException e) { - } - } - - /** - * check whether we can successfully read the header of the script file - */ - public boolean validate() { - boolean b = readNextBatch(); - if (mVerbose > 0) { - System.out.println("Replaying " + mEventCountInScript + - " events with speed " + mSpeed); - } - return b; - } - - public void setVerbose(int verbose) { - mVerbose = verbose; - } - - /** - * adjust key downtime and eventtime according to both - * recorded values and current system time - * @param e KeyEvent - */ - private void adjustKeyEventTime(MonkeyKeyEvent e) { - if (e.getEventTime() < 0) { - return; - } - long thisDownTime = 0; - long thisEventTime = 0; - long expectedDelay = 0; - - if (mLastRecordedEventTime <= 0) { - // first time event - thisDownTime = SystemClock.uptimeMillis(); - thisEventTime = thisDownTime; - } else { - if (e.getDownTime() != mLastRecordedDownTimeKey) { - thisDownTime = e.getDownTime(); - } else { - thisDownTime = mLastExportDownTimeKey; - } - expectedDelay = (long) ((e.getEventTime() - - mLastRecordedEventTime) * mSpeed); - thisEventTime = mLastExportEventTime + expectedDelay; - // add sleep to simulate everything in recording - needSleep(expectedDelay - SLEEP_COMPENSATE_DIFF); - } - mLastRecordedDownTimeKey = e.getDownTime(); - mLastRecordedEventTime = e.getEventTime(); - e.setDownTime(thisDownTime); - e.setEventTime(thisEventTime); - mLastExportDownTimeKey = thisDownTime; - mLastExportEventTime = thisEventTime; - } - - /** - * adjust motion downtime and eventtime according to both - * recorded values and current system time - * @param e KeyEvent - */ - private void adjustMotionEventTime(MonkeyMotionEvent e) { - if (e.getEventTime() < 0) { - return; - } - long thisDownTime = 0; - long thisEventTime = 0; - long expectedDelay = 0; - - if (mLastRecordedEventTime <= 0) { - // first time event - thisDownTime = SystemClock.uptimeMillis(); - thisEventTime = thisDownTime; - } else { - if (e.getDownTime() != mLastRecordedDownTimeMotion) { - thisDownTime = e.getDownTime(); - } else { - thisDownTime = mLastExportDownTimeMotion; - } - expectedDelay = (long) ((e.getEventTime() - - mLastRecordedEventTime) * mSpeed); - thisEventTime = mLastExportEventTime + expectedDelay; - // add sleep to simulate everything in recording - needSleep(expectedDelay - SLEEP_COMPENSATE_DIFF); - } - - mLastRecordedDownTimeMotion = e.getDownTime(); - mLastRecordedEventTime = e.getEventTime(); - e.setDownTime(thisDownTime); - e.setEventTime(thisEventTime); - mLastExportDownTimeMotion = thisDownTime; - mLastExportEventTime = thisEventTime; - } - - /** - * if the queue is empty, we generate events first - * @return the first event in the queue, if null, indicating the system crashes - */ - public MonkeyEvent getNextEvent() { - long recordedEventTime = -1; - - if (mQ.isEmpty()) { - readNextBatch(); - } - MonkeyEvent e = mQ.getFirst(); - mQ.removeFirst(); - - if (e.getEventType() == MonkeyEvent.EVENT_TYPE_KEY) { - adjustKeyEventTime((MonkeyKeyEvent) e); - } else if (e.getEventType() == MonkeyEvent.EVENT_TYPE_POINTER || - e.getEventType() == MonkeyEvent.EVENT_TYPE_TRACKBALL) { - adjustMotionEventTime((MonkeyMotionEvent) e); - } - return e; - } -} |
