TestTouchUtils.java revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5package org.chromium.content.browser.test.util;
6
7import android.app.Activity;
8import android.app.Instrumentation;
9import android.os.SystemClock;
10import android.test.InstrumentationTestCase;
11import android.view.MotionEvent;
12import android.view.View;
13import android.view.ViewConfiguration;
14
15/**
16 * Collection of utilities for generating touch events.
17 * Based on android.test.TouchUtils, but slightly more flexible (allows to
18 * specify coordinates for longClick, splits drag operation in three stages, etc).
19 */
20public class TestTouchUtils extends android.test.TouchUtils {
21    /**
22     * Returns the absolute location in screen coordinates from location relative
23     * to view.
24     * @param v The view the coordinates are relative to.
25     * @param x Relative x location.
26     * @param y Relative y location.
27     * @return the absolute x and y location in an array.
28     */
29    public static int[] getAbsoluteLocationFromRelative(View v, int x, int y) {
30        int location[] = new int[2];
31        v.getLocationOnScreen(location);
32        location[0] += x;
33        location[1] += y;
34        return location;
35    }
36
37    private static void sendAction(Instrumentation instrumentation, int action, long downTime,
38            float x, float y) {
39        long eventTime = SystemClock.uptimeMillis();
40        MotionEvent event = MotionEvent.obtain(downTime, eventTime, action, x, y, 0);
41        instrumentation.sendPointerSync(event);
42        instrumentation.waitForIdleSync();
43    }
44
45    /**
46     * Sends (synchronously) a single click to an absolute screen coordinates.
47     *
48     * @param instrumentation Instrumentation object used by the test.
49     * @param x Screen absolute x location.
50     * @param y Screen absolute y location.
51     */
52    public static void singleClick(Instrumentation instrumentation, float x, float y) {
53        long downTime = SystemClock.uptimeMillis();
54        sendAction(instrumentation, MotionEvent.ACTION_DOWN, downTime, x, y);
55        sendAction(instrumentation, MotionEvent.ACTION_UP, downTime, x, y);
56    }
57
58    /**
59     * Sends (synchronously) a single click to the View at the specified coordinates.
60     *
61     * @param instrumentation Instrumentation object used by the test.
62     * @param v The view the coordinates are relative to.
63     * @param x Relative x location to the view.
64     * @param y Relative y location to the view.
65     */
66    public static void singleClickView(Instrumentation instrumentation, View v, int x, int y) {
67        int location[] = getAbsoluteLocationFromRelative(v, x, y);
68        int absoluteX = location[0];
69        int absoluteY = location[1];
70        singleClick(instrumentation, absoluteX, absoluteY);
71    }
72
73    /**
74     * Sends (synchronously) a single click to the center of the View.
75     *
76     * @param instrumentation Instrumentation object used by the test.
77     * @param v The view the coordinates are relative to.
78     */
79    public static void singleClickView(Instrumentation instrumentation, View v) {
80        int x = v.getWidth() / 2;
81        int y = v.getHeight() / 2;
82        singleClickView(instrumentation, v, x, y);
83    }
84
85    /**
86     * Sleeps for at least the length of the double tap timeout.
87     *
88     * @param instrumentation Instrumentation object used by the test.
89     */
90    public static void sleepForDoubleTapTimeout(Instrumentation instrumentation) {
91        SystemClock.sleep((long)(ViewConfiguration.getDoubleTapTimeout() * 1.5));
92    }
93
94    /**
95     * Sends (synchronously) a long click to the View at the specified coordinates.
96     *
97     * @param instrumentation Instrumentation object used by the test.
98     * @param v The view the coordinates are relative to.
99     * @param x Relative x location to the view.
100     * @param y Relative y location to the view.
101     */
102    public static void longClickView(Instrumentation instrumentation, View v, int x, int y) {
103        int location[] = getAbsoluteLocationFromRelative(v, x, y);
104        int absoluteX = location[0];
105        int absoluteY = location[1];
106
107        long downTime = SystemClock.uptimeMillis();
108        sendAction(instrumentation, MotionEvent.ACTION_DOWN, downTime, absoluteX, absoluteY);
109        SystemClock.sleep((long)(ViewConfiguration.getLongPressTimeout() * 1.5));
110        sendAction(instrumentation, MotionEvent.ACTION_UP, downTime, absoluteX, absoluteY);
111    }
112
113    /**
114     * Starts (synchronously) a drag motion. Normally followed by dragTo() and dragEnd().
115     *
116     * @param instrumentation Instrumentation object used by the test.
117     * @param x The x location.
118     * @param y The y location.
119     * @return The downTime of the triggered event.
120     */
121    public static long dragStart(Instrumentation instrumentation, float x, float y) {
122        long downTime = SystemClock.uptimeMillis();
123        sendAction(instrumentation, MotionEvent.ACTION_DOWN, downTime, x, y);
124        return downTime;
125    }
126
127    /**
128     * Drags / moves (synchronously) to the specified coordinates. Normally preceeded by
129     * dragStart() and followed by dragEnd()
130     *
131     * @param instrumentation Instrumentation object used by the test.
132     * @param fromX The relative x-coordinate of the start point of the drag.
133     * @param toX The relative x-coordinate of the end point of the drag.
134     * @param fromY The relative y-coordinate of the start point of the drag.
135     * @param toY The relative y-coordinate of the end point of the drag.
136     * @param stepCount The total number of motion events that should be generated during the drag.
137     * @param downTime The initial time of the drag, in ms.
138     */
139    public static void dragTo(Instrumentation instrumentation, float fromX, float toX, float fromY,
140            float toY, int stepCount, long downTime) {
141        float x = fromX;
142        float y = fromY;
143        float yStep = (toY - fromY) / stepCount;
144        float xStep = (toX - fromX) / stepCount;
145        for (int i = 0; i < stepCount; ++i) {
146            y += yStep;
147            x += xStep;
148            sendAction(instrumentation, MotionEvent.ACTION_MOVE, downTime, x, y);
149        }
150    }
151
152    /**
153     * Finishes (synchronously) a drag / move at the specified coordinate.
154     * Normally preceeded by dragStart() and dragTo().
155     *
156     * @param instrumentation Instrumentation object used by the test.
157     * @param x The x location.
158     * @param y The y location.
159     * @param downTime The initial time of the drag, in ms.
160     */
161    public static void dragEnd(Instrumentation instrumentation, float x, float y, long downTime) {
162        sendAction(instrumentation, MotionEvent.ACTION_UP, downTime, x, y);
163    }
164
165    /**
166     * Performs a drag between the given coordinates, specified relative to the given view.
167     * This method makes calls to dragStart, dragTo and dragEnd.
168     *
169     * @param instrumentation Instrumentation object used by the test.
170     * @param view The view the coordinates are relative to.
171     * @param fromX The relative x-coordinate of the start point of the drag.
172     * @param toX The relative x-coordinate of the end point of the drag.
173     * @param fromY The relative y-coordinate of the start point of the drag.
174     * @param toY The relative y-coordinate of the end point of the drag.
175     * @param stepCount The total number of motion events that should be generated during the drag.
176     */
177    public static void dragCompleteView(Instrumentation instrumentation, View view,
178            int fromX, int toX, int fromY, int toY, int stepCount) {
179        int fromLocation[] = getAbsoluteLocationFromRelative(view, fromX, fromY);
180        int toLocation[] = getAbsoluteLocationFromRelative(view, toX, toY);
181        long downTime = dragStart(instrumentation, fromLocation[0], fromLocation[1]);
182        dragTo(instrumentation, fromLocation[0], toLocation[0], fromLocation[1], toLocation[1],
183                stepCount, downTime);
184        dragEnd(instrumentation, toLocation[0], toLocation[1], downTime);
185    }
186
187    /**
188     * Calls performClick on a View on the main UI thread.
189     *
190     * @param instrumentation Instrumentation object used by the test.
191     * @param v The view to call performClick on.
192     */
193    public static void performClickOnMainSync(Instrumentation instrumentation, final View v) {
194        instrumentation.runOnMainSync(new Runnable() {
195            @Override
196            public void run() {
197                v.performClick();
198            }
199        });
200    }
201
202    /**
203     * Clicks on specified view in the given {@link Activity}.
204     *
205     * @param test The test case using this utility.
206     * @param activity Activity containing the view.
207     * @param id The view to be clicked.
208     * @return {@code true} if a view with the given id exists.
209     */
210    public static boolean clickById(InstrumentationTestCase test, Activity activity, int id) {
211        View v = activity.findViewById(id);
212        if (v == null) return false;
213        clickView(test, v);
214        return true;
215    }
216}
217