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