| // Copyright 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package org.chromium.content.browser.test.util; |
| |
| import android.app.Activity; |
| import android.app.Instrumentation; |
| import android.os.SystemClock; |
| import android.test.InstrumentationTestCase; |
| import android.view.MotionEvent; |
| import android.view.View; |
| import android.view.ViewConfiguration; |
| |
| /** |
| * Collection of utilities for generating touch events. |
| * Based on android.test.TouchUtils, but slightly more flexible (allows to |
| * specify coordinates for longClick, splits drag operation in three stages, etc). |
| */ |
| public class TestTouchUtils extends android.test.TouchUtils { |
| /** |
| * Returns the absolute location in screen coordinates from location relative |
| * to view. |
| * @param v The view the coordinates are relative to. |
| * @param x Relative x location. |
| * @param y Relative y location. |
| * @return the absolute x and y location in an array. |
| */ |
| public static int[] getAbsoluteLocationFromRelative(View v, int x, int y) { |
| int location[] = new int[2]; |
| v.getLocationOnScreen(location); |
| location[0] += x; |
| location[1] += y; |
| return location; |
| } |
| |
| private static void sendAction(Instrumentation instrumentation, int action, long downTime, |
| float x, float y) { |
| long eventTime = SystemClock.uptimeMillis(); |
| MotionEvent event = MotionEvent.obtain(downTime, eventTime, action, x, y, 0); |
| instrumentation.sendPointerSync(event); |
| instrumentation.waitForIdleSync(); |
| } |
| |
| /** |
| * Sends (synchronously) a single click to an absolute screen coordinates. |
| * |
| * @param instrumentation Instrumentation object used by the test. |
| * @param x Screen absolute x location. |
| * @param y Screen absolute y location. |
| */ |
| public static void singleClick(Instrumentation instrumentation, float x, float y) { |
| long downTime = SystemClock.uptimeMillis(); |
| sendAction(instrumentation, MotionEvent.ACTION_DOWN, downTime, x, y); |
| sendAction(instrumentation, MotionEvent.ACTION_UP, downTime, x, y); |
| } |
| |
| /** |
| * Sends (synchronously) a single click to the View at the specified coordinates. |
| * |
| * @param instrumentation Instrumentation object used by the test. |
| * @param v The view the coordinates are relative to. |
| * @param x Relative x location to the view. |
| * @param y Relative y location to the view. |
| */ |
| public static void singleClickView(Instrumentation instrumentation, View v, int x, int y) { |
| int location[] = getAbsoluteLocationFromRelative(v, x, y); |
| int absoluteX = location[0]; |
| int absoluteY = location[1]; |
| singleClick(instrumentation, absoluteX, absoluteY); |
| } |
| |
| /** |
| * Sends (synchronously) a single click to the center of the View. |
| * |
| * @param instrumentation Instrumentation object used by the test. |
| * @param v The view the coordinates are relative to. |
| */ |
| public static void singleClickView(Instrumentation instrumentation, View v) { |
| int x = v.getWidth() / 2; |
| int y = v.getHeight() / 2; |
| singleClickView(instrumentation, v, x, y); |
| } |
| |
| /** |
| * Sleeps for at least the length of the double tap timeout. |
| * |
| * @param instrumentation Instrumentation object used by the test. |
| */ |
| public static void sleepForDoubleTapTimeout(Instrumentation instrumentation) { |
| SystemClock.sleep((long) (ViewConfiguration.getDoubleTapTimeout() * 1.5)); |
| } |
| |
| /** |
| * Sends (synchronously) a long click to the View at the specified coordinates. |
| * |
| * @param instrumentation Instrumentation object used by the test. |
| * @param v The view the coordinates are relative to. |
| * @param x Relative x location to the view. |
| * @param y Relative y location to the view. |
| */ |
| public static void longClickView(Instrumentation instrumentation, View v, int x, int y) { |
| int location[] = getAbsoluteLocationFromRelative(v, x, y); |
| int absoluteX = location[0]; |
| int absoluteY = location[1]; |
| |
| long downTime = SystemClock.uptimeMillis(); |
| sendAction(instrumentation, MotionEvent.ACTION_DOWN, downTime, absoluteX, absoluteY); |
| SystemClock.sleep((long) (ViewConfiguration.getLongPressTimeout() * 1.5)); |
| sendAction(instrumentation, MotionEvent.ACTION_UP, downTime, absoluteX, absoluteY); |
| } |
| |
| /** |
| * Sends (synchronously) a long click to the View at its center. |
| * |
| * @param instrumentation Instrumentation object used by the test. |
| * @param v The view to long click. |
| */ |
| public static void longClickView(Instrumentation instrumentation, View v) { |
| int x = v.getWidth() / 2; |
| int y = v.getHeight() / 2; |
| longClickView(instrumentation, v, x, y); |
| } |
| |
| /** |
| * Starts (synchronously) a drag motion. Normally followed by dragTo() and dragEnd(). |
| * |
| * @param instrumentation Instrumentation object used by the test. |
| * @param x The x location. |
| * @param y The y location. |
| * @return The downTime of the triggered event. |
| */ |
| public static long dragStart(Instrumentation instrumentation, float x, float y) { |
| long downTime = SystemClock.uptimeMillis(); |
| sendAction(instrumentation, MotionEvent.ACTION_DOWN, downTime, x, y); |
| return downTime; |
| } |
| |
| /** |
| * Drags / moves (synchronously) to the specified coordinates. Normally preceeded by |
| * dragStart() and followed by dragEnd() |
| * |
| * @param instrumentation Instrumentation object used by the test. |
| * @param fromX The relative x-coordinate of the start point of the drag. |
| * @param toX The relative x-coordinate of the end point of the drag. |
| * @param fromY The relative y-coordinate of the start point of the drag. |
| * @param toY The relative y-coordinate of the end point of the drag. |
| * @param stepCount The total number of motion events that should be generated during the drag. |
| * @param downTime The initial time of the drag, in ms. |
| */ |
| public static void dragTo(Instrumentation instrumentation, float fromX, float toX, float fromY, |
| float toY, int stepCount, long downTime) { |
| float x = fromX; |
| float y = fromY; |
| float yStep = (toY - fromY) / stepCount; |
| float xStep = (toX - fromX) / stepCount; |
| for (int i = 0; i < stepCount; ++i) { |
| y += yStep; |
| x += xStep; |
| sendAction(instrumentation, MotionEvent.ACTION_MOVE, downTime, x, y); |
| } |
| } |
| |
| /** |
| * Finishes (synchronously) a drag / move at the specified coordinate. |
| * Normally preceeded by dragStart() and dragTo(). |
| * |
| * @param instrumentation Instrumentation object used by the test. |
| * @param x The x location. |
| * @param y The y location. |
| * @param downTime The initial time of the drag, in ms. |
| */ |
| public static void dragEnd(Instrumentation instrumentation, float x, float y, long downTime) { |
| sendAction(instrumentation, MotionEvent.ACTION_UP, downTime, x, y); |
| } |
| |
| /** |
| * Performs a drag between the given coordinates, specified relative to the given view. |
| * This method makes calls to dragStart, dragTo and dragEnd. |
| * |
| * @param instrumentation Instrumentation object used by the test. |
| * @param view The view the coordinates are relative to. |
| * @param fromX The relative x-coordinate of the start point of the drag. |
| * @param toX The relative x-coordinate of the end point of the drag. |
| * @param fromY The relative y-coordinate of the start point of the drag. |
| * @param toY The relative y-coordinate of the end point of the drag. |
| * @param stepCount The total number of motion events that should be generated during the drag. |
| */ |
| public static void dragCompleteView(Instrumentation instrumentation, View view, |
| int fromX, int toX, int fromY, int toY, int stepCount) { |
| int fromLocation[] = getAbsoluteLocationFromRelative(view, fromX, fromY); |
| int toLocation[] = getAbsoluteLocationFromRelative(view, toX, toY); |
| long downTime = dragStart(instrumentation, fromLocation[0], fromLocation[1]); |
| dragTo(instrumentation, fromLocation[0], toLocation[0], fromLocation[1], toLocation[1], |
| stepCount, downTime); |
| dragEnd(instrumentation, toLocation[0], toLocation[1], downTime); |
| } |
| |
| /** |
| * Calls performClick on a View on the main UI thread. |
| * |
| * @param instrumentation Instrumentation object used by the test. |
| * @param v The view to call performClick on. |
| */ |
| public static void performClickOnMainSync(Instrumentation instrumentation, final View v) { |
| instrumentation.runOnMainSync(new Runnable() { |
| @Override |
| public void run() { |
| v.performClick(); |
| } |
| }); |
| } |
| |
| /** |
| * Clicks on specified view in the given {@link Activity}. |
| * |
| * @param test The test case using this utility. |
| * @param activity Activity containing the view. |
| * @param id The view to be clicked. |
| * @return {@code true} if a view with the given id exists. |
| */ |
| public static boolean clickById(InstrumentationTestCase test, Activity activity, int id) { |
| View v = activity.findViewById(id); |
| if (v == null) return false; |
| clickView(test, v); |
| return true; |
| } |
| } |