TouchUtils.java revision 12093976a4842a795491cfd2b1d3b71e18503f2d
1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.test;
18
19import android.app.Activity;
20import android.app.Instrumentation;
21import android.os.SystemClock;
22import android.view.Display;
23import android.view.Gravity;
24import android.view.MotionEvent;
25import android.view.View;
26import android.view.ViewConfiguration;
27import android.view.ViewGroup;
28
29/**
30 * Reusable methods for generating touch events. These methods can be used with
31 * InstrumentationTestCase or ActivityInstrumentationTestCase2 to simulate user interaction with
32 * the application through a touch screen.
33 */
34public class TouchUtils {
35
36    /**
37     * Simulate touching in the center of the screen and dragging one quarter of the way down
38     * @param test The test case that is being run
39     *
40     * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
41     * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
42     * configuring the Activity under test
43     */
44    @Deprecated
45    public static void dragQuarterScreenDown(ActivityInstrumentationTestCase test) {
46        dragQuarterScreenDown(test, test.getActivity());
47    }
48
49    /**
50     * Simulate touching in the center of the screen and dragging one quarter of the way down
51     * @param test The test case that is being run
52     * @param activity The activity that is in the foreground of the test case
53     */
54    public static void dragQuarterScreenDown(InstrumentationTestCase test, Activity activity) {
55        Display display = activity.getWindowManager().getDefaultDisplay();
56        int screenHeight = display.getHeight();
57        int screenWidth = display.getWidth();
58
59        final float x = screenWidth / 2.0f;
60        final float fromY = screenHeight * 0.5f;
61        final float toY = screenHeight * 0.75f;
62
63        drag(test, x, x, fromY, toY, 4);
64    }
65
66    /**
67     * Simulate touching in the center of the screen and dragging one quarter of the way up
68     * @param test The test case that is being run
69     *
70     * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
71     * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
72     * configuring the Activity under test
73     */
74    @Deprecated
75    public static void dragQuarterScreenUp(ActivityInstrumentationTestCase test) {
76        dragQuarterScreenUp(test, test.getActivity());
77    }
78
79    /**
80     * Simulate touching in the center of the screen and dragging one quarter of the way up
81     * @param test The test case that is being run
82     * @param activity The activity that is in the foreground of the test case
83     */
84    public static void dragQuarterScreenUp(InstrumentationTestCase test, Activity activity) {
85        Display display = activity.getWindowManager().getDefaultDisplay();
86        int screenHeight = display.getHeight();
87        int screenWidth = display.getWidth();
88
89        final float x = screenWidth / 2.0f;
90        final float fromY = screenHeight * 0.5f;
91        final float toY = screenHeight * 0.25f;
92
93        drag(test, x, x, fromY, toY, 4);
94    }
95
96    /**
97     * Scroll a ViewGroup to the bottom by repeatedly calling
98     * {@link #dragQuarterScreenUp(InstrumentationTestCase, Activity)}
99     *
100     * @param test The test case that is being run
101     * @param v The ViewGroup that should be dragged
102     *
103     * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
104     * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
105     * configuring the Activity under test
106     */
107    @Deprecated
108    public static void scrollToBottom(ActivityInstrumentationTestCase test, ViewGroup v) {
109        scrollToBottom(test, test.getActivity(), v);
110    }
111
112    /**
113     * Scroll a ViewGroup to the bottom by repeatedly calling
114     * {@link #dragQuarterScreenUp(InstrumentationTestCase, Activity)}
115     *
116     * @param test The test case that is being run
117     * @param activity The activity that is in the foreground of the test case
118     * @param v The ViewGroup that should be dragged
119     */
120    public static void scrollToBottom(InstrumentationTestCase test, Activity activity,
121            ViewGroup v) {
122        View firstChild;
123        int firstId = Integer.MIN_VALUE;
124        int firstTop = Integer.MIN_VALUE;
125        int prevId;
126        int prevTop;
127        do {
128            prevId = firstId;
129            prevTop = firstTop;
130            TouchUtils.dragQuarterScreenUp(test, activity);
131            firstChild = v.getChildAt(0);
132            firstId = firstChild.getId();
133            firstTop = firstChild.getTop();
134        } while ((prevId != firstId) || (prevTop != firstTop));
135    }
136
137    /**
138     * Scroll a ViewGroup to the top by repeatedly calling
139     * {@link #dragQuarterScreenDown(InstrumentationTestCase, Activity)}
140     *
141     * @param test The test case that is being run
142     * @param v The ViewGroup that should be dragged
143     *
144     * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
145     * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
146     * configuring the Activity under test
147     */
148    @Deprecated
149    public static void scrollToTop(ActivityInstrumentationTestCase test, ViewGroup v) {
150        scrollToTop(test, test.getActivity(), v);
151    }
152
153    /**
154     * Scroll a ViewGroup to the top by repeatedly calling
155     * {@link #dragQuarterScreenDown(InstrumentationTestCase, Activity)}
156     *
157     * @param test The test case that is being run
158     * @param activity The activity that is in the foreground of the test case
159     * @param v The ViewGroup that should be dragged
160     */
161    public static void scrollToTop(InstrumentationTestCase test, Activity activity, ViewGroup v) {
162        View firstChild;
163        int firstId = Integer.MIN_VALUE;
164        int firstTop = Integer.MIN_VALUE;
165        int prevId;
166        int prevTop;
167        do {
168            prevId = firstId;
169            prevTop = firstTop;
170            TouchUtils.dragQuarterScreenDown(test, activity);
171            firstChild = v.getChildAt(0);
172            firstId = firstChild.getId();
173            firstTop = firstChild.getTop();
174        } while ((prevId != firstId) || (prevTop != firstTop));
175    }
176
177    /**
178     * Simulate touching the center of a view and dragging to the bottom of the screen.
179     *
180     * @param test The test case that is being run
181     * @param v The view that should be dragged
182     *
183     * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
184     * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
185     * configuring the Activity under test
186     */
187    @Deprecated
188    public static void dragViewToBottom(ActivityInstrumentationTestCase test, View v) {
189        dragViewToBottom(test, test.getActivity(), v, 4);
190    }
191
192    /**
193     * Simulate touching the center of a view and dragging to the bottom of the screen.
194     *
195     * @param test The test case that is being run
196     * @param activity The activity that is in the foreground of the test case
197     * @param v The view that should be dragged
198     */
199    public static void dragViewToBottom(InstrumentationTestCase test, Activity activity, View v) {
200        dragViewToBottom(test, activity, v, 4);
201    }
202
203    /**
204     * Simulate touching the center of a view and dragging to the bottom of the screen.
205     *
206     * @param test The test case that is being run
207     * @param v The view that should be dragged
208     * @param stepCount How many move steps to include in the drag
209     *
210     * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
211     * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
212     * configuring the Activity under test
213     */
214    @Deprecated
215    public static void dragViewToBottom(ActivityInstrumentationTestCase test, View v,
216            int stepCount) {
217        dragViewToBottom(test, test.getActivity(), v, stepCount);
218    }
219
220    /**
221     * Simulate touching the center of a view and dragging to the bottom of the screen.
222     *
223     * @param test The test case that is being run
224     * @param activity The activity that is in the foreground of the test case
225     * @param v The view that should be dragged
226     * @param stepCount How many move steps to include in the drag
227     */
228    public static void dragViewToBottom(InstrumentationTestCase test, Activity activity, View v,
229            int stepCount) {
230        int screenHeight = activity.getWindowManager().getDefaultDisplay().getHeight();
231
232        int[] xy = new int[2];
233        v.getLocationOnScreen(xy);
234
235        final int viewWidth = v.getWidth();
236        final int viewHeight = v.getHeight();
237
238        final float x = xy[0] + (viewWidth / 2.0f);
239        float fromY = xy[1] + (viewHeight / 2.0f);
240        float toY = screenHeight - 1;
241
242        drag(test, x, x, fromY, toY, stepCount);
243    }
244
245    /**
246     * Simulate touching the center of a view and releasing quickly (before the tap timeout).
247     *
248     * @param test The test case that is being run
249     * @param v The view that should be clicked
250     */
251    public static void tapView(InstrumentationTestCase test, View v) {
252        int[] xy = new int[2];
253        v.getLocationOnScreen(xy);
254
255        final int viewWidth = v.getWidth();
256        final int viewHeight = v.getHeight();
257
258        final float x = xy[0] + (viewWidth / 2.0f);
259        float y = xy[1] + (viewHeight / 2.0f);
260
261        Instrumentation inst = test.getInstrumentation();
262
263        long downTime = SystemClock.uptimeMillis();
264        long eventTime = SystemClock.uptimeMillis();
265
266        MotionEvent event = MotionEvent.obtain(downTime, eventTime,
267                MotionEvent.ACTION_DOWN, x, y, 0);
268        inst.sendPointerSync(event);
269        inst.waitForIdleSync();
270
271        eventTime = SystemClock.uptimeMillis();
272        final int touchSlop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop();
273        event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE,
274                x + (touchSlop / 2.0f), y + (touchSlop / 2.0f), 0);
275        inst.sendPointerSync(event);
276        inst.waitForIdleSync();
277
278        eventTime = SystemClock.uptimeMillis();
279        event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
280        inst.sendPointerSync(event);
281        inst.waitForIdleSync();
282    }
283
284    /**
285     * Simulate touching the center of a view and cancelling (so no onClick should
286     * fire, etc).
287     *
288     * @param test The test case that is being run
289     * @param v The view that should be clicked
290     */
291    public static void touchAndCancelView(InstrumentationTestCase test, View v) {
292        int[] xy = new int[2];
293        v.getLocationOnScreen(xy);
294
295        final int viewWidth = v.getWidth();
296        final int viewHeight = v.getHeight();
297
298        final float x = xy[0] + (viewWidth / 2.0f);
299        float y = xy[1] + (viewHeight / 2.0f);
300
301        Instrumentation inst = test.getInstrumentation();
302
303        long downTime = SystemClock.uptimeMillis();
304        long eventTime = SystemClock.uptimeMillis();
305
306        MotionEvent event = MotionEvent.obtain(downTime, eventTime,
307                MotionEvent.ACTION_DOWN, x, y, 0);
308        inst.sendPointerSync(event);
309        inst.waitForIdleSync();
310
311        eventTime = SystemClock.uptimeMillis();
312        final int touchSlop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop();
313        event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_CANCEL,
314                x + (touchSlop / 2.0f), y + (touchSlop / 2.0f), 0);
315        inst.sendPointerSync(event);
316        inst.waitForIdleSync();
317
318    }
319
320    /**
321     * Simulate touching the center of a view and releasing.
322     *
323     * @param test The test case that is being run
324     * @param v The view that should be clicked
325     */
326    public static void clickView(InstrumentationTestCase test, View v) {
327        int[] xy = new int[2];
328        v.getLocationOnScreen(xy);
329
330        final int viewWidth = v.getWidth();
331        final int viewHeight = v.getHeight();
332
333        final float x = xy[0] + (viewWidth / 2.0f);
334        float y = xy[1] + (viewHeight / 2.0f);
335
336        Instrumentation inst = test.getInstrumentation();
337
338        long downTime = SystemClock.uptimeMillis();
339        long eventTime = SystemClock.uptimeMillis();
340
341        MotionEvent event = MotionEvent.obtain(downTime, eventTime,
342                MotionEvent.ACTION_DOWN, x, y, 0);
343        inst.sendPointerSync(event);
344        inst.waitForIdleSync();
345
346
347        eventTime = SystemClock.uptimeMillis();
348        final int touchSlop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop();
349        event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE,
350                x + (touchSlop / 2.0f), y + (touchSlop / 2.0f), 0);
351        inst.sendPointerSync(event);
352        inst.waitForIdleSync();
353
354        eventTime = SystemClock.uptimeMillis();
355        event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
356        inst.sendPointerSync(event);
357        inst.waitForIdleSync();
358
359        try {
360            Thread.sleep(1000);
361        } catch (InterruptedException e) {
362            e.printStackTrace();
363        }
364    }
365
366    /**
367     * Simulate touching the center of a view, holding until it is a long press, and then releasing.
368     *
369     * @param test The test case that is being run
370     * @param v The view that should be clicked
371     *
372     * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
373     * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
374     * configuring the Activity under test
375     */
376    @Deprecated
377    public static void longClickView(ActivityInstrumentationTestCase test, View v) {
378        longClickView((InstrumentationTestCase) test, v);
379    }
380
381    /**
382     * Simulate touching the center of a view, holding until it is a long press, and then releasing.
383     *
384     * @param test The test case that is being run
385     * @param v The view that should be clicked
386     */
387    public static void longClickView(InstrumentationTestCase test, View v) {
388        int[] xy = new int[2];
389        v.getLocationOnScreen(xy);
390
391        final int viewWidth = v.getWidth();
392        final int viewHeight = v.getHeight();
393
394        final float x = xy[0] + (viewWidth / 2.0f);
395        float y = xy[1] + (viewHeight / 2.0f);
396
397        Instrumentation inst = test.getInstrumentation();
398
399        long downTime = SystemClock.uptimeMillis();
400        long eventTime = SystemClock.uptimeMillis();
401
402        MotionEvent event = MotionEvent.obtain(downTime, eventTime,
403                MotionEvent.ACTION_DOWN, x, y, 0);
404        inst.sendPointerSync(event);
405        inst.waitForIdleSync();
406
407        eventTime = SystemClock.uptimeMillis();
408        final int touchSlop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop();
409        event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE,
410                x + touchSlop / 2, y + touchSlop / 2, 0);
411        inst.sendPointerSync(event);
412        inst.waitForIdleSync();
413
414        try {
415            Thread.sleep((long)(ViewConfiguration.getLongPressTimeout() * 1.5f));
416        } catch (InterruptedException e) {
417            e.printStackTrace();
418        }
419
420        eventTime = SystemClock.uptimeMillis();
421        event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
422        inst.sendPointerSync(event);
423        inst.waitForIdleSync();
424    }
425
426    /**
427     * Simulate touching the center of a view and dragging to the top of the screen.
428     *
429     * @param test The test case that is being run
430     * @param v The view that should be dragged
431     *
432     * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
433     * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
434     * configuring the Activity under test
435     */
436    @Deprecated
437    public static void dragViewToTop(ActivityInstrumentationTestCase test, View v) {
438        dragViewToTop((InstrumentationTestCase) test, v, 4);
439    }
440
441    /**
442     * Simulate touching the center of a view and dragging to the top of the screen.
443     *
444     * @param test The test case that is being run
445     * @param v The view that should be dragged
446     * @param stepCount How many move steps to include in the drag
447     *
448     * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
449     * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
450     * configuring the Activity under test
451     */
452    @Deprecated
453    public static void dragViewToTop(ActivityInstrumentationTestCase test, View v, int stepCount) {
454        dragViewToTop((InstrumentationTestCase) test, v, stepCount);
455    }
456
457    /**
458     * Simulate touching the center of a view and dragging to the top of the screen.
459     *
460     * @param test The test case that is being run
461     * @param v The view that should be dragged
462     */
463    public static void dragViewToTop(InstrumentationTestCase test, View v) {
464        dragViewToTop(test, v, 4);
465    }
466
467    /**
468     * Simulate touching the center of a view and dragging to the top of the screen.
469     *
470     * @param test The test case that is being run
471     * @param v The view that should be dragged
472     * @param stepCount How many move steps to include in the drag
473     */
474    public static void dragViewToTop(InstrumentationTestCase test, View v, int stepCount) {
475        int[] xy = new int[2];
476        v.getLocationOnScreen(xy);
477
478        final int viewWidth = v.getWidth();
479        final int viewHeight = v.getHeight();
480
481        final float x = xy[0] + (viewWidth / 2.0f);
482        float fromY = xy[1] + (viewHeight / 2.0f);
483        float toY = 0;
484
485        drag(test, x, x, fromY, toY, stepCount);
486    }
487
488    /**
489     * Get the location of a view. Use the gravity param to specify which part of the view to
490     * return.
491     *
492     * @param v View to find
493     * @param gravity A combination of (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL,
494     *        RIGHT)
495     * @param xy Result
496     */
497    private static void getStartLocation(View v, int gravity, int[] xy) {
498        v.getLocationOnScreen(xy);
499
500        final int viewWidth = v.getWidth();
501        final int viewHeight = v.getHeight();
502
503        switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
504        case Gravity.TOP:
505            break;
506        case Gravity.CENTER_VERTICAL:
507            xy[1] += viewHeight / 2;
508            break;
509        case Gravity.BOTTOM:
510            xy[1] += viewHeight - 1;
511            break;
512        default:
513            // Same as top -- do nothing
514        }
515
516        switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
517        case Gravity.LEFT:
518            break;
519        case Gravity.CENTER_HORIZONTAL:
520            xy[0] += viewWidth / 2;
521            break;
522        case Gravity.RIGHT:
523            xy[0] += viewWidth - 1;
524            break;
525        default:
526            // Same as left -- do nothing
527        }
528    }
529
530    /**
531     * Simulate touching a view and dragging it by the specified amount.
532     *
533     * @param test The test case that is being run
534     * @param v The view that should be dragged
535     * @param gravity Which part of the view to use for the initial down event. A combination of
536     *        (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
537     * @param deltaX Amount to drag horizontally in pixels
538     * @param deltaY Amount to drag vertically in pixels
539     *
540     * @return distance in pixels covered by the drag
541     *
542     * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
543     * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
544     * configuring the Activity under test
545     */
546    @Deprecated
547    public static int dragViewBy(ActivityInstrumentationTestCase test, View v, int gravity,
548            int deltaX, int deltaY) {
549        return dragViewBy((InstrumentationTestCase) test, v, gravity, deltaX, deltaY);
550    }
551
552    /**
553     * Simulate touching a view and dragging it by the specified amount.
554     *
555     * @param test The test case that is being run
556     * @param v The view that should be dragged
557     * @param gravity Which part of the view to use for the initial down event. A combination of
558     *        (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
559     * @param deltaX Amount to drag horizontally in pixels
560     * @param deltaY Amount to drag vertically in pixels
561     *
562     * @return distance in pixels covered by the drag
563     *
564     * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
565     * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
566     * configuring the Activity under test
567     */
568    @Deprecated
569    public static int dragViewBy(InstrumentationTestCase test, View v, int gravity, int deltaX,
570            int deltaY) {
571        int[] xy = new int[2];
572
573        getStartLocation(v, gravity, xy);
574
575        final int fromX = xy[0];
576        final int fromY = xy[1];
577
578        int distance = (int) Math.sqrt(deltaX * deltaX + deltaY * deltaY);
579
580        drag(test, fromX, fromX + deltaX, fromY, fromY + deltaY, distance);
581
582        return distance;
583    }
584
585    /**
586     * Simulate touching a view and dragging it to a specified location.
587     *
588     * @param test The test case that is being run
589     * @param v The view that should be dragged
590     * @param gravity Which part of the view to use for the initial down event. A combination of
591     *        (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
592     * @param toX Final location of the view after dragging
593     * @param toY Final location of the view after dragging
594     *
595     * @return distance in pixels covered by the drag
596     *
597     * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
598     * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
599     * configuring the Activity under test
600     */
601    @Deprecated
602    public static int dragViewTo(ActivityInstrumentationTestCase test, View v, int gravity, int toX,
603            int toY) {
604        return dragViewTo((InstrumentationTestCase) test, v, gravity, toX, toY);
605    }
606
607    /**
608     * Simulate touching a view and dragging it to a specified location.
609     *
610     * @param test The test case that is being run
611     * @param v The view that should be dragged
612     * @param gravity Which part of the view to use for the initial down event. A combination of
613     *        (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
614     * @param toX Final location of the view after dragging
615     * @param toY Final location of the view after dragging
616     *
617     * @return distance in pixels covered by the drag
618     */
619    public static int dragViewTo(InstrumentationTestCase test, View v, int gravity, int toX,
620            int toY) {
621        int[] xy = new int[2];
622
623        getStartLocation(v, gravity, xy);
624
625        final int fromX = xy[0];
626        final int fromY = xy[1];
627
628        int deltaX = fromX - toX;
629        int deltaY = fromY - toY;
630
631        int distance = (int)Math.sqrt(deltaX * deltaX + deltaY * deltaY);
632        drag(test, fromX, toX, fromY, toY, distance);
633
634        return distance;
635    }
636
637    /**
638     * Simulate touching a view and dragging it to a specified location. Only moves horizontally.
639     *
640     * @param test The test case that is being run
641     * @param v The view that should be dragged
642     * @param gravity Which part of the view to use for the initial down event. A combination of
643     *        (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
644     * @param toX Final location of the view after dragging
645     *
646     * @return distance in pixels covered by the drag
647     *
648     * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
649     * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
650     * configuring the Activity under test
651     */
652    @Deprecated
653    public static int dragViewToX(ActivityInstrumentationTestCase test, View v, int gravity,
654            int toX) {
655        return dragViewToX((InstrumentationTestCase) test, v, gravity, toX);
656    }
657
658    /**
659     * Simulate touching a view and dragging it to a specified location. Only moves horizontally.
660     *
661     * @param test The test case that is being run
662     * @param v The view that should be dragged
663     * @param gravity Which part of the view to use for the initial down event. A combination of
664     *        (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
665     * @param toX Final location of the view after dragging
666     *
667     * @return distance in pixels covered by the drag
668     */
669    public static int dragViewToX(InstrumentationTestCase test, View v, int gravity, int toX) {
670        int[] xy = new int[2];
671
672        getStartLocation(v, gravity, xy);
673
674        final int fromX = xy[0];
675        final int fromY = xy[1];
676
677        int deltaX = fromX - toX;
678
679        drag(test, fromX, toX, fromY, fromY, deltaX);
680
681        return deltaX;
682    }
683
684    /**
685     * Simulate touching a view and dragging it to a specified location. Only moves vertically.
686     *
687     * @param test The test case that is being run
688     * @param v The view that should be dragged
689     * @param gravity Which part of the view to use for the initial down event. A combination of
690     *        (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
691     * @param toY Final location of the view after dragging
692     *
693     * @return distance in pixels covered by the drag
694     *
695     * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
696     * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
697     * configuring the Activity under test
698     */
699    @Deprecated
700    public static int dragViewToY(ActivityInstrumentationTestCase test, View v, int gravity,
701            int toY) {
702        return dragViewToY((InstrumentationTestCase) test, v, gravity, toY);
703    }
704
705    /**
706     * Simulate touching a view and dragging it to a specified location. Only moves vertically.
707     *
708     * @param test The test case that is being run
709     * @param v The view that should be dragged
710     * @param gravity Which part of the view to use for the initial down event. A combination of
711     *        (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT)
712     * @param toY Final location of the view after dragging
713     *
714     * @return distance in pixels covered by the drag
715     */
716    public static int dragViewToY(InstrumentationTestCase test, View v, int gravity, int toY) {
717        int[] xy = new int[2];
718
719        getStartLocation(v, gravity, xy);
720
721        final int fromX = xy[0];
722        final int fromY = xy[1];
723
724        int deltaY = fromY - toY;
725
726        drag(test, fromX, fromX, fromY, toY, deltaY);
727
728        return deltaY;
729    }
730
731
732    /**
733     * Simulate touching a specific location and dragging to a new location.
734     *
735     * @param test The test case that is being run
736     * @param fromX X coordinate of the initial touch, in screen coordinates
737     * @param toX Xcoordinate of the drag destination, in screen coordinates
738     * @param fromY X coordinate of the initial touch, in screen coordinates
739     * @param toY Y coordinate of the drag destination, in screen coordinates
740     * @param stepCount How many move steps to include in the drag
741     *
742     * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of
743     * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for
744     * configuring the Activity under test
745     */
746    @Deprecated
747    public static void drag(ActivityInstrumentationTestCase test, float fromX, float toX,
748            float fromY, float toY, int stepCount) {
749        drag((InstrumentationTestCase) test, fromX, toX, fromY, toY, stepCount);
750    }
751
752    /**
753     * Simulate touching a specific location and dragging to a new location.
754     *
755     * @param test The test case that is being run
756     * @param fromX X coordinate of the initial touch, in screen coordinates
757     * @param toX Xcoordinate of the drag destination, in screen coordinates
758     * @param fromY X coordinate of the initial touch, in screen coordinates
759     * @param toY Y coordinate of the drag destination, in screen coordinates
760     * @param stepCount How many move steps to include in the drag
761     */
762    public static void drag(InstrumentationTestCase test, float fromX, float toX, float fromY,
763            float toY, int stepCount) {
764        Instrumentation inst = test.getInstrumentation();
765
766        long downTime = SystemClock.uptimeMillis();
767        long eventTime = SystemClock.uptimeMillis();
768
769        float y = fromY;
770        float x = fromX;
771
772        float yStep = (toY - fromY) / stepCount;
773        float xStep = (toX - fromX) / stepCount;
774
775        MotionEvent event = MotionEvent.obtain(downTime, eventTime,
776                MotionEvent.ACTION_DOWN, x, y, 0);
777        inst.sendPointerSync(event);
778        inst.waitForIdleSync();
779
780        for (int i = 0; i < stepCount; ++i) {
781            y += yStep;
782            x += xStep;
783            eventTime = SystemClock.uptimeMillis();
784            event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x, y, 0);
785            inst.sendPointerSync(event);
786            inst.waitForIdleSync();
787        }
788
789        eventTime = SystemClock.uptimeMillis();
790        event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
791        inst.sendPointerSync(event);
792        inst.waitForIdleSync();
793    }
794}
795