157e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le/* 21194ec356a16f3c6dcf408289e36e42c149d6dc8Kevin Jin * Copyright (C) 2013 DroidDriver committers 357e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le * 457e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le * Licensed under the Apache License, Version 2.0 (the "License"); 557e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le * you may not use this file except in compliance with the License. 657e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le * You may obtain a copy of the License at 757e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le * 857e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le * http://www.apache.org/licenses/LICENSE-2.0 957e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le * 1057e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le * Unless required by applicable law or agreed to in writing, software 1157e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le * distributed under the License is distributed on an "AS IS" BASIS, 1257e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1357e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le * See the License for the specific language governing permissions and 1457e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le * limitations under the License. 1557e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le */ 1657e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le 174b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinpackage io.appium.droiddriver.util; 1857e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le 19082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jinimport android.annotation.TargetApi; 20082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jinimport android.os.Build; 2157e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Leimport android.os.SystemClock; 221e9f07f4cb681fb142202113caedba35737a83efKevin Jinimport android.util.Log; 2357e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Leimport android.view.InputDevice; 24337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchettimport android.view.InputEvent; 25cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Leimport android.view.KeyEvent; 2657e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Leimport android.view.MotionEvent; 2757e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le 284b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.actions.InputInjector; 294b31201b5a2dbf8036da5a8d089a68a39cc1dc44Kevin Jinimport io.appium.droiddriver.exceptions.ActionException; 30f9c2a591497874769b87bf492a0666cf853e0ae5Kevin Jin 3157e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le/** 3257e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le * Helper methods to create InputEvents. 3357e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le */ 3457e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Lepublic class Events { 35544e68a6af3ef73316b9994bb7a63790c19415b9Thanh Le /** 36544e68a6af3ef73316b9994bb7a63790c19415b9Thanh Le * @return a touch down event at the specified coordinates 37544e68a6af3ef73316b9994bb7a63790c19415b9Thanh Le */ 38082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) 39337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett private static MotionEvent newTouchDownEvent(int x, int y) { 4031692a4134ef82a4144d25980c0c5f14bbf1bfadThanh Le long downTime = SystemClock.uptimeMillis(); 4131692a4134ef82a4144d25980c0c5f14bbf1bfadThanh Le MotionEvent event = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN, x, y, 1); 42082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin // TODO: Fix this if 'source' is required on devices older than HONEYCOMB_MR1. 43082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) { 44082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin event.setSource(InputDevice.SOURCE_TOUCHSCREEN); 45082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin } 4657e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le return event; 4757e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le } 4857e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le 49544e68a6af3ef73316b9994bb7a63790c19415b9Thanh Le /** 50544e68a6af3ef73316b9994bb7a63790c19415b9Thanh Le * @return a touch up event at the specified coordinates 51544e68a6af3ef73316b9994bb7a63790c19415b9Thanh Le */ 52082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) 53337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett private static MotionEvent newTouchUpEvent(long downTime, int x, int y) { 54544e68a6af3ef73316b9994bb7a63790c19415b9Thanh Le long eventTime = SystemClock.uptimeMillis(); 55544e68a6af3ef73316b9994bb7a63790c19415b9Thanh Le MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 1); 56082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) { 57082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin event.setSource(InputDevice.SOURCE_TOUCHSCREEN); 58082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin } 59544e68a6af3ef73316b9994bb7a63790c19415b9Thanh Le return event; 60544e68a6af3ef73316b9994bb7a63790c19415b9Thanh Le } 61544e68a6af3ef73316b9994bb7a63790c19415b9Thanh Le 62544e68a6af3ef73316b9994bb7a63790c19415b9Thanh Le /** 63544e68a6af3ef73316b9994bb7a63790c19415b9Thanh Le * @return a touch move event at the specified coordinates 64544e68a6af3ef73316b9994bb7a63790c19415b9Thanh Le */ 65082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) 66337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett private static MotionEvent newTouchMoveEvent(long downTime, int x, int y) { 67544e68a6af3ef73316b9994bb7a63790c19415b9Thanh Le long eventTime = SystemClock.uptimeMillis(); 68544e68a6af3ef73316b9994bb7a63790c19415b9Thanh Le MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x, y, 1); 69082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) { 70082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin event.setSource(InputDevice.SOURCE_TOUCHSCREEN); 71082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin } 7257e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le return event; 7357e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le } 7457e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le 75082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) 76337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett private static KeyEvent newKeyEvent(long downTime, long eventTime, int action, int keyCode, 77337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett int metaState) { 78337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett KeyEvent event = new KeyEvent(downTime, eventTime, action, keyCode, 0 /* repeat */, metaState); 79082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) { 80082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin event.setSource(InputDevice.SOURCE_KEYBOARD); 81082c7925e5109092ff31d7021f1f9bb6daabee12Kevin Jin } 82cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le return event; 83cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le } 84cce3dd4492cf04a89154e36fda1909ab4e35213aThanh Le 85f9c2a591497874769b87bf492a0666cf853e0ae5Kevin Jin /** 86f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin * Injects {@code event}. {@code event} is recycled and should not be used 87f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin * after. 88f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin * 89f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin * @throws ActionException if injection failed 90f9c2a591497874769b87bf492a0666cf853e0ae5Kevin Jin */ 91337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett private static void injectEvent(InputInjector injector, InputEvent event) { 921e9f07f4cb681fb142202113caedba35737a83efKevin Jin injectEvent(Log.DEBUG, injector, event); 931e9f07f4cb681fb142202113caedba35737a83efKevin Jin } 941e9f07f4cb681fb142202113caedba35737a83efKevin Jin 95337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett private static void injectEvent(int priority, InputInjector injector, InputEvent event) { 961e9f07f4cb681fb142202113caedba35737a83efKevin Jin Logs.call(priority, injector, "injectInputEvent", event); 97f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin try { 98f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin if (!injector.injectInputEvent(event)) { 99f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin throw new ActionException("Failed to inject " + event); 100f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin } 101f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin } finally { 102337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett if (event instanceof MotionEvent) { 103337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett ((MotionEvent) event).recycle(); 104337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett } 105f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin } 106f9c2a591497874769b87bf492a0666cf853e0ae5Kevin Jin } 107f9c2a591497874769b87bf492a0666cf853e0ae5Kevin Jin 108f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin public static long touchDown(InputInjector injector, int x, int y) { 109f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin MotionEvent downEvent = newTouchDownEvent(x, y); 110f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin long downTime = downEvent.getDownTime(); 111f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin injectEvent(injector, downEvent); 112f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin return downTime; 113f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin } 114f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin 115f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin public static void touchUp(InputInjector injector, long downTime, int x, int y) { 116f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin injectEvent(injector, newTouchUpEvent(downTime, x, y)); 117f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin } 118f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin 119f9c6c5063b38b623679e47d7095cccddb0481319Kevin Jin public static void touchMove(InputInjector injector, long downTime, int x, int y) { 1201e9f07f4cb681fb142202113caedba35737a83efKevin Jin injectEvent(Log.VERBOSE, injector, newTouchMoveEvent(downTime, x, y)); 121f9c2a591497874769b87bf492a0666cf853e0ae5Kevin Jin } 122f9c2a591497874769b87bf492a0666cf853e0ae5Kevin Jin 123337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett public static long keyDown(InputInjector injector, int keyCode, int metaState) { 124337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett long downTime = SystemClock.uptimeMillis(); 125337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett KeyEvent downEvent = newKeyEvent(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode, metaState); 126337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett injectEvent(injector, downEvent); 127337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett return downTime; 128337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett } 129337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett 130337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett public static void keyUp(InputInjector injector, long downTime, int keyCode, int metaState) { 131337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett injectEvent(injector, 132337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett newKeyEvent(downTime, SystemClock.uptimeMillis(), KeyEvent.ACTION_UP, keyCode, metaState)); 133337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett } 134337fafc3b2ede7dbd1be4d1ed0bbfdfdbbbd684bEric Fitchett 13557e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le private Events() {} 13657e46577852ffa1dde4662f6018f7fbcfacb6148Thanh Le} 137