• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 DroidDriver committers
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 
17 package io.appium.droiddriver.util;
18 
19 import android.annotation.TargetApi;
20 import android.os.Build;
21 import android.os.SystemClock;
22 import android.util.Log;
23 import android.view.InputDevice;
24 import android.view.InputEvent;
25 import android.view.KeyEvent;
26 import android.view.MotionEvent;
27 
28 import io.appium.droiddriver.actions.InputInjector;
29 import io.appium.droiddriver.exceptions.ActionException;
30 
31 /**
32  * Helper methods to create InputEvents.
33  */
34 public class Events {
35   /**
36    * @return a touch down event at the specified coordinates
37    */
38   @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
newTouchDownEvent(int x, int y)39   private static MotionEvent newTouchDownEvent(int x, int y) {
40     long downTime = SystemClock.uptimeMillis();
41     MotionEvent event = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN, x, y, 1);
42     // TODO: Fix this if 'source' is required on devices older than HONEYCOMB_MR1.
43     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
44       event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
45     }
46     return event;
47   }
48 
49   /**
50    * @return a touch up event at the specified coordinates
51    */
52   @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
newTouchUpEvent(long downTime, int x, int y)53   private static MotionEvent newTouchUpEvent(long downTime, int x, int y) {
54     long eventTime = SystemClock.uptimeMillis();
55     MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 1);
56     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
57       event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
58     }
59     return event;
60   }
61 
62   /**
63    * @return a touch move event at the specified coordinates
64    */
65   @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
newTouchMoveEvent(long downTime, int x, int y)66   private static MotionEvent newTouchMoveEvent(long downTime, int x, int y) {
67     long eventTime = SystemClock.uptimeMillis();
68     MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x, y, 1);
69     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
70       event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
71     }
72     return event;
73   }
74 
75   @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
newKeyEvent(long downTime, long eventTime, int action, int keyCode, int metaState)76   private static KeyEvent newKeyEvent(long downTime, long eventTime, int action, int keyCode,
77       int metaState) {
78     KeyEvent event = new KeyEvent(downTime, eventTime, action, keyCode, 0 /* repeat */, metaState);
79     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
80       event.setSource(InputDevice.SOURCE_KEYBOARD);
81     }
82     return event;
83   }
84 
85   /**
86    * Injects {@code event}. {@code event} is recycled and should not be used
87    * after.
88    *
89    * @throws ActionException if injection failed
90    */
injectEvent(InputInjector injector, InputEvent event)91   private static void injectEvent(InputInjector injector, InputEvent event) {
92     injectEvent(Log.DEBUG, injector, event);
93   }
94 
injectEvent(int priority, InputInjector injector, InputEvent event)95   private static void injectEvent(int priority, InputInjector injector, InputEvent event) {
96     Logs.call(priority, injector, "injectInputEvent", event);
97     try {
98       if (!injector.injectInputEvent(event)) {
99         throw new ActionException("Failed to inject " + event);
100       }
101     } finally {
102       if (event instanceof MotionEvent) {
103         ((MotionEvent) event).recycle();
104       }
105     }
106   }
107 
touchDown(InputInjector injector, int x, int y)108   public static long touchDown(InputInjector injector, int x, int y) {
109     MotionEvent downEvent = newTouchDownEvent(x, y);
110     long downTime = downEvent.getDownTime();
111     injectEvent(injector, downEvent);
112     return downTime;
113   }
114 
touchUp(InputInjector injector, long downTime, int x, int y)115   public static void touchUp(InputInjector injector, long downTime, int x, int y) {
116     injectEvent(injector, newTouchUpEvent(downTime, x, y));
117   }
118 
touchMove(InputInjector injector, long downTime, int x, int y)119   public static void touchMove(InputInjector injector, long downTime, int x, int y) {
120     injectEvent(Log.VERBOSE, injector, newTouchMoveEvent(downTime, x, y));
121   }
122 
keyDown(InputInjector injector, int keyCode, int metaState)123   public static long keyDown(InputInjector injector, int keyCode, int metaState) {
124     long downTime = SystemClock.uptimeMillis();
125     KeyEvent downEvent = newKeyEvent(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode, metaState);
126     injectEvent(injector, downEvent);
127     return downTime;
128   }
129 
keyUp(InputInjector injector, long downTime, int keyCode, int metaState)130   public static void keyUp(InputInjector injector, long downTime, int keyCode, int metaState) {
131     injectEvent(injector,
132         newKeyEvent(downTime, SystemClock.uptimeMillis(), KeyEvent.ACTION_UP, keyCode, metaState));
133   }
134 
Events()135   private Events() {}
136 }
137