OLD | NEW |
1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Provides a variety of device interactions based on adb. | 5 """Provides a variety of device interactions based on adb. |
6 | 6 |
7 Eventually, this will be based on adb_wrapper. | 7 Eventually, this will be based on adb_wrapper. |
8 """ | 8 """ |
9 # pylint: disable=W0613 | 9 # pylint: disable=W0613 |
10 | 10 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 self._default_timeout = default_timeout | 74 self._default_timeout = default_timeout |
75 self._default_retries = default_retries | 75 self._default_retries = default_retries |
76 assert(hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR)) | 76 assert(hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR)) |
77 assert(hasattr(self, decorators.DEFAULT_RETRIES_ATTR)) | 77 assert(hasattr(self, decorators.DEFAULT_RETRIES_ATTR)) |
78 | 78 |
79 @decorators.WithTimeoutAndRetriesFromInstance() | 79 @decorators.WithTimeoutAndRetriesFromInstance() |
80 def IsOnline(self, timeout=None, retries=None): | 80 def IsOnline(self, timeout=None, retries=None): |
81 """Checks whether the device is online. | 81 """Checks whether the device is online. |
82 | 82 |
83 Args: | 83 Args: |
84 timeout: An integer containing the number of seconds to wait for the | 84 timeout: timeout in seconds |
85 operation to complete. | 85 retries: number of retries |
86 retries: An integer containing the number of times the operation should | |
87 be retried if it fails. | |
88 Returns: | 86 Returns: |
89 True if the device is online, False otherwise. | 87 True if the device is online, False otherwise. |
| 88 Raises: |
| 89 CommandTimeoutError on timeout. |
90 """ | 90 """ |
91 return self.old_interface.IsOnline() | 91 return self.old_interface.IsOnline() |
92 | 92 |
93 @decorators.WithTimeoutAndRetriesFromInstance() | 93 @decorators.WithTimeoutAndRetriesFromInstance() |
94 def HasRoot(self, timeout=None, retries=None): | 94 def HasRoot(self, timeout=None, retries=None): |
95 """Checks whether or not adbd has root privileges. | 95 """Checks whether or not adbd has root privileges. |
96 | 96 |
97 Args: | 97 Args: |
98 timeout: Same as for |IsOnline|. | 98 timeout: timeout in seconds |
99 retries: Same as for |IsOnline|. | 99 retries: number of retries |
100 Returns: | 100 Returns: |
101 True if adbd has root privileges, False otherwise. | 101 True if adbd has root privileges, False otherwise. |
| 102 Raises: |
| 103 CommandTimeoutError on timeout. |
| 104 DeviceUnreachableError on missing device. |
102 """ | 105 """ |
103 return self._HasRootImpl() | 106 return self._HasRootImpl() |
104 | 107 |
105 def _HasRootImpl(self): | 108 def _HasRootImpl(self): |
106 """ Implementation of HasRoot. | 109 """Implementation of HasRoot. |
107 | 110 |
108 This is split from HasRoot to allow other DeviceUtils methods to call | 111 This is split from HasRoot to allow other DeviceUtils methods to call |
109 HasRoot without spawning a new timeout thread. | 112 HasRoot without spawning a new timeout thread. |
110 | 113 |
111 Returns: | 114 Returns: |
112 Same as for |HasRoot|. | 115 Same as for |HasRoot|. |
| 116 Raises: |
| 117 Same as for |HasRoot|. |
113 """ | 118 """ |
114 return self.old_interface.IsRootEnabled() | 119 return self.old_interface.IsRootEnabled() |
115 | 120 |
116 @decorators.WithTimeoutAndRetriesFromInstance() | 121 @decorators.WithTimeoutAndRetriesFromInstance() |
117 def EnableRoot(self, timeout=None, retries=None): | 122 def EnableRoot(self, timeout=None, retries=None): |
118 """Restarts adbd with root privileges. | 123 """Restarts adbd with root privileges. |
119 | 124 |
120 Args: | 125 Args: |
121 timeout: Same as for |IsOnline|. | 126 timeout: timeout in seconds |
122 retries: Same as for |IsOnline|. | 127 retries: number of retries |
123 Raises: | 128 Raises: |
124 CommandFailedError if root could not be enabled. | 129 CommandFailedError if root could not be enabled. |
| 130 CommandTimeoutError on timeout. |
125 """ | 131 """ |
126 if not self.old_interface.EnableAdbRoot(): | 132 if not self.old_interface.EnableAdbRoot(): |
127 raise device_errors.CommandFailedError( | 133 raise device_errors.CommandFailedError( |
128 'Could not enable root.', device=str(self)) | 134 'Could not enable root.', device=str(self)) |
129 | 135 |
130 @decorators.WithTimeoutAndRetriesFromInstance() | 136 @decorators.WithTimeoutAndRetriesFromInstance() |
131 def GetExternalStoragePath(self, timeout=None, retries=None): | 137 def GetExternalStoragePath(self, timeout=None, retries=None): |
132 """Get the device's path to its SD card. | 138 """Get the device's path to its SD card. |
133 | 139 |
134 Args: | 140 Args: |
135 timeout: Same as for |IsOnline|. | 141 timeout: timeout in seconds |
136 retries: Same as for |IsOnline|. | 142 retries: number of retries |
137 Returns: | 143 Returns: |
138 The device's path to its SD card. | 144 The device's path to its SD card. |
| 145 Raises: |
| 146 CommandFailedError if the external storage path could not be determined. |
| 147 CommandTimeoutError on timeout. |
| 148 DeviceUnreachableError on missing device. |
139 """ | 149 """ |
140 try: | 150 try: |
141 return self.old_interface.GetExternalStorage() | 151 return self.old_interface.GetExternalStorage() |
142 except AssertionError as e: | 152 except AssertionError as e: |
143 raise device_errors.CommandFailedError( | 153 raise device_errors.CommandFailedError( |
144 str(e), device=str(self)), None, sys.exc_info()[2] | 154 str(e), device=str(self)), None, sys.exc_info()[2] |
145 | 155 |
146 @decorators.WithTimeoutAndRetriesFromInstance() | 156 @decorators.WithTimeoutAndRetriesFromInstance() |
147 def WaitUntilFullyBooted(self, wifi=False, timeout=None, retries=None): | 157 def WaitUntilFullyBooted(self, wifi=False, timeout=None, retries=None): |
148 """Wait for the device to fully boot. | 158 """Wait for the device to fully boot. |
149 | 159 |
150 This means waiting for the device to boot, the package manager to be | 160 This means waiting for the device to boot, the package manager to be |
151 available, and the SD card to be ready. It can optionally mean waiting | 161 available, and the SD card to be ready. It can optionally mean waiting |
152 for wifi to come up, too. | 162 for wifi to come up, too. |
153 | 163 |
154 Args: | 164 Args: |
155 wifi: A boolean indicating if we should wait for wifi to come up or not. | 165 wifi: A boolean indicating if we should wait for wifi to come up or not. |
156 timeout: Same as for |IsOnline|. | 166 timeout: timeout in seconds |
157 retries: Same as for |IsOnline|. | 167 retries: number of retries |
158 Raises: | 168 Raises: |
| 169 CommandFailedError on failure. |
159 CommandTimeoutError if one of the component waits times out. | 170 CommandTimeoutError if one of the component waits times out. |
160 DeviceUnreachableError if the device becomes unresponsive. | 171 DeviceUnreachableError if the device becomes unresponsive. |
161 """ | 172 """ |
162 self._WaitUntilFullyBootedImpl(wifi=wifi, timeout=timeout) | 173 self._WaitUntilFullyBootedImpl(wifi=wifi, timeout=timeout) |
163 | 174 |
164 def _WaitUntilFullyBootedImpl(self, wifi=False, timeout=None): | 175 def _WaitUntilFullyBootedImpl(self, wifi=False, timeout=None): |
165 """ Implementation of WaitUntilFullyBooted. | 176 """Implementation of WaitUntilFullyBooted. |
166 | 177 |
167 This is split from WaitUntilFullyBooted to allow other DeviceUtils methods | 178 This is split from WaitUntilFullyBooted to allow other DeviceUtils methods |
168 to call WaitUntilFullyBooted without spawning a new timeout thread. | 179 to call WaitUntilFullyBooted without spawning a new timeout thread. |
169 | 180 |
170 TODO(jbudorick) Remove the timeout parameter once this is no longer | 181 TODO(jbudorick) Remove the timeout parameter once this is no longer |
171 implemented via AndroidCommands. | 182 implemented via AndroidCommands. |
172 | 183 |
173 Args: | 184 Args: |
174 wifi: Same as for |WaitUntilFullyBooted|. | 185 wifi: Same as for |WaitUntilFullyBooted|. |
175 timeout: Same as for |IsOnline|. | 186 timeout: timeout in seconds |
176 Raises: | 187 Raises: |
177 Same as for |WaitUntilFullyBooted|. | 188 Same as for |WaitUntilFullyBooted|. |
178 """ | 189 """ |
179 if timeout is None: | 190 if timeout is None: |
180 timeout = self._default_timeout | 191 timeout = self._default_timeout |
181 self.old_interface.WaitForSystemBootCompleted(timeout) | 192 self.old_interface.WaitForSystemBootCompleted(timeout) |
182 self.old_interface.WaitForDevicePm() | 193 self.old_interface.WaitForDevicePm() |
183 self.old_interface.WaitForSdCardReady(timeout) | 194 self.old_interface.WaitForSdCardReady(timeout) |
184 if wifi: | 195 if wifi: |
185 while not 'Wi-Fi is enabled' in ( | 196 while not 'Wi-Fi is enabled' in ( |
186 self._RunShellCommandImpl('dumpsys wifi')): | 197 self._RunShellCommandImpl('dumpsys wifi')): |
187 time.sleep(1) | 198 time.sleep(1) |
188 | 199 |
189 REBOOT_DEFAULT_TIMEOUT = 10 * _DEFAULT_TIMEOUT | 200 REBOOT_DEFAULT_TIMEOUT = 10 * _DEFAULT_TIMEOUT |
190 REBOOT_DEFAULT_RETRIES = _DEFAULT_RETRIES | 201 REBOOT_DEFAULT_RETRIES = _DEFAULT_RETRIES |
191 | 202 |
192 @decorators.WithTimeoutAndRetriesDefaults( | 203 @decorators.WithTimeoutAndRetriesDefaults( |
193 REBOOT_DEFAULT_TIMEOUT, | 204 REBOOT_DEFAULT_TIMEOUT, |
194 REBOOT_DEFAULT_RETRIES) | 205 REBOOT_DEFAULT_RETRIES) |
195 def Reboot(self, block=True, timeout=None, retries=None): | 206 def Reboot(self, block=True, timeout=None, retries=None): |
196 """Reboot the device. | 207 """Reboot the device. |
197 | 208 |
198 Args: | 209 Args: |
199 block: A boolean indicating if we should wait for the reboot to complete. | 210 block: A boolean indicating if we should wait for the reboot to complete. |
200 timeout: Same as for |IsOnline|. | 211 timeout: timeout in seconds |
201 retries: Same as for |IsOnline|. | 212 retries: number of retries |
| 213 Raises: |
| 214 CommandTimeoutError on timeout. |
| 215 DeviceUnreachableError on missing device. |
202 """ | 216 """ |
203 self.old_interface.Reboot() | 217 self.old_interface.Reboot() |
204 if block: | 218 if block: |
205 self._WaitUntilFullyBootedImpl(timeout=timeout) | 219 self._WaitUntilFullyBootedImpl(timeout=timeout) |
206 | 220 |
207 INSTALL_DEFAULT_TIMEOUT = 4 * _DEFAULT_TIMEOUT | 221 INSTALL_DEFAULT_TIMEOUT = 4 * _DEFAULT_TIMEOUT |
208 INSTALL_DEFAULT_RETRIES = _DEFAULT_RETRIES | 222 INSTALL_DEFAULT_RETRIES = _DEFAULT_RETRIES |
209 | 223 |
210 @decorators.WithTimeoutAndRetriesDefaults( | 224 @decorators.WithTimeoutAndRetriesDefaults( |
211 INSTALL_DEFAULT_TIMEOUT, | 225 INSTALL_DEFAULT_TIMEOUT, |
212 INSTALL_DEFAULT_RETRIES) | 226 INSTALL_DEFAULT_RETRIES) |
213 def Install(self, apk_path, reinstall=False, timeout=None, retries=None): | 227 def Install(self, apk_path, reinstall=False, timeout=None, retries=None): |
214 """Install an APK. | 228 """Install an APK. |
215 | 229 |
216 Noop if an identical APK is already installed. | 230 Noop if an identical APK is already installed. |
217 | 231 |
218 Args: | 232 Args: |
219 apk_path: A string containing the path to the APK to install. | 233 apk_path: A string containing the path to the APK to install. |
220 reinstall: A boolean indicating if we should keep any existing app data. | 234 reinstall: A boolean indicating if we should keep any existing app data. |
221 timeout: Same as for |IsOnline|. | 235 timeout: timeout in seconds |
222 retries: Same as for |IsOnline|. | 236 retries: number of retries |
223 Raises: | 237 Raises: |
224 CommandFailedError if the installation fails. | 238 CommandFailedError if the installation fails. |
225 CommandTimeoutError if the installation times out. | 239 CommandTimeoutError if the installation times out. |
| 240 DeviceUnreachableError on missing device. |
226 """ | 241 """ |
227 package_name = apk_helper.GetPackageName(apk_path) | 242 package_name = apk_helper.GetPackageName(apk_path) |
228 device_path = self.old_interface.GetApplicationPath(package_name) | 243 device_path = self.old_interface.GetApplicationPath(package_name) |
229 if device_path is not None: | 244 if device_path is not None: |
230 files_changed = self.old_interface.GetFilesChanged( | 245 files_changed = self.old_interface.GetFilesChanged( |
231 apk_path, device_path, ignore_filenames=True) | 246 apk_path, device_path, ignore_filenames=True) |
232 if len(files_changed) > 0: | 247 if len(files_changed) > 0: |
233 should_install = True | 248 should_install = True |
234 if not reinstall: | 249 if not reinstall: |
235 out = self.old_interface.Uninstall(package_name) | 250 out = self.old_interface.Uninstall(package_name) |
(...skipping 23 matching lines...) Expand all Loading... |
259 | 274 |
260 TODO(jbudorick) Switch the default value of check_return to True after | 275 TODO(jbudorick) Switch the default value of check_return to True after |
261 AndroidCommands is gone. | 276 AndroidCommands is gone. |
262 | 277 |
263 Args: | 278 Args: |
264 cmd: A list containing the command to run on the device and any arguments. | 279 cmd: A list containing the command to run on the device and any arguments. |
265 check_return: A boolean indicating whether or not the return code should | 280 check_return: A boolean indicating whether or not the return code should |
266 be checked. | 281 be checked. |
267 as_root: A boolean indicating whether the shell command should be run | 282 as_root: A boolean indicating whether the shell command should be run |
268 with root privileges. | 283 with root privileges. |
269 timeout: Same as for |IsOnline|. | 284 timeout: timeout in seconds |
270 retries: Same as for |IsOnline|. | 285 retries: number of retries |
| 286 Returns: |
| 287 The output of the command. |
271 Raises: | 288 Raises: |
272 CommandFailedError if check_return is True and the return code is nozero. | 289 CommandFailedError if check_return is True and the return code is nozero. |
273 Returns: | 290 CommandTimeoutError on timeout. |
274 The output of the command. | 291 DeviceUnreachableError on missing device. |
275 """ | 292 """ |
276 return self._RunShellCommandImpl(cmd, check_return=check_return, | 293 return self._RunShellCommandImpl(cmd, check_return=check_return, |
277 as_root=as_root, timeout=timeout) | 294 as_root=as_root, timeout=timeout) |
278 | 295 |
279 def _RunShellCommandImpl(self, cmd, check_return=False, as_root=False, | 296 def _RunShellCommandImpl(self, cmd, check_return=False, as_root=False, |
280 timeout=None): | 297 timeout=None): |
281 """Implementation of RunShellCommand. | 298 """Implementation of RunShellCommand. |
282 | 299 |
283 This is split from RunShellCommand to allow other DeviceUtils methods to | 300 This is split from RunShellCommand to allow other DeviceUtils methods to |
284 call RunShellCommand without spawning a new timeout thread. | 301 call RunShellCommand without spawning a new timeout thread. |
285 | 302 |
286 TODO(jbudorick) Remove the timeout parameter once this is no longer | 303 TODO(jbudorick) Remove the timeout parameter once this is no longer |
287 implemented via AndroidCommands. | 304 implemented via AndroidCommands. |
288 | 305 |
289 Args: | 306 Args: |
290 cmd: Same as for |RunShellCommand|. | 307 cmd: Same as for |RunShellCommand|. |
291 check_return: Same as for |RunShellCommand|. | 308 check_return: Same as for |RunShellCommand|. |
292 as_root: Same as for |RunShellCommand|. | 309 as_root: Same as for |RunShellCommand|. |
293 timeout: Same as for |IsOnline|. | 310 timeout: timeout in seconds |
294 Raises: | 311 Raises: |
295 Same as for |RunShellCommand|. | 312 Same as for |RunShellCommand|. |
296 Returns: | 313 Returns: |
297 Same as for |RunShellCommand|. | 314 Same as for |RunShellCommand|. |
298 """ | 315 """ |
299 if isinstance(cmd, list): | 316 if isinstance(cmd, list): |
300 cmd = ' '.join(cmd) | 317 cmd = ' '.join(cmd) |
301 if as_root and not self.HasRoot(): | 318 if as_root and not self.HasRoot(): |
302 cmd = 'su -c %s' % cmd | 319 cmd = 'su -c %s' % cmd |
303 if check_return: | 320 if check_return: |
(...skipping 12 matching lines...) Expand all Loading... |
316 """Kill all processes with the given name on the device. | 333 """Kill all processes with the given name on the device. |
317 | 334 |
318 Args: | 335 Args: |
319 process_name: A string containing the name of the process to kill. | 336 process_name: A string containing the name of the process to kill. |
320 signum: An integer containing the signal number to send to kill. Defaults | 337 signum: An integer containing the signal number to send to kill. Defaults |
321 to 9 (SIGKILL). | 338 to 9 (SIGKILL). |
322 as_root: A boolean indicating whether the kill should be executed with | 339 as_root: A boolean indicating whether the kill should be executed with |
323 root privileges. | 340 root privileges. |
324 blocking: A boolean indicating whether we should wait until all processes | 341 blocking: A boolean indicating whether we should wait until all processes |
325 with the given |process_name| are dead. | 342 with the given |process_name| are dead. |
326 timeout: Same as for |IsOnline|. | 343 timeout: timeout in seconds |
327 retries: Same as for |IsOnline|. | 344 retries: number of retries |
328 Raises: | 345 Raises: |
329 CommandFailedError if no process was killed. | 346 CommandFailedError if no process was killed. |
| 347 CommandTimeoutError on timeout. |
| 348 DeviceUnreachableError on missing device. |
330 """ | 349 """ |
331 pids = self.old_interface.ExtractPid(process_name) | 350 pids = self.old_interface.ExtractPid(process_name) |
332 if len(pids) == 0: | 351 if len(pids) == 0: |
333 raise device_errors.CommandFailedError( | 352 raise device_errors.CommandFailedError( |
334 'No process "%s"' % process_name, device=str(self)) | 353 'No process "%s"' % process_name, device=str(self)) |
335 | 354 |
336 if blocking: | 355 if blocking: |
337 total_killed = self.old_interface.KillAllBlocking( | 356 total_killed = self.old_interface.KillAllBlocking( |
338 process_name, signum=signum, with_su=as_root, timeout_sec=timeout) | 357 process_name, signum=signum, with_su=as_root, timeout_sec=timeout) |
339 else: | 358 else: |
(...skipping 10 matching lines...) Expand all Loading... |
350 | 369 |
351 Args: | 370 Args: |
352 intent: An Intent to send. | 371 intent: An Intent to send. |
353 blocking: A boolean indicating whether we should wait for the activity to | 372 blocking: A boolean indicating whether we should wait for the activity to |
354 finish launching. | 373 finish launching. |
355 trace_file_name: If present, a string that both indicates that we want to | 374 trace_file_name: If present, a string that both indicates that we want to |
356 profile the activity and contains the path to which the | 375 profile the activity and contains the path to which the |
357 trace should be saved. | 376 trace should be saved. |
358 force_stop: A boolean indicating whether we should stop the activity | 377 force_stop: A boolean indicating whether we should stop the activity |
359 before starting it. | 378 before starting it. |
360 timeout: Same as for |IsOnline|. | 379 timeout: timeout in seconds |
361 retries: Same as for |IsOnline|. | 380 retries: number of retries |
362 Raises: | 381 Raises: |
363 CommandFailedError if the activity could not be started. | 382 CommandFailedError if the activity could not be started. |
| 383 CommandTimeoutError on timeout. |
| 384 DeviceUnreachableError on missing device. |
364 """ | 385 """ |
365 single_category = (intent.category[0] if isinstance(intent.category, list) | 386 single_category = (intent.category[0] if isinstance(intent.category, list) |
366 else intent.category) | 387 else intent.category) |
367 output = self.old_interface.StartActivity( | 388 output = self.old_interface.StartActivity( |
368 intent.package, intent.activity, wait_for_completion=blocking, | 389 intent.package, intent.activity, wait_for_completion=blocking, |
369 action=intent.action, category=single_category, data=intent.data, | 390 action=intent.action, category=single_category, data=intent.data, |
370 extras=intent.extras, trace_file_name=trace_file_name, | 391 extras=intent.extras, trace_file_name=trace_file_name, |
371 force_stop=force_stop, flags=intent.flags) | 392 force_stop=force_stop, flags=intent.flags) |
372 for l in output: | 393 for l in output: |
373 if l.startswith('Error:'): | 394 if l.startswith('Error:'): |
374 raise device_errors.CommandFailedError(l, device=str(self)) | 395 raise device_errors.CommandFailedError(l, device=str(self)) |
375 | 396 |
376 @decorators.WithTimeoutAndRetriesFromInstance() | 397 @decorators.WithTimeoutAndRetriesFromInstance() |
377 def BroadcastIntent(self, intent, timeout=None, retries=None): | 398 def BroadcastIntent(self, intent, timeout=None, retries=None): |
378 """Send a broadcast intent. | 399 """Send a broadcast intent. |
379 | 400 |
380 Args: | 401 Args: |
381 intent: An Intent to broadcast. | 402 intent: An Intent to broadcast. |
382 timeout: Same as for |IsOnline|. | 403 timeout: timeout in seconds |
383 retries: Same as for |IsOnline|. | 404 retries: number of retries |
| 405 Raises: |
| 406 CommandTimeoutError on timeout. |
| 407 DeviceUnreachableError on missing device. |
384 """ | 408 """ |
385 package, old_intent = intent.action.rsplit('.', 1) | 409 package, old_intent = intent.action.rsplit('.', 1) |
386 if intent.extras is None: | 410 if intent.extras is None: |
387 args = [] | 411 args = [] |
388 else: | 412 else: |
389 args = ['-e %s%s' % (k, ' "%s"' % v if v else '') | 413 args = ['-e %s%s' % (k, ' "%s"' % v if v else '') |
390 for k, v in intent.extras.items() if len(k) > 0] | 414 for k, v in intent.extras.items() if len(k) > 0] |
391 self.old_interface.BroadcastIntent(package, old_intent, *args) | 415 self.old_interface.BroadcastIntent(package, old_intent, *args) |
392 | 416 |
393 @decorators.WithTimeoutAndRetriesFromInstance() | 417 @decorators.WithTimeoutAndRetriesFromInstance() |
394 def GoHome(self, timeout=None, retries=None): | 418 def GoHome(self, timeout=None, retries=None): |
395 """Return to the home screen. | 419 """Return to the home screen. |
396 | 420 |
397 Args: | 421 Args: |
398 timeout: Same as for |IsOnline|. | 422 timeout: timeout in seconds |
399 retries: Same as for |IsOnline|. | 423 retries: number of retries |
| 424 Raises: |
| 425 CommandTimeoutError on timeout. |
| 426 DeviceUnreachableError on missing device. |
400 """ | 427 """ |
401 self.old_interface.GoHome() | 428 self.old_interface.GoHome() |
402 | 429 |
403 @decorators.WithTimeoutAndRetriesFromInstance() | 430 @decorators.WithTimeoutAndRetriesFromInstance() |
404 def ForceStop(self, package, timeout=None, retries=None): | 431 def ForceStop(self, package, timeout=None, retries=None): |
405 """Close the application. | 432 """Close the application. |
406 | 433 |
407 Args: | 434 Args: |
408 package: A string containing the name of the package to stop. | 435 package: A string containing the name of the package to stop. |
409 timeout: Same as for |IsOnline|. | 436 timeout: timeout in seconds |
410 retries: Same as for |IsOnline|. | 437 retries: number of retries |
| 438 Raises: |
| 439 CommandTimeoutError on timeout. |
| 440 DeviceUnreachableError on missing device. |
411 """ | 441 """ |
412 self.old_interface.CloseApplication(package) | 442 self.old_interface.CloseApplication(package) |
413 | 443 |
414 @decorators.WithTimeoutAndRetriesFromInstance() | 444 @decorators.WithTimeoutAndRetriesFromInstance() |
415 def ClearApplicationState(self, package, timeout=None, retries=None): | 445 def ClearApplicationState(self, package, timeout=None, retries=None): |
416 """Clear all state for the given package. | 446 """Clear all state for the given package. |
417 | 447 |
418 Args: | 448 Args: |
419 package: A string containing the name of the package to stop. | 449 package: A string containing the name of the package to stop. |
420 timeout: Same as for |IsOnline|. | 450 timeout: timeout in seconds |
421 retries: Same as for |IsOnline|. | 451 retries: number of retries |
| 452 Raises: |
| 453 CommandTimeoutError on timeout. |
| 454 DeviceUnreachableError on missing device. |
422 """ | 455 """ |
423 self.old_interface.ClearApplicationState(package) | 456 self.old_interface.ClearApplicationState(package) |
424 | 457 |
425 @decorators.WithTimeoutAndRetriesFromInstance() | 458 @decorators.WithTimeoutAndRetriesFromInstance() |
426 def SendKeyEvent(self, keycode, timeout=None, retries=None): | 459 def SendKeyEvent(self, keycode, timeout=None, retries=None): |
427 """Sends a keycode to the device. | 460 """Sends a keycode to the device. |
428 | 461 |
429 See: http://developer.android.com/reference/android/view/KeyEvent.html | 462 See: http://developer.android.com/reference/android/view/KeyEvent.html |
430 | 463 |
431 Args: | 464 Args: |
432 keycode: A integer keycode to send to the device. | 465 keycode: A integer keycode to send to the device. |
433 timeout: Same as for |IsOnline|. | 466 timeout: timeout in seconds |
434 retries: Same as for |IsOnline|. | 467 retries: number of retries |
| 468 Raises: |
| 469 CommandTimeoutError on timeout. |
| 470 DeviceUnreachableError on missing device. |
435 """ | 471 """ |
436 self.old_interface.SendKeyEvent(keycode) | 472 self.old_interface.SendKeyEvent(keycode) |
437 | 473 |
438 PUSH_CHANGED_FILES_DEFAULT_TIMEOUT = 10 * _DEFAULT_TIMEOUT | 474 PUSH_CHANGED_FILES_DEFAULT_TIMEOUT = 10 * _DEFAULT_TIMEOUT |
439 PUSH_CHANGED_FILES_DEFAULT_RETRIES = _DEFAULT_RETRIES | 475 PUSH_CHANGED_FILES_DEFAULT_RETRIES = _DEFAULT_RETRIES |
440 | 476 |
441 @decorators.WithTimeoutAndRetriesDefaults( | 477 @decorators.WithTimeoutAndRetriesDefaults( |
442 PUSH_CHANGED_FILES_DEFAULT_TIMEOUT, | 478 PUSH_CHANGED_FILES_DEFAULT_TIMEOUT, |
443 PUSH_CHANGED_FILES_DEFAULT_RETRIES) | 479 PUSH_CHANGED_FILES_DEFAULT_RETRIES) |
444 def PushChangedFiles(self, host_path, device_path, timeout=None, | 480 def PushChangedFiles(self, host_path, device_path, timeout=None, |
445 retries=None): | 481 retries=None): |
446 """Push files to the device, skipping files that don't need updating. | 482 """Push files to the device, skipping files that don't need updating. |
447 | 483 |
448 Args: | 484 Args: |
449 host_path: A string containing the absolute path to the file or directory | 485 host_path: A string containing the absolute path to the file or directory |
450 on the host that should be minimally pushed to the device. | 486 on the host that should be minimally pushed to the device. |
451 device_path: A string containing the absolute path of the destination on | 487 device_path: A string containing the absolute path of the destination on |
452 the device. | 488 the device. |
453 timeout: Same as for |IsOnline|. | 489 timeout: timeout in seconds |
454 retries: Same as for |IsOnline|. | 490 retries: number of retries |
| 491 Raises: |
| 492 CommandFailedError on failure. |
| 493 CommandTimeoutError on timeout. |
| 494 DeviceUnreachableError on missing device. |
455 """ | 495 """ |
456 self.old_interface.PushIfNeeded(host_path, device_path) | 496 self.old_interface.PushIfNeeded(host_path, device_path) |
457 | 497 |
458 @decorators.WithTimeoutAndRetriesFromInstance() | 498 @decorators.WithTimeoutAndRetriesFromInstance() |
459 def FileExists(self, device_path, timeout=None, retries=None): | 499 def FileExists(self, device_path, timeout=None, retries=None): |
460 """Checks whether the given file exists on the device. | 500 """Checks whether the given file exists on the device. |
461 | 501 |
462 Args: | 502 Args: |
463 device_path: A string containing the absolute path to the file on the | 503 device_path: A string containing the absolute path to the file on the |
464 device. | 504 device. |
465 timeout: Same as for |IsOnline|. | 505 timeout: timeout in seconds |
466 retries: Same as for |IsOnline|. | 506 retries: number of retries |
467 Returns: | 507 Returns: |
468 True if the file exists on the device, False otherwise. | 508 True if the file exists on the device, False otherwise. |
| 509 Raises: |
| 510 CommandTimeoutError on timeout. |
| 511 DeviceUnreachableError on missing device. |
469 """ | 512 """ |
470 return self._FileExistsImpl(device_path) | 513 return self._FileExistsImpl(device_path) |
471 | 514 |
472 def _FileExistsImpl(self, device_path): | 515 def _FileExistsImpl(self, device_path): |
473 """Implementation of FileExists. | 516 """Implementation of FileExists. |
474 | 517 |
475 This is split from FileExists to allow other DeviceUtils methods to call | 518 This is split from FileExists to allow other DeviceUtils methods to call |
476 FileExists without spawning a new timeout thread. | 519 FileExists without spawning a new timeout thread. |
477 | 520 |
478 Args: | 521 Args: |
479 device_path: Same as for |FileExists|. | 522 device_path: Same as for |FileExists|. |
480 Returns: | 523 Returns: |
481 True if the file exists on the device, False otherwise. | 524 True if the file exists on the device, False otherwise. |
| 525 Raises: |
| 526 Same as for |FileExists|. |
482 """ | 527 """ |
483 return self.old_interface.FileExistsOnDevice(device_path) | 528 return self.old_interface.FileExistsOnDevice(device_path) |
484 | 529 |
485 @decorators.WithTimeoutAndRetriesFromInstance() | 530 @decorators.WithTimeoutAndRetriesFromInstance() |
486 def PullFile(self, device_path, host_path, timeout=None, retries=None): | 531 def PullFile(self, device_path, host_path, timeout=None, retries=None): |
487 """Pull a file from the device. | 532 """Pull a file from the device. |
488 | 533 |
489 Args: | 534 Args: |
490 device_path: A string containing the absolute path of the file to pull | 535 device_path: A string containing the absolute path of the file to pull |
491 from the device. | 536 from the device. |
492 host_path: A string containing the absolute path of the destination on | 537 host_path: A string containing the absolute path of the destination on |
493 the host. | 538 the host. |
494 timeout: Same as for |IsOnline|. | 539 timeout: timeout in seconds |
495 retries: Same as for |IsOnline|. | 540 retries: number of retries |
| 541 Raises: |
| 542 CommandFailedError on failure. |
| 543 CommandTimeoutError on timeout. |
496 """ | 544 """ |
497 self.old_interface.PullFileFromDevice(device_path, host_path) | 545 try: |
| 546 self.old_interface.PullFileFromDevice(device_path, host_path) |
| 547 except AssertionError as e: |
| 548 raise device_errors.CommandFailedError( |
| 549 str(e), device=str(self)), None, sys.exc_info()[2] |
498 | 550 |
499 @decorators.WithTimeoutAndRetriesFromInstance() | 551 @decorators.WithTimeoutAndRetriesFromInstance() |
500 def ReadFile(self, device_path, as_root=False, timeout=None, retries=None): | 552 def ReadFile(self, device_path, as_root=False, timeout=None, retries=None): |
501 """Reads the contents of a file from the device. | 553 """Reads the contents of a file from the device. |
502 | 554 |
503 Args: | 555 Args: |
504 device_path: A string containing the absolute path of the file to read | 556 device_path: A string containing the absolute path of the file to read |
505 from the device. | 557 from the device. |
506 as_root: A boolean indicating whether the read should be executed with | 558 as_root: A boolean indicating whether the read should be executed with |
507 root privileges. | 559 root privileges. |
508 timeout: Same as for |IsOnline|. | 560 timeout: timeout in seconds |
509 retries: Same as for |IsOnline|. | 561 retries: number of retries |
510 Returns: | 562 Returns: |
511 The contents of the file at |device_path| as a list of lines. | 563 The contents of the file at |device_path| as a list of lines. |
512 Raises: | 564 Raises: |
513 CommandFailedError if the file can't be read. | 565 CommandFailedError if the file can't be read. |
| 566 CommandTimeoutError on timeout. |
| 567 DeviceUnreachableError on missing device. |
514 """ | 568 """ |
515 # TODO(jbudorick) Evaluate whether we actually want to return a list of | 569 # TODO(jbudorick) Evaluate whether we actually want to return a list of |
516 # lines after the implementation switch. | 570 # lines after the implementation switch. |
517 if as_root: | 571 if as_root: |
518 if not self.old_interface.CanAccessProtectedFileContents(): | 572 if not self.old_interface.CanAccessProtectedFileContents(): |
519 raise device_errors.CommandFailedError( | 573 raise device_errors.CommandFailedError( |
520 'Cannot read from %s with root privileges.' % device_path) | 574 'Cannot read from %s with root privileges.' % device_path) |
521 return self.old_interface.GetProtectedFileContents(device_path) | 575 return self.old_interface.GetProtectedFileContents(device_path) |
522 else: | 576 else: |
523 return self.old_interface.GetFileContents(device_path) | 577 return self.old_interface.GetFileContents(device_path) |
524 | 578 |
525 @decorators.WithTimeoutAndRetriesFromInstance() | 579 @decorators.WithTimeoutAndRetriesFromInstance() |
526 def WriteFile(self, device_path, contents, as_root=False, timeout=None, | 580 def WriteFile(self, device_path, contents, as_root=False, timeout=None, |
527 retries=None): | 581 retries=None): |
528 """Writes |contents| to a file on the device. | 582 """Writes |contents| to a file on the device. |
529 | 583 |
530 Args: | 584 Args: |
531 device_path: A string containing the absolute path to the file to write | 585 device_path: A string containing the absolute path to the file to write |
532 on the device. | 586 on the device. |
533 contents: A string containing the data to write to the device. | 587 contents: A string containing the data to write to the device. |
534 as_root: A boolean indicating whether the write should be executed with | 588 as_root: A boolean indicating whether the write should be executed with |
535 root privileges. | 589 root privileges. |
536 timeout: Same as for |IsOnline|. | 590 timeout: timeout in seconds |
537 retries: Same as for |IsOnline|. | 591 retries: number of retries |
538 Raises: | 592 Raises: |
539 CommandFailedError if the file could not be written on the device. | 593 CommandFailedError if the file could not be written on the device. |
| 594 CommandTimeoutError on timeout. |
| 595 DeviceUnreachableError on missing device. |
540 """ | 596 """ |
541 if as_root: | 597 if as_root: |
542 if not self.old_interface.CanAccessProtectedFileContents(): | 598 if not self.old_interface.CanAccessProtectedFileContents(): |
543 raise device_errors.CommandFailedError( | 599 raise device_errors.CommandFailedError( |
544 'Cannot write to %s with root privileges.' % device_path) | 600 'Cannot write to %s with root privileges.' % device_path) |
545 self.old_interface.SetProtectedFileContents(device_path, contents) | 601 self.old_interface.SetProtectedFileContents(device_path, contents) |
546 else: | 602 else: |
547 self.old_interface.SetFileContents(device_path, contents) | 603 self.old_interface.SetFileContents(device_path, contents) |
548 | 604 |
549 @decorators.WithTimeoutAndRetriesFromInstance() | 605 @decorators.WithTimeoutAndRetriesFromInstance() |
550 def Ls(self, device_path, timeout=None, retries=None): | 606 def Ls(self, device_path, timeout=None, retries=None): |
551 """Lists the contents of a directory on the device. | 607 """Lists the contents of a directory on the device. |
552 | 608 |
553 Args: | 609 Args: |
554 device_path: A string containing the path of the directory on the device | 610 device_path: A string containing the path of the directory on the device |
555 to list. | 611 to list. |
556 timeout: Same as for |IsOnline|. | 612 timeout: timeout in seconds |
557 retries: Same as for |IsOnline|. | 613 retries: number of retries |
558 Returns: | 614 Returns: |
559 The contents of the directory specified by |device_path|. | 615 The contents of the directory specified by |device_path|. |
| 616 Raises: |
| 617 CommandTimeoutError on timeout. |
| 618 DeviceUnreachableError on missing device. |
560 """ | 619 """ |
561 return self.old_interface.ListPathContents(device_path) | 620 return self.old_interface.ListPathContents(device_path) |
562 | 621 |
563 @decorators.WithTimeoutAndRetriesFromInstance() | 622 @decorators.WithTimeoutAndRetriesFromInstance() |
564 def SetJavaAsserts(self, enabled, timeout=None, retries=None): | 623 def SetJavaAsserts(self, enabled, timeout=None, retries=None): |
565 """Enables or disables Java asserts. | 624 """Enables or disables Java asserts. |
566 | 625 |
567 Args: | 626 Args: |
568 enabled: A boolean indicating whether Java asserts should be enabled | 627 enabled: A boolean indicating whether Java asserts should be enabled |
569 or disabled. | 628 or disabled. |
570 timeout: Same as for |IsOnline|. | 629 timeout: timeout in seconds |
571 retries: Same as for |IsOnline|. | 630 retries: number of retries |
| 631 Raises: |
| 632 CommandTimeoutError on timeout. |
572 """ | 633 """ |
573 self.old_interface.SetJavaAssertsEnabled(enabled) | 634 self.old_interface.SetJavaAssertsEnabled(enabled) |
574 | 635 |
575 @decorators.WithTimeoutAndRetriesFromInstance() | 636 @decorators.WithTimeoutAndRetriesFromInstance() |
576 def GetProp(self, property_name, timeout=None, retries=None): | 637 def GetProp(self, property_name, timeout=None, retries=None): |
577 """Gets a property from the device. | 638 """Gets a property from the device. |
578 | 639 |
579 Args: | 640 Args: |
580 property_name: A string containing the name of the property to get from | 641 property_name: A string containing the name of the property to get from |
581 the device. | 642 the device. |
582 timeout: Same as for |IsOnline|. | 643 timeout: timeout in seconds |
583 retries: Same as for |IsOnline|. | 644 retries: number of retries |
584 Returns: | 645 Returns: |
585 The value of the device's |property_name| property. | 646 The value of the device's |property_name| property. |
| 647 Raises: |
| 648 CommandTimeoutError on timeout. |
586 """ | 649 """ |
587 return self.old_interface.system_properties[property_name] | 650 return self.old_interface.system_properties[property_name] |
588 | 651 |
589 @decorators.WithTimeoutAndRetriesFromInstance() | 652 @decorators.WithTimeoutAndRetriesFromInstance() |
590 def SetProp(self, property_name, value, timeout=None, retries=None): | 653 def SetProp(self, property_name, value, timeout=None, retries=None): |
591 """Sets a property on the device. | 654 """Sets a property on the device. |
592 | 655 |
593 Args: | 656 Args: |
594 property_name: A string containing the name of the property to set on | 657 property_name: A string containing the name of the property to set on |
595 the device. | 658 the device. |
596 value: A string containing the value to set to the property on the | 659 value: A string containing the value to set to the property on the |
597 device. | 660 device. |
598 timeout: Same as for |IsOnline|. | 661 timeout: timeout in seconds |
599 retries: Same as for |IsOnline|. | 662 retries: number of retries |
| 663 Raises: |
| 664 CommandTimeoutError on timeout. |
600 """ | 665 """ |
601 self.old_interface.system_properties[property_name] = value | 666 self.old_interface.system_properties[property_name] = value |
602 | 667 |
| 668 @decorators.WithTimeoutAndRetriesFromInstance() |
| 669 def GetPids(self, process_name, timeout=None, retries=None): |
| 670 """Returns the PIDs of processes with the given name. |
| 671 |
| 672 Note that the |process_name| is often the package name. |
| 673 |
| 674 Args: |
| 675 process_name: A string containing the process name to get the PIDs for. |
| 676 timeout: timeout in seconds |
| 677 retries: number of retries |
| 678 Returns: |
| 679 A dict mapping process name to PID for each process that contained the |
| 680 provided |process_name|. |
| 681 Raises: |
| 682 CommandTimeoutError on timeout. |
| 683 DeviceUnreachableError on missing device. |
| 684 """ |
| 685 procs_pids = {} |
| 686 for line in self._RunShellCommandImpl('ps'): |
| 687 try: |
| 688 ps_data = line.split() |
| 689 if process_name in ps_data[-1]: |
| 690 procs_pids[ps_data[-1]] = ps_data[1] |
| 691 except IndexError: |
| 692 pass |
| 693 return procs_pids |
| 694 |
| 695 @decorators.WithTimeoutAndRetriesFromInstance() |
| 696 def TakeScreenshot(self, host_path=None, timeout=None, retries=None): |
| 697 """Takes a screenshot of the device. |
| 698 |
| 699 Args: |
| 700 host_path: A string containing the path on the host to save the |
| 701 screenshot to. If None, a file name will be generated. |
| 702 timeout: timeout in seconds |
| 703 retries: number of retries |
| 704 Returns: |
| 705 The name of the file on the host to which the screenshot was saved. |
| 706 Raises: |
| 707 CommandFailedError on failure. |
| 708 CommandTimeoutError on timeout. |
| 709 DeviceUnreachableError on missing device. |
| 710 """ |
| 711 return self.old_interface.TakeScreenshot(host_path) |
| 712 |
| 713 @decorators.WithTimeoutAndRetriesFromInstance() |
| 714 def GetIOStats(self, timeout=None, retries=None): |
| 715 """Gets cumulative disk IO stats since boot for all processes. |
| 716 |
| 717 Args: |
| 718 timeout: timeout in seconds |
| 719 retries: number of retries |
| 720 Returns: |
| 721 A dict containing |num_reads|, |num_writes|, |read_ms|, and |write_ms|. |
| 722 Raises: |
| 723 CommandTimeoutError on timeout. |
| 724 DeviceUnreachableError on missing device. |
| 725 """ |
| 726 return self.old_interface.GetIoStats() |
| 727 |
603 def __str__(self): | 728 def __str__(self): |
604 """Returns the device serial.""" | 729 """Returns the device serial.""" |
605 return self.old_interface.GetDevice() | 730 return self.old_interface.GetDevice() |
606 | 731 |
607 @staticmethod | 732 @staticmethod |
608 def parallel(devices=None, async=False): | 733 def parallel(devices=None, async=False): |
609 """Creates a Parallelizer to operate over the provided list of devices. | 734 """Creates a Parallelizer to operate over the provided list of devices. |
610 | 735 |
611 If |devices| is either |None| or an empty list, the Parallelizer will | 736 If |devices| is either |None| or an empty list, the Parallelizer will |
612 operate over all attached devices. | 737 operate over all attached devices. |
613 | 738 |
614 Args: | 739 Args: |
615 devices: A list of either DeviceUtils instances or objects from | 740 devices: A list of either DeviceUtils instances or objects from |
616 from which DeviceUtils instances can be constructed. If None, | 741 from which DeviceUtils instances can be constructed. If None, |
617 all attached devices will be used. | 742 all attached devices will be used. |
618 async: If true, returns a Parallelizer that runs operations | 743 async: If true, returns a Parallelizer that runs operations |
619 asynchronously. | 744 asynchronously. |
620 Returns: | 745 Returns: |
621 A Parallelizer operating over |devices|. | 746 A Parallelizer operating over |devices|. |
622 """ | 747 """ |
623 if not devices or len(devices) == 0: | 748 if not devices or len(devices) == 0: |
624 devices = pylib.android_commands.GetAttachedDevices() | 749 devices = pylib.android_commands.GetAttachedDevices() |
625 parallelizer_type = (parallelizer.Parallelizer if async | 750 parallelizer_type = (parallelizer.Parallelizer if async |
626 else parallelizer.SyncParallelizer) | 751 else parallelizer.SyncParallelizer) |
627 return parallelizer_type([ | 752 return parallelizer_type([ |
628 d if isinstance(d, DeviceUtils) else DeviceUtils(d) | 753 d if isinstance(d, DeviceUtils) else DeviceUtils(d) |
629 for d in devices]) | 754 for d in devices]) |
630 | 755 |
OLD | NEW |