1# Copyright 2015 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 5import logging 6import time 7 8from telemetry.core import util 9 10 11class ActionNotSupported(Exception): 12 pass 13 14 15class AndroidActionRunner(object): 16 """Provides an API for interacting with an android device. 17 18 This makes use of functionality provided by the android input command. None 19 of the gestures here are guaranteed to be performant for telemetry tests and 20 there is no official support for this API. 21 22 TODO(ariblue): Replace this API with a better implementation for interacting 23 with native components. 24 """ 25 26 def __init__(self, platform_backend): 27 self._platform_backend = platform_backend 28 29 def SmoothScrollBy(self, left_start_coord, top_start_coord, direction, 30 scroll_distance): 31 """Perform gesture to scroll down on the android device. 32 """ 33 if direction not in ['down', 'up', 'left', 'right']: 34 raise ActionNotSupported('Invalid scroll direction: %s' % direction) 35 36 # This velocity is slower so that the exact distance we specify is the 37 # distance the page travels. 38 duration = scroll_distance 39 40 # Note that the default behavior is swiping up for scrolling down. 41 if direction == 'down': 42 left_end_coord = left_start_coord 43 top_end_coord = top_start_coord - scroll_distance 44 elif direction == 'up': 45 left_end_coord = left_start_coord 46 top_end_coord = top_start_coord + scroll_distance 47 elif direction == 'right': 48 left_end_coord = left_start_coord - scroll_distance 49 top_end_coord = top_start_coord 50 elif direction == 'left': 51 left_end_coord = left_start_coord + scroll_distance 52 top_end_coord = top_start_coord 53 54 self.InputSwipe(left_start_coord, top_start_coord, left_end_coord, 55 top_end_coord, duration) 56 57 def Wait(self, seconds): 58 """Wait for the number of seconds specified. 59 60 Args: 61 seconds: The number of seconds to wait. 62 """ 63 time.sleep(seconds) 64 65 def InputText(self, string): 66 """Convert the characters of the string into key events and send to device. 67 68 Args: 69 string: The string to send to the device. 70 """ 71 self._platform_backend.device.RunShellCommand('input text %s' % string) 72 73 def InputKeyEvent(self, key): 74 """Send a single key input to the device. 75 76 Args: 77 key: A key code number or name that will be sent to the device 78 """ 79 self._platform_backend.device.RunShellCommand('input keyevent %s' % key) 80 81 def InputTap(self, x_coord, y_coord): 82 """Perform a tap input at the given coordinates. 83 84 Args: 85 x_coord: The x coordinate of the tap event. 86 y_coord: The y coordinate of the tap event. 87 """ 88 self._platform_backend.device.RunShellCommand('input tap %s %s' % (x_coord, 89 y_coord)) 90 91 def InputSwipe(self, left_start_coord, top_start_coord, left_end_coord, 92 top_end_coord, duration): 93 """Perform a swipe input. 94 95 Args: 96 left_start_coord: The horizontal starting coordinate of the gesture 97 top_start_coord: The vertical starting coordinate of the gesture 98 left_end_coord: The horizontal ending coordinate of the gesture 99 top_end_coord: The vertical ending coordinate of the gesture 100 duration: The length of time of the swipe in milliseconds 101 """ 102 self._platform_backend.device.RunShellCommand( 103 'input swipe %s %s %s %s %s' % (left_start_coord, top_start_coord, 104 left_end_coord, top_end_coord, 105 duration)) 106 107 def InputPress(self): 108 """Perform a press input.""" 109 self._platform_backend.device.RunShellCommand('input press') 110 111 def InputRoll(self, dx, dy): 112 """Perform a roll input. This sends a simple zero-pressure move event. 113 114 Args: 115 dx: Change in the x coordinate due to move. 116 dy: Change in the y coordinate due to move. 117 """ 118 self._platform_backend.device.RunShellCommand('input roll %s %s' % (dx, dy)) 119 120 def TurnScreenOn(self): 121 """If device screen is off, turn screen on. 122 If the screen is already on, log a warning and return immediately. 123 124 Raises: 125 Timeout: If the screen is off and device fails to turn screen on. 126 """ 127 self._platform_backend.device.SetScreen(True) 128 util.WaitFor(self._platform_backend.device.IsScreenOn, 5) 129 130 def TurnScreenOff(self): 131 """If device screen is on, turn screen off. 132 If the screen is already off, log a warning and return immediately. 133 134 Raises: 135 Timeout: If the screen is on and device fails to turn screen off. 136 """ 137 138 def is_screen_off(): 139 return not self._platform_backend.device.IsScreenOn() 140 141 self._platform_backend.device.SetScreen(False) 142 util.WaitFor(is_screen_off, 5) 143 144 def UnlockScreen(self): 145 """If device screen is locked, unlocks it. 146 If the device is not locked, log a warning and return immediately. 147 148 Raises: 149 Timeout: If device fails to unlock screen. 150 """ 151 152 def is_screen_unlocked(): 153 return not self._platform_backend.IsScreenLocked() 154 155 if self._platform_backend.IsScreenLocked(): 156 self._platform_backend.device.RunShellCommand('input keyevent 82') 157 else: 158 logging.warning('Screen not locked when expected.') 159 return 160 161 util.WaitFor(is_screen_unlocked, 5) 162