AI 145122: am: CL 144927 Fix throttling in scripted monkeys (bug #1739843).
  Original author: emillar

Automated import of CL 145122
diff --git a/cmds/monkey/src/com/android/commands/monkey/Monkey.java b/cmds/monkey/src/com/android/commands/monkey/Monkey.java
index 00fb40c..fe0de99 100644
--- a/cmds/monkey/src/com/android/commands/monkey/Monkey.java
+++ b/cmds/monkey/src/com/android/commands/monkey/Monkey.java
@@ -362,7 +362,7 @@
         
         if (mScriptFileName != null) {
             // script mode, ignore other options
-            mEventSource = new MonkeySourceScript(mScriptFileName);
+            mEventSource = new MonkeySourceScript(mScriptFileName, mThrottle);
             mEventSource.setVerbose(mVerbose);
         } else {
             // random source by default
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyEvent.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyEvent.java
index 7176073..d926be8 100644
--- a/cmds/monkey/src/com/android/commands/monkey/MonkeyEvent.java
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeyEvent.java
@@ -51,6 +51,14 @@
     }
     
     /**
+     * @return true if it is safe to throttle after this event, and false otherwise.
+     */
+    public boolean isThrottlable() {
+        return true;
+    }
+    
+    
+    /**
      * a method for injecting event
      * @param iwm wires to current window manager
      * @param iam wires to current activity manager
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyEventQueue.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyEventQueue.java
new file mode 100644
index 0000000..dfe389a
--- /dev/null
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeyEventQueue.java
@@ -0,0 +1,41 @@
+/*
+ * 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.util.LinkedList;
+
+/**
+ * class for keeping a monkey event queue
+ */
+@SuppressWarnings("serial")
+public class MonkeyEventQueue extends LinkedList<MonkeyEvent> {   
+
+    private long mThrottle;
+    
+    public MonkeyEventQueue(long throttle) {
+        super();
+        mThrottle = throttle;
+    }
+    
+    @Override
+    public void addLast(MonkeyEvent e) {
+        super.add(e);
+        if (e.isThrottlable()) {
+            super.add(new MonkeyThrottleEvent(mThrottle));
+        }
+    }
+}
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyKeyEvent.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyKeyEvent.java
index c1e0ffc..877ebb5 100644
--- a/cmds/monkey/src/com/android/commands/monkey/MonkeyKeyEvent.java
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeyKeyEvent.java
@@ -92,6 +92,11 @@
     }
 
     @Override
+    public boolean isThrottlable() {
+        return (getAction() == KeyEvent.ACTION_UP);
+    }
+    
+    @Override
     public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
         if (verbose > 1) {
             String note;
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyMotionEvent.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyMotionEvent.java
index 2657061..81c64b4 100644
--- a/cmds/monkey/src/com/android/commands/monkey/MonkeyMotionEvent.java
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeyMotionEvent.java
@@ -20,6 +20,7 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.view.IWindowManager;
+import android.view.KeyEvent;
 import android.view.MotionEvent;
 
 
@@ -124,6 +125,11 @@
     }
 
     @Override
+    public boolean isThrottlable() {
+        return (getAction() == KeyEvent.ACTION_UP);
+    }
+    
+    @Override
     public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
         
         String note;
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java
index 902d8e8..5f9c10f 100644
--- a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java
@@ -31,7 +31,7 @@
 /**
  * monkey event queue
  */
-public class MonkeySourceRandom implements MonkeyEventSource{    
+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,
@@ -168,7 +168,7 @@
     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 MonkeyEventQueue mQ;
     private Random mRandom;    
     private int mVerbose = 0;
     private long mThrottle = 0;
@@ -203,7 +203,7 @@
         mRandom = new SecureRandom();
         mRandom.setSeed((seed == 0) ? -1 : seed);
         mMainApps = MainApps;
-        mThrottle = throttle;
+        mQ = new MonkeyEventQueue(throttle);
     }
 
     /**
@@ -336,7 +336,6 @@
                 downAt, MotionEvent.ACTION_UP, x, y, 0);        
         e.setIntermediateNote(false);        
         mQ.addLast(e);
-        addThrottle();
     }
   
     /**
@@ -387,7 +386,6 @@
             e.setIntermediateNote(false);        
             mQ.addLast(e);
         }        
-        addThrottle();
     }
     
     /** 
@@ -420,13 +418,11 @@
             MonkeyActivityEvent e = new MonkeyActivityEvent(mMainApps.get(
                     mRandom.nextInt(mMainApps.size())));
             mQ.addLast(e);
-            addThrottle();
             return;
         } else if (cls < mFactors[FACTOR_FLIP]) {
             MonkeyFlipEvent e = new MonkeyFlipEvent(mKeyboardOpen);
             mKeyboardOpen = !mKeyboardOpen;
             mQ.addLast(e);
-            addThrottle();
             return;
         } else {
             lastKey = 1 + mRandom.nextInt(KeyEvent.getMaxKeyCode() - 1);
@@ -437,8 +433,6 @@
         
         e = new MonkeyKeyEvent(KeyEvent.ACTION_UP, lastKey);
         mQ.addLast(e);
-        
-        addThrottle();
     }
     
     public boolean validate() {
@@ -472,8 +466,4 @@
         mQ.removeFirst();        
         return e;
     }
-    
-    private void addThrottle() {
-        mQ.addLast(new MonkeyThrottleEvent(MonkeyEvent.EVENT_TYPE_THROTTLE, mThrottle));
-    }
 }
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java
index aadda9f..869af2c 100644
--- a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java
@@ -35,18 +35,19 @@
  *      type= raw events
  *      count= 10
  *      speed= 1.0
+ *      start data >>
  *      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{    
+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 MonkeyEventQueue mQ;
     
     private static final String HEADER_TYPE = "type=";
     private static final String HEADER_COUNT = "count=";
@@ -80,12 +81,14 @@
     // 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) {
+    public MonkeySourceScript(String filename, long throttle) {
         mScriptFileName = filename;
+        mQ = new MonkeyEventQueue(throttle);
     }
     
     /**
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyThrottleEvent.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyThrottleEvent.java
index 3d7d48a..0b4e6b6 100644
--- a/cmds/monkey/src/com/android/commands/monkey/MonkeyThrottleEvent.java
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeyThrottleEvent.java
@@ -16,11 +16,10 @@
 
 package com.android.commands.monkey;
 
+import java.util.List;
+
 import android.app.IActivityManager;
-import android.os.RemoteException;
-import android.os.SystemClock;
 import android.view.IWindowManager;
-import android.view.MotionEvent;
 
 
 /**
@@ -29,8 +28,8 @@
 public class MonkeyThrottleEvent extends MonkeyEvent {
     private long mThrottle; 
         
-    public MonkeyThrottleEvent(int type, long throttle) {
-        super(type);
+    public MonkeyThrottleEvent(long throttle) {
+        super(MonkeyEvent.EVENT_TYPE_THROTTLE);
         mThrottle = throttle;
     }