MonkeySourceRandompublic class MonkeySourceRandom extends Object implements MonkeyEventSource
Fields Summary |
---|
private static final int[] | NAV_KEYSKey events that move around the UI. | private static final int[] | MAJOR_NAV_KEYSKey events that perform major navigation options (so shouldn't be sent
as much). | private static final int[] | SYS_KEYSKey events that perform system operations. | private static final String[] | KEY_NAMESNice names for all key events. | public static final int | FACTOR_TOUCH | public static final int | FACTOR_MOTION | public static final int | FACTOR_TRACKBALL | public static final int | FACTOR_NAV | public static final int | FACTOR_MAJORNAV | public static final int | FACTOR_SYSOPS | public static final int | FACTOR_APPSWITCH | public static final int | FACTOR_FLIP | public static final int | FACTOR_ANYTHING | public static final int | FACTORZ_COUNT | private float[] | mFactorspercentages for each type of event. These will be remapped to working
values after we read any optional values. | private ArrayList | mMainApps | private int | mEventCount | private LinkedList | mQ | private Random | mRandom | private int | mVerbose | private long | mThrottle | private boolean | mKeyboardOpen |
Constructors Summary |
---|
public MonkeySourceRandom(long seed, ArrayList MainApps, long throttle)
// 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;
mThrottle = throttle;
|
Methods Summary |
---|
private void | addThrottle()
mQ.addLast(new MonkeyThrottleEvent(MonkeyEvent.EVENT_TYPE_THROTTLE, mThrottle));
| private boolean | adjustEventFactors()Adjust the percentages (after applying user values) and then normalize to a 0..1 scale.
// 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;
| public void | generateActivity()generate an activity event
MonkeyActivityEvent e = new MonkeyActivityEvent(mMainApps.get(
mRandom.nextInt(mMainApps.size())));
mQ.addLast(e);
| private void | generateEvents()generate a random event based on mFactor
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);
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);
}
MonkeyKeyEvent e = new MonkeyKeyEvent(KeyEvent.ACTION_DOWN, lastKey);
mQ.addLast(e);
e = new MonkeyKeyEvent(KeyEvent.ACTION_UP, lastKey);
mQ.addLast(e);
addThrottle();
| private void | generateMotionEvent(java.util.Random random, boolean motionEvent)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).
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);
addThrottle();
| private void | generateTrackballEvent(java.util.Random random)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).
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);
}
addThrottle();
| public static java.lang.String | getKeyName(int keycode)
return KEY_NAMES[keycode];
| public static java.lang.String | getLastKeyName()
return KEY_NAMES[KeyEvent.getMaxKeyCode() + 1];
| public MonkeyEvent | getNextEvent()if the queue is empty, we generate events first
if (mQ.isEmpty()) {
generateEvents();
}
mEventCount++;
MonkeyEvent e = mQ.getFirst();
mQ.removeFirst();
return e;
| public void | setFactors(float[] factors)set the 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;
| public void | setVerbose(int verbose)
mVerbose = verbose;
| public boolean | validate()
//check factors
return adjustEventFactors();
|
|