/** * Generates a random trackball event. This consists of a sequence of small moves, followed by an * optional single click. * * <p>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); for (int i = 0; i < 10; ++i) { // generate a small random step int dX = random.nextInt(10) - 5; int dY = random.nextInt(10) - 5; mQ.addLast( new MonkeyTrackballEvent(MotionEvent.ACTION_MOVE) .addPointer(0, dX, dY) .setIntermediateNote(i > 0)); } // 10% of trackball moves end with a click if (0 == random.nextInt(10)) { long downAt = SystemClock.uptimeMillis(); mQ.addLast( new MonkeyTrackballEvent(MotionEvent.ACTION_DOWN) .setDownTime(downAt) .addPointer(0, 0, 0) .setIntermediateNote(true)); mQ.addLast( new MonkeyTrackballEvent(MotionEvent.ACTION_UP) .setDownTime(downAt) .addPointer(0, 0, 0) .setIntermediateNote(false)); } }
/** * Generates a random trackball event. This consists of a sequence of small moves, followed by an * optional single click. * * <p>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); } }
/** * 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; }
/** generate a random event based on mFactor */ private void generateEvents() { float cls = mRandom.nextFloat(); int lastKey = 0; if (cls < mFactors[FACTOR_TOUCH]) { generatePointerEvent(mRandom, GESTURE_TAP); return; } else if (cls < mFactors[FACTOR_MOTION]) { generatePointerEvent(mRandom, GESTURE_DRAG); return; } else if (cls < mFactors[FACTOR_PINCHZOOM]) { generatePointerEvent(mRandom, GESTURE_PINCH_OR_ZOOM); return; } else if (cls < mFactors[FACTOR_TRACKBALL]) { generateTrackballEvent(mRandom); return; } else if (cls < mFactors[FACTOR_ROTATION]) { generateRotationEvent(mRandom); return; } // The remaining event categories are injected as key events for (; ; ) { 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); } if (lastKey != KeyEvent.KEYCODE_POWER && lastKey != KeyEvent.KEYCODE_ENDCALL && PHYSICAL_KEY_EXISTS[lastKey]) { break; } } MonkeyKeyEvent e = new MonkeyKeyEvent(KeyEvent.ACTION_DOWN, lastKey); mQ.addLast(e); e = new MonkeyKeyEvent(KeyEvent.ACTION_UP, lastKey); 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 do { 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); } } while (!PHYSICAL_KEY_EXISTS[lastKey]); MonkeyKeyEvent e = new MonkeyKeyEvent(KeyEvent.ACTION_DOWN, lastKey); mQ.addLast(e); e = new MonkeyKeyEvent(KeyEvent.ACTION_UP, lastKey); mQ.addLast(e); }
/** * Generates a random motion event. This method counts a down, move, and up as multiple events. * * <p>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); }
/** generate an activity event */ public void generateActivity() { MonkeyActivityEvent e = new MonkeyActivityEvent(mMainApps.get(mRandom.nextInt(mMainApps.size()))); mQ.addLast(e); }
/** * Generates a random screen rotation event. * * @param random Random number source for rotation degree. */ private void generateRotationEvent(Random random) { mQ.addLast( new MonkeyRotationEvent( SCREEN_ROTATION_DEGREES[random.nextInt(SCREEN_ROTATION_DEGREES.length)], random.nextBoolean())); }
/** * Generates a random motion event. This method counts a down, move, and up as multiple events. * * <p>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 gesture The gesture to perform. */ private void generatePointerEvent(Random random, int gesture) { Display display = WindowManagerImpl.getDefault().getDefaultDisplay(); PointF p1 = randomPoint(random, display); PointF v1 = randomVector(random); long downAt = SystemClock.uptimeMillis(); mQ.addLast( new MonkeyTouchEvent(MotionEvent.ACTION_DOWN) .setDownTime(downAt) .addPointer(0, p1.x, p1.y) .setIntermediateNote(false)); // sometimes we'll move during the touch if (gesture == GESTURE_DRAG) { int count = random.nextInt(10); for (int i = 0; i < count; i++) { randomWalk(random, display, p1, v1); mQ.addLast( new MonkeyTouchEvent(MotionEvent.ACTION_MOVE) .setDownTime(downAt) .addPointer(0, p1.x, p1.y) .setIntermediateNote(true)); } } else if (gesture == GESTURE_PINCH_OR_ZOOM) { PointF p2 = randomPoint(random, display); PointF v2 = randomVector(random); randomWalk(random, display, p1, v1); mQ.addLast( new MonkeyTouchEvent( MotionEvent.ACTION_POINTER_DOWN | (1 << MotionEvent.ACTION_POINTER_INDEX_SHIFT)) .setDownTime(downAt) .addPointer(0, p1.x, p1.y) .addPointer(1, p2.x, p2.y) .setIntermediateNote(true)); int count = random.nextInt(10); for (int i = 0; i < count; i++) { randomWalk(random, display, p1, v1); randomWalk(random, display, p2, v2); mQ.addLast( new MonkeyTouchEvent(MotionEvent.ACTION_MOVE) .setDownTime(downAt) .addPointer(0, p1.x, p1.y) .addPointer(1, p2.x, p2.y) .setIntermediateNote(true)); } randomWalk(random, display, p1, v1); randomWalk(random, display, p2, v2); mQ.addLast( new MonkeyTouchEvent( MotionEvent.ACTION_POINTER_UP | (1 << MotionEvent.ACTION_POINTER_INDEX_SHIFT)) .setDownTime(downAt) .addPointer(0, p1.x, p1.y) .addPointer(1, p2.x, p2.y) .setIntermediateNote(true)); } randomWalk(random, display, p1, v1); mQ.addLast( new MonkeyTouchEvent(MotionEvent.ACTION_UP) .setDownTime(downAt) .addPointer(0, p1.x, p1.y) .setIntermediateNote(false)); }