DO NOT MERGE Modify Monkey so that scripts can use raw and user events.

Fix javadoc comment in MonkeySourceRandom.java and combine raw events and user
events in MonkeySourceScript.java.  Also, fix bug where too few arguments in
the script causes a RuntimeException.
This commit is contained in:
Eric Rowe
2009-10-19 18:06:38 -07:00
parent 2b9a0444ea
commit b2fa770013
2 changed files with 212 additions and 202 deletions

View File

@@ -285,7 +285,7 @@ public class MonkeySourceRandom implements MonkeyEventSource {
/** /**
* set the factors * set the factors
* *
* @param factors: percentages for each type of event * @param factors percentages for each type of event
*/ */
public void setFactors(float factors[]) { public void setFactors(float factors[]) {
int c = FACTORZ_COUNT; int c = FACTORZ_COUNT;

View File

@@ -26,117 +26,131 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.StringTokenizer;
import android.view.KeyEvent;
/** /**
* monkey event queue. It takes a script to produce events * monkey event queue. It takes a script to produce events sample script format:
* *
* sample script format: * <pre>
* type= raw events * type= raw events
* count= 10 * count= 10
* speed= 1.0 * speed= 1.0
* start data >> * start data &gt;&gt;
* captureDispatchPointer(5109520,5109520,0,230.75429,458.1814,0.20784314, * captureDispatchPointer(5109520,5109520,0,230.75429,458.1814,0.20784314,0.06666667,0,0.0,0.0,65539,0)
* 0.06666667,0,0.0,0.0,65539,0) * captureDispatchKey(5113146,5113146,0,20,0,0,0,0)
* captureDispatchKey(5113146,5113146,0,20,0,0,0,0) * captureDispatchFlip(true)
* captureDispatchFlip(true) * ...
* ... * </pre>
*/ */
public class MonkeySourceScript implements MonkeyEventSource { public class MonkeySourceScript implements MonkeyEventSource {
private int mEventCountInScript = 0; //total number of events in the file private int mEventCountInScript = 0; // total number of events in the file
private int mVerbose = 0; private int mVerbose = 0;
private double mSpeed = 1.0; private double mSpeed = 1.0;
private String mScriptFileName;
private String mScriptFileName;
private MonkeyEventQueue mQ; private MonkeyEventQueue mQ;
private static final String HEADER_TYPE = "type=";
private static final String HEADER_COUNT = "count="; private static final String HEADER_COUNT = "count=";
private static final String HEADER_SPEED = "speed="; private static final String HEADER_SPEED = "speed=";
// New script type
private static final String USER_EVENT_TYPE = "user"; private long mLastRecordedDownTimeKey = 0;
private long mLastRecordedDownTimeKey = 0;
private long mLastRecordedDownTimeMotion = 0; private long mLastRecordedDownTimeMotion = 0;
private long mLastExportDownTimeKey = 0; private long mLastExportDownTimeKey = 0;
private long mLastExportDownTimeMotion = 0; private long mLastExportDownTimeMotion = 0;
private long mLastExportEventTime = -1; private long mLastExportEventTime = -1;
private long mLastRecordedEventTime = -1; private long mLastRecordedEventTime = -1;
private String mScriptType = USER_EVENT_TYPE;
private static final boolean THIS_DEBUG = false; private static final boolean THIS_DEBUG = false;
// a parameter that compensates the difference of real elapsed time and
// a parameter that compensates the difference of real elapsed time and
// time in theory // time in theory
private static final long SLEEP_COMPENSATE_DIFF = 16; private static final long SLEEP_COMPENSATE_DIFF = 16;
// maximum number of events that we read at one time // maximum number of events that we read at one time
private static final int MAX_ONE_TIME_READS = 100; 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 // 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 = 0;
// event key word in the capture log
private static final String EVENT_KEYWORD_POINTER = "DispatchPointer"; private static final String EVENT_KEYWORD_POINTER = "DispatchPointer";
private static final String EVENT_KEYWORD_TRACKBALL = "DispatchTrackball"; private static final String EVENT_KEYWORD_TRACKBALL = "DispatchTrackball";
private static final String EVENT_KEYWORD_KEY = "DispatchKey"; private static final String EVENT_KEYWORD_KEY = "DispatchKey";
private static final String EVENT_KEYWORD_FLIP = "DispatchFlip"; private static final String EVENT_KEYWORD_FLIP = "DispatchFlip";
private static final String EVENT_KEYWORD_KEYPRESS = "DispatchPress"; private static final String EVENT_KEYWORD_KEYPRESS = "DispatchPress";
private static final String EVENT_KEYWORD_ACTIVITY = "LaunchActivity"; private static final String EVENT_KEYWORD_ACTIVITY = "LaunchActivity";
private static final String EVENT_KEYWORD_WAIT = "UserWait"; private static final String EVENT_KEYWORD_WAIT = "UserWait";
private static final String EVENT_KEYWORD_LONGPRESS = "LongPress"; private static final String EVENT_KEYWORD_LONGPRESS = "LongPress";
// a line at the end of the header // a line at the end of the header
private static final String STARTING_DATA_LINE = "start data >>"; private static final String STARTING_DATA_LINE = "start data >>";
private boolean mFileOpened = false;
private static int LONGPRESS_WAIT_TIME = 2000; // wait time for the long press private boolean mFileOpened = false;
private static int LONGPRESS_WAIT_TIME = 2000; // wait time for the long
// press
FileInputStream mFStream; FileInputStream mFStream;
DataInputStream mInputStream; DataInputStream mInputStream;
BufferedReader mBufferReader; BufferedReader mBufferReader;
public MonkeySourceScript(String filename, long throttle) { public MonkeySourceScript(String filename, long throttle) {
mScriptFileName = filename; mScriptFileName = filename;
mQ = new MonkeyEventQueue(throttle); mQ = new MonkeyEventQueue(throttle);
} }
/** /**
* * @return the number of total events that will be generated in a round
* @return the number of total events that will be generated in a round
*/ */
public int getOneRoundEventCount() { public int getOneRoundEventCount() {
//plus one home key down and up event // plus one home key down and up event
return mEventCountInScript + POLICY_ADDITIONAL_EVENT_COUNT; return mEventCountInScript + POLICY_ADDITIONAL_EVENT_COUNT;
} }
private void resetValue() { private void resetValue() {
mLastRecordedDownTimeKey = 0; mLastRecordedDownTimeKey = 0;
mLastRecordedDownTimeMotion = 0; mLastRecordedDownTimeMotion = 0;
mLastExportDownTimeKey = 0; mLastExportDownTimeKey = 0;
mLastExportDownTimeMotion = 0; mLastExportDownTimeMotion = 0;
mLastRecordedEventTime = -1; mLastRecordedEventTime = -1;
mLastExportEventTime = -1; mLastExportEventTime = -1;
} }
private boolean readScriptHeader() { private boolean readScriptHeader() {
mEventCountInScript = -1; mEventCountInScript = -1;
mFileOpened = false; mFileOpened = false;
try { try {
if (THIS_DEBUG) { if (THIS_DEBUG) {
System.out.println("reading script header"); System.out.println("reading script header");
} }
mFStream = new FileInputStream(mScriptFileName); mFStream = new FileInputStream(mScriptFileName);
mInputStream = new DataInputStream(mFStream); mInputStream = new DataInputStream(mFStream);
mBufferReader = new BufferedReader( mBufferReader = new BufferedReader(new InputStreamReader(mInputStream));
new InputStreamReader(mInputStream));
String sLine; String sLine;
while ((sLine = mBufferReader.readLine()) != null) { while ((sLine = mBufferReader.readLine()) != null) {
sLine = sLine.trim(); sLine = sLine.trim();
if (sLine.indexOf(HEADER_TYPE) >= 0) {
mScriptType = sLine.substring(HEADER_TYPE.length() + 1).trim(); if (sLine.indexOf(HEADER_COUNT) >= 0) {
} else if (sLine.indexOf(HEADER_COUNT) >= 0) {
try { try {
mEventCountInScript = Integer.parseInt(sLine.substring( mEventCountInScript = Integer.parseInt(sLine.substring(
HEADER_COUNT.length() + 1).trim()); HEADER_COUNT.length() + 1).trim());
@@ -145,9 +159,9 @@ public class MonkeySourceScript implements MonkeyEventSource {
} }
} else if (sLine.indexOf(HEADER_SPEED) >= 0) { } else if (sLine.indexOf(HEADER_SPEED) >= 0) {
try { try {
mSpeed = Double.parseDouble(sLine.substring( mSpeed = Double.parseDouble(sLine.substring(HEADER_SPEED.length() + 1)
HEADER_SPEED.length() + 1).trim()); .trim());
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
System.err.println(e); System.err.println(e);
} }
@@ -156,112 +170,123 @@ public class MonkeySourceScript implements MonkeyEventSource {
mFileOpened = true; mFileOpened = true;
if (THIS_DEBUG) { if (THIS_DEBUG) {
System.out.println("read script header success"); System.out.println("read script header success");
} }
return true; return true;
} }
} }
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
System.err.println(e); System.err.println(e);
} catch (IOException e) { } catch (IOException e) {
System.err.println(e); System.err.println(e);
} }
if (THIS_DEBUG) { if (THIS_DEBUG) {
System.out.println("Error in reading script header"); System.out.println("Error in reading script header");
} }
return false; return false;
} }
private void handleRawEvent(String s, StringTokenizer st) { private void handleEvent(String s, String[] args) {
if (s.indexOf(EVENT_KEYWORD_KEY) >= 0) { // Handle key event
// key events if (s.indexOf(EVENT_KEYWORD_KEY) >= 0 && args.length == 8) {
try { try {
System.out.println(" old key\n"); System.out.println(" old key\n");
long downTime = Long.parseLong(st.nextToken()); long downTime = Long.parseLong(args[0]);
long eventTime = Long.parseLong(st.nextToken()); long eventTime = Long.parseLong(args[1]);
int action = Integer.parseInt(st.nextToken()); int action = Integer.parseInt(args[2]);
int code = Integer.parseInt(st.nextToken()); int code = Integer.parseInt(args[3]);
int repeat = Integer.parseInt(st.nextToken()); int repeat = Integer.parseInt(args[4]);
int metaState = Integer.parseInt(st.nextToken()); int metaState = Integer.parseInt(args[5]);
int device = Integer.parseInt(st.nextToken()); int device = Integer.parseInt(args[6]);
int scancode = Integer.parseInt(st.nextToken()); int scancode = Integer.parseInt(args[7]);
MonkeyKeyEvent e = MonkeyKeyEvent e = new MonkeyKeyEvent(downTime, eventTime, action, code, repeat,
new MonkeyKeyEvent(downTime, eventTime, action, code, repeat, metaState, metaState, device, scancode);
device, scancode);
System.out.println(" Key code " + code + "\n"); System.out.println(" Key code " + code + "\n");
mQ.addLast(e); mQ.addLast(e);
System.out.println("Added key up \n"); System.out.println("Added key up \n");
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
// something wrong with this line in the script
} }
} else if (s.indexOf(EVENT_KEYWORD_POINTER) >= 0 || return;
s.indexOf(EVENT_KEYWORD_TRACKBALL) >= 0) { }
// trackball/pointer event
// Handle trackball or pointer events
if ((s.indexOf(EVENT_KEYWORD_POINTER) >= 0 || s.indexOf(EVENT_KEYWORD_TRACKBALL) >= 0)
&& args.length == 12) {
try { try {
long downTime = Long.parseLong(st.nextToken()); long downTime = Long.parseLong(args[0]);
long eventTime = Long.parseLong(st.nextToken()); long eventTime = Long.parseLong(args[1]);
int action = Integer.parseInt(st.nextToken()); int action = Integer.parseInt(args[2]);
float x = Float.parseFloat(st.nextToken()); float x = Float.parseFloat(args[3]);
float y = Float.parseFloat(st.nextToken()); float y = Float.parseFloat(args[4]);
float pressure = Float.parseFloat(st.nextToken()); float pressure = Float.parseFloat(args[5]);
float size = Float.parseFloat(st.nextToken()); float size = Float.parseFloat(args[6]);
int metaState = Integer.parseInt(st.nextToken()); int metaState = Integer.parseInt(args[7]);
float xPrecision = Float.parseFloat(st.nextToken()); float xPrecision = Float.parseFloat(args[8]);
float yPrecision = Float.parseFloat(st.nextToken()); float yPrecision = Float.parseFloat(args[9]);
int device = Integer.parseInt(st.nextToken()); int device = Integer.parseInt(args[10]);
int edgeFlags = Integer.parseInt(st.nextToken()); int edgeFlags = Integer.parseInt(args[11]);
int type = MonkeyEvent.EVENT_TYPE_TRACKBALL; int type = MonkeyEvent.EVENT_TYPE_TRACKBALL;
if (s.indexOf("Pointer") > 0) { if (s.indexOf("Pointer") > 0) {
type = MonkeyEvent.EVENT_TYPE_POINTER; type = MonkeyEvent.EVENT_TYPE_POINTER;
} }
MonkeyMotionEvent e = MonkeyMotionEvent e = new MonkeyMotionEvent(type, downTime, eventTime, action, x,
new MonkeyMotionEvent(type, downTime, eventTime, action, x, y, pressure, y, pressure, size, metaState, xPrecision, yPrecision, device, edgeFlags);
size, metaState, xPrecision, yPrecision, device, edgeFlags);
mQ.addLast(e); mQ.addLast(e);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
// we ignore this event
} }
} else if (s.indexOf(EVENT_KEYWORD_FLIP) >= 0) { return;
boolean keyboardOpen = Boolean.parseBoolean(st.nextToken()); }
// Handle flip events
if (s.indexOf(EVENT_KEYWORD_FLIP) >= 0 && args.length == 1) {
boolean keyboardOpen = Boolean.parseBoolean(args[0]);
MonkeyFlipEvent e = new MonkeyFlipEvent(keyboardOpen); MonkeyFlipEvent e = new MonkeyFlipEvent(keyboardOpen);
mQ.addLast(e); mQ.addLast(e);
} }
} // Handle launch events
if (s.indexOf(EVENT_KEYWORD_ACTIVITY) >= 0 && args.length == 2) {
private void handleUserEvent(String s, StringTokenizer st) { String pkg_name = args[0];
if (s.indexOf(EVENT_KEYWORD_ACTIVITY) >= 0) { String cl_name = args[1];
String pkg_name = st.nextToken();
String cl_name = st.nextToken();
ComponentName mApp = new ComponentName(pkg_name, cl_name); ComponentName mApp = new ComponentName(pkg_name, cl_name);
MonkeyActivityEvent e = new MonkeyActivityEvent(mApp); MonkeyActivityEvent e = new MonkeyActivityEvent(mApp);
mQ.addLast(e); mQ.addLast(e);
return;
}
} else if (s.indexOf(EVENT_KEYWORD_WAIT) >= 0) { // Handle wait events
long sleeptime = Integer.parseInt(st.nextToken()); if (s.indexOf(EVENT_KEYWORD_WAIT) >= 0 && args.length == 1) {
MonkeyWaitEvent e = new MonkeyWaitEvent(sleeptime); try {
mQ.addLast(e); long sleeptime = Integer.parseInt(args[0]);
MonkeyWaitEvent e = new MonkeyWaitEvent(sleeptime);
mQ.addLast(e);
} catch (NumberFormatException e) {
}
return;
}
} else if (s.indexOf(EVENT_KEYWORD_KEYPRESS) >= 0) { // Handle keypress events
String key_name = st.nextToken(); if (s.indexOf(EVENT_KEYWORD_KEYPRESS) >= 0 && args.length == 1) {
String key_name = args[0];
int keyCode = MonkeySourceRandom.getKeyCode(key_name); int keyCode = MonkeySourceRandom.getKeyCode(key_name);
MonkeyKeyEvent e = new MonkeyKeyEvent(KeyEvent.ACTION_DOWN, keyCode); MonkeyKeyEvent e = new MonkeyKeyEvent(KeyEvent.ACTION_DOWN, keyCode);
mQ.addLast(e); mQ.addLast(e);
e = new MonkeyKeyEvent(KeyEvent.ACTION_UP, keyCode); e = new MonkeyKeyEvent(KeyEvent.ACTION_UP, keyCode);
mQ.addLast(e); mQ.addLast(e);
} else if (s.indexOf(EVENT_KEYWORD_LONGPRESS) >= 0) { return;
// handle the long press }
MonkeyKeyEvent e = new MonkeyKeyEvent(KeyEvent.ACTION_DOWN,
KeyEvent.KEYCODE_DPAD_CENTER); // Handle longpress events
if (s.indexOf(EVENT_KEYWORD_LONGPRESS) >= 0) {
MonkeyKeyEvent e;
e = new MonkeyKeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
mQ.addLast(e); mQ.addLast(e);
MonkeyWaitEvent we = new MonkeyWaitEvent(LONGPRESS_WAIT_TIME); MonkeyWaitEvent we = new MonkeyWaitEvent(LONGPRESS_WAIT_TIME);
mQ.addLast(we); mQ.addLast(we);
e = new MonkeyKeyEvent(KeyEvent.ACTION_UP, e = new MonkeyKeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER);
KeyEvent.KEYCODE_DPAD_CENTER);
mQ.addLast(e); mQ.addLast(e);
} }
} }
@@ -274,23 +299,17 @@ public class MonkeySourceScript implements MonkeyEventSource {
return; return;
} }
StringTokenizer st = new StringTokenizer( String[] args = s.substring(index1 + 1, index2).split(",");
s.substring(index1 + 1, index2), ",");
if (mScriptType.compareTo(USER_EVENT_TYPE) == 0) { handleEvent(s, args);
// User event type
handleUserEvent(s, st);
} else {
// Raw type
handleRawEvent(s,st);
}
} }
private void closeFile() { private void closeFile() {
mFileOpened = false; mFileOpened = false;
if (THIS_DEBUG) { if (THIS_DEBUG) {
System.out.println("closing script file"); System.out.println("closing script file");
} }
try { try {
mFStream.close(); mFStream.close();
mInputStream.close(); mInputStream.close();
@@ -298,20 +317,10 @@ public class MonkeySourceScript implements MonkeyEventSource {
System.out.println(e); System.out.println(e);
} }
} }
/** /**
* add home key press/release event to the queue * read next batch of events from the provided script file
*/ *
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 * @return true if success
*/ */
private boolean readNextBatch() { private boolean readNextBatch() {
@@ -333,149 +342,150 @@ public class MonkeySourceScript implements MonkeyEventSource {
} }
resetValue(); resetValue();
} }
try { try {
while (readCount++ < MAX_ONE_TIME_READS && while (readCount++ < MAX_ONE_TIME_READS && (sLine = mBufferReader.readLine()) != null) {
(sLine = mBufferReader.readLine()) != null) { sLine = sLine.trim();
sLine = sLine.trim();
processLine(sLine); processLine(sLine);
} }
} catch (IOException e) { } catch (IOException e) {
System.err.println(e); System.err.println(e);
return false; return false;
} }
if (sLine == null) { if (sLine == null) {
// to the end of the file // to the end of the file
if (THIS_DEBUG) { if (THIS_DEBUG) {
System.out.println("readNextBatch(): to the end of file"); System.out.println("readNextBatch(): to the end of file");
} }
closeFile(); closeFile();
} }
return true; return true;
} }
/** /**
* sleep for a period of given time, introducing latency among events * sleep for a period of given time, introducing latency among events
*
* @param time to sleep in millisecond * @param time to sleep in millisecond
*/ */
private void needSleep(long time) { private void needSleep(long time) {
if (time < 1) { if (time < 1) {
return; return;
} }
try { try {
Thread.sleep(time); Thread.sleep(time);
} catch (InterruptedException e) { } catch (InterruptedException e) {
} }
} }
/** /**
* check whether we can successfully read the header of the script file * check whether we can successfully read the header of the script file
*/ */
public boolean validate() { public boolean validate() {
boolean b = readNextBatch(); boolean b = readNextBatch();
if (mVerbose > 0) { if (mVerbose > 0) {
System.out.println("Replaying " + mEventCountInScript + System.out.println("Replaying " + mEventCountInScript + " events with speed " + mSpeed);
" events with speed " + mSpeed);
} }
return b; return b;
} }
public void setVerbose(int verbose) { public void setVerbose(int verbose) {
mVerbose = verbose; mVerbose = verbose;
} }
/** /**
* adjust key downtime and eventtime according to both * adjust key downtime and eventtime according to both recorded values and
* recorded values and current system time * current system time
*
* @param e KeyEvent * @param e KeyEvent
*/ */
private void adjustKeyEventTime(MonkeyKeyEvent e) { private void adjustKeyEventTime(MonkeyKeyEvent e) {
if (e.getEventTime() < 0) { if (e.getEventTime() < 0) {
return; return;
} }
long thisDownTime = 0; long thisDownTime = 0;
long thisEventTime = 0; long thisEventTime = 0;
long expectedDelay = 0; long expectedDelay = 0;
if (mLastRecordedEventTime <= 0) { if (mLastRecordedEventTime <= 0) {
// first time event // first time event
thisDownTime = SystemClock.uptimeMillis(); thisDownTime = SystemClock.uptimeMillis();
thisEventTime = thisDownTime; thisEventTime = thisDownTime;
} else { } else {
if (e.getDownTime() != mLastRecordedDownTimeKey) { if (e.getDownTime() != mLastRecordedDownTimeKey) {
thisDownTime = e.getDownTime(); thisDownTime = e.getDownTime();
} else { } else {
thisDownTime = mLastExportDownTimeKey; thisDownTime = mLastExportDownTimeKey;
} }
expectedDelay = (long) ((e.getEventTime() - expectedDelay = (long) ((e.getEventTime() - mLastRecordedEventTime) * mSpeed);
mLastRecordedEventTime) * mSpeed);
thisEventTime = mLastExportEventTime + expectedDelay; thisEventTime = mLastExportEventTime + expectedDelay;
// add sleep to simulate everything in recording // add sleep to simulate everything in recording
needSleep(expectedDelay - SLEEP_COMPENSATE_DIFF); needSleep(expectedDelay - SLEEP_COMPENSATE_DIFF);
} }
mLastRecordedDownTimeKey = e.getDownTime(); mLastRecordedDownTimeKey = e.getDownTime();
mLastRecordedEventTime = e.getEventTime(); mLastRecordedEventTime = e.getEventTime();
e.setDownTime(thisDownTime); e.setDownTime(thisDownTime);
e.setEventTime(thisEventTime); e.setEventTime(thisEventTime);
mLastExportDownTimeKey = thisDownTime; mLastExportDownTimeKey = thisDownTime;
mLastExportEventTime = thisEventTime; mLastExportEventTime = thisEventTime;
} }
/** /**
* adjust motion downtime and eventtime according to both * adjust motion downtime and eventtime according to both recorded values
* recorded values and current system time * and current system time
*
* @param e KeyEvent * @param e KeyEvent
*/ */
private void adjustMotionEventTime(MonkeyMotionEvent e) { private void adjustMotionEventTime(MonkeyMotionEvent e) {
if (e.getEventTime() < 0) { if (e.getEventTime() < 0) {
return; return;
} }
long thisDownTime = 0; long thisDownTime = 0;
long thisEventTime = 0; long thisEventTime = 0;
long expectedDelay = 0; long expectedDelay = 0;
if (mLastRecordedEventTime <= 0) { if (mLastRecordedEventTime <= 0) {
// first time event // first time event
thisDownTime = SystemClock.uptimeMillis(); thisDownTime = SystemClock.uptimeMillis();
thisEventTime = thisDownTime; thisEventTime = thisDownTime;
} else { } else {
if (e.getDownTime() != mLastRecordedDownTimeMotion) { if (e.getDownTime() != mLastRecordedDownTimeMotion) {
thisDownTime = e.getDownTime(); thisDownTime = e.getDownTime();
} else { } else {
thisDownTime = mLastExportDownTimeMotion; thisDownTime = mLastExportDownTimeMotion;
} }
expectedDelay = (long) ((e.getEventTime() - expectedDelay = (long) ((e.getEventTime() - mLastRecordedEventTime) * mSpeed);
mLastRecordedEventTime) * mSpeed);
thisEventTime = mLastExportEventTime + expectedDelay; thisEventTime = mLastExportEventTime + expectedDelay;
// add sleep to simulate everything in recording // add sleep to simulate everything in recording
needSleep(expectedDelay - SLEEP_COMPENSATE_DIFF); needSleep(expectedDelay - SLEEP_COMPENSATE_DIFF);
} }
mLastRecordedDownTimeMotion = e.getDownTime(); mLastRecordedDownTimeMotion = e.getDownTime();
mLastRecordedEventTime = e.getEventTime(); mLastRecordedEventTime = e.getEventTime();
e.setDownTime(thisDownTime); e.setDownTime(thisDownTime);
e.setEventTime(thisEventTime); e.setEventTime(thisEventTime);
mLastExportDownTimeMotion = thisDownTime; mLastExportDownTimeMotion = thisDownTime;
mLastExportEventTime = thisEventTime; mLastExportEventTime = thisEventTime;
} }
/** /**
* if the queue is empty, we generate events first * if the queue is empty, we generate events first
* @return the first event in the queue, if null, indicating the system crashes *
* @return the first event in the queue, if null, indicating the system
* crashes
*/ */
public MonkeyEvent getNextEvent() { public MonkeyEvent getNextEvent() {
long recordedEventTime = -1; long recordedEventTime = -1;
if (mQ.isEmpty()) { if (mQ.isEmpty()) {
readNextBatch(); readNextBatch();
} }
MonkeyEvent e = mQ.getFirst(); MonkeyEvent e = mQ.getFirst();
mQ.removeFirst(); mQ.removeFirst();
if (e.getEventType() == MonkeyEvent.EVENT_TYPE_KEY) { if (e.getEventType() == MonkeyEvent.EVENT_TYPE_KEY) {
adjustKeyEventTime((MonkeyKeyEvent) e); adjustKeyEventTime((MonkeyKeyEvent) e);
} else if (e.getEventType() == MonkeyEvent.EVENT_TYPE_POINTER || } else if (e.getEventType() == MonkeyEvent.EVENT_TYPE_POINTER
e.getEventType() == MonkeyEvent.EVENT_TYPE_TRACKBALL) { || e.getEventType() == MonkeyEvent.EVENT_TYPE_TRACKBALL) {
adjustMotionEventTime((MonkeyMotionEvent) e); adjustMotionEventTime((MonkeyMotionEvent) e);
} }
return e; return e;