Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Side by Side Diff: build/android/pylib/device/device_utils.py

Issue 338353004: [Android] Switch KillAll, StartActivity, and BroadcastIntent to DeviceUtils. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: appeasing windows Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
11 import sys
11 import time 12 import time
12 13
13 import pylib.android_commands 14 import pylib.android_commands
14 from pylib.device import adb_wrapper 15 from pylib.device import adb_wrapper
15 from pylib.device import decorators 16 from pylib.device import decorators
16 from pylib.device import device_errors 17 from pylib.device import device_errors
17 from pylib.utils import apk_helper 18 from pylib.utils import apk_helper
18 from pylib.utils import parallelizer 19 from pylib.utils import parallelizer
19 20
20 _DEFAULT_TIMEOUT = 30 21 _DEFAULT_TIMEOUT = 30
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 """Restarts adbd with root privileges. 118 """Restarts adbd with root privileges.
118 119
119 Args: 120 Args:
120 timeout: Same as for |IsOnline|. 121 timeout: Same as for |IsOnline|.
121 retries: Same as for |IsOnline|. 122 retries: Same as for |IsOnline|.
122 Raises: 123 Raises:
123 CommandFailedError if root could not be enabled. 124 CommandFailedError if root could not be enabled.
124 """ 125 """
125 if not self.old_interface.EnableAdbRoot(): 126 if not self.old_interface.EnableAdbRoot():
126 raise device_errors.CommandFailedError( 127 raise device_errors.CommandFailedError(
127 ['adb', 'root'], 'Could not enable root.') 128 'Could not enable root.', device=str(self))
128 129
129 @decorators.WithTimeoutAndRetriesFromInstance() 130 @decorators.WithTimeoutAndRetriesFromInstance()
130 def GetExternalStoragePath(self, timeout=None, retries=None): 131 def GetExternalStoragePath(self, timeout=None, retries=None):
131 """Get the device's path to its SD card. 132 """Get the device's path to its SD card.
132 133
133 Args: 134 Args:
134 timeout: Same as for |IsOnline|. 135 timeout: Same as for |IsOnline|.
135 retries: Same as for |IsOnline|. 136 retries: Same as for |IsOnline|.
136 Returns: 137 Returns:
137 The device's path to its SD card. 138 The device's path to its SD card.
138 """ 139 """
139 try: 140 try:
140 return self.old_interface.GetExternalStorage() 141 return self.old_interface.GetExternalStorage()
141 except AssertionError as e: 142 except AssertionError as e:
142 raise device_errors.CommandFailedError( 143 raise device_errors.CommandFailedError(
143 ['adb', 'shell', 'echo', '$EXTERNAL_STORAGE'], str(e)) 144 str(e), device=str(self)), None, sys.exc_info()[2]
144 145
145 @decorators.WithTimeoutAndRetriesFromInstance() 146 @decorators.WithTimeoutAndRetriesFromInstance()
146 def WaitUntilFullyBooted(self, wifi=False, timeout=None, retries=None): 147 def WaitUntilFullyBooted(self, wifi=False, timeout=None, retries=None):
147 """Wait for the device to fully boot. 148 """Wait for the device to fully boot.
148 149
149 This means waiting for the device to boot, the package manager to be 150 This means waiting for the device to boot, the package manager to be
150 available, and the SD card to be ready. It can optionally mean waiting 151 available, and the SD card to be ready. It can optionally mean waiting
151 for wifi to come up, too. 152 for wifi to come up, too.
152 153
153 Args: 154 Args:
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 if device_path is not None: 229 if device_path is not None:
229 files_changed = self.old_interface.GetFilesChanged( 230 files_changed = self.old_interface.GetFilesChanged(
230 apk_path, device_path, ignore_filenames=True) 231 apk_path, device_path, ignore_filenames=True)
231 if len(files_changed) > 0: 232 if len(files_changed) > 0:
232 should_install = True 233 should_install = True
233 if not reinstall: 234 if not reinstall:
234 out = self.old_interface.Uninstall(package_name) 235 out = self.old_interface.Uninstall(package_name)
235 for line in out.splitlines(): 236 for line in out.splitlines():
236 if 'Failure' in line: 237 if 'Failure' in line:
237 raise device_errors.CommandFailedError( 238 raise device_errors.CommandFailedError(
238 ['adb', 'uninstall', package_name], line.strip()) 239 line.strip(), device=str(self))
239 else: 240 else:
240 should_install = False 241 should_install = False
241 else: 242 else:
242 should_install = True 243 should_install = True
243 if should_install: 244 if should_install:
244 try: 245 try:
245 out = self.old_interface.Install(apk_path, reinstall=reinstall) 246 out = self.old_interface.Install(apk_path, reinstall=reinstall)
246 for line in out.splitlines(): 247 for line in out.splitlines():
247 if 'Failure' in line: 248 if 'Failure' in line:
248 raise device_errors.CommandFailedError( 249 raise device_errors.CommandFailedError(
249 ['adb', 'install', apk_path], line.strip()) 250 line.strip(), device=str(self))
250 except AssertionError as e: 251 except AssertionError as e:
251 raise device_errors.CommandFailedError( 252 raise device_errors.CommandFailedError(
252 ['adb', 'install', apk_path], str(e)) 253 str(e), device=str(self)), None, sys.exc_info()[2]
253 254
254 @decorators.WithTimeoutAndRetriesFromInstance() 255 @decorators.WithTimeoutAndRetriesFromInstance()
255 def RunShellCommand(self, cmd, check_return=False, root=False, timeout=None, 256 def RunShellCommand(self, cmd, check_return=False, as_root=False,
256 retries=None): 257 timeout=None, retries=None):
257 """Run an ADB shell command. 258 """Run an ADB shell command.
258 259
259 TODO(jbudorick) Switch the default value of check_return to True after 260 TODO(jbudorick) Switch the default value of check_return to True after
260 AndroidCommands is gone. 261 AndroidCommands is gone.
261 262
262 Args: 263 Args:
263 cmd: A list containing the command to run on the device and any arguments. 264 cmd: A list containing the command to run on the device and any arguments.
264 check_return: A boolean indicating whether or not the return code should 265 check_return: A boolean indicating whether or not the return code should
265 be checked. 266 be checked.
267 as_root: A boolean indicating whether the shell command should be run
268 with root privileges.
266 timeout: Same as for |IsOnline|. 269 timeout: Same as for |IsOnline|.
267 retries: Same as for |IsOnline|. 270 retries: Same as for |IsOnline|.
268 Raises: 271 Raises:
269 CommandFailedError if check_return is True and the return code is nozero. 272 CommandFailedError if check_return is True and the return code is nozero.
270 Returns: 273 Returns:
271 The output of the command. 274 The output of the command.
272 """ 275 """
273 return self._RunShellCommandImpl(cmd, check_return=check_return, root=root, 276 return self._RunShellCommandImpl(cmd, check_return=check_return,
274 timeout=timeout) 277 as_root=as_root, timeout=timeout)
275 278
276 def _RunShellCommandImpl(self, cmd, check_return=False, root=False, 279 def _RunShellCommandImpl(self, cmd, check_return=False, as_root=False,
277 timeout=None): 280 timeout=None):
278 """Implementation of RunShellCommand. 281 """Implementation of RunShellCommand.
279 282
280 This is split from RunShellCommand to allow other DeviceUtils methods to 283 This is split from RunShellCommand to allow other DeviceUtils methods to
281 call RunShellCommand without spawning a new timeout thread. 284 call RunShellCommand without spawning a new timeout thread.
282 285
283 TODO(jbudorick) Remove the timeout parameter once this is no longer 286 TODO(jbudorick) Remove the timeout parameter once this is no longer
284 implemented via AndroidCommands. 287 implemented via AndroidCommands.
285 288
286 Args: 289 Args:
287 cmd: Same as for |RunShellCommand|. 290 cmd: Same as for |RunShellCommand|.
288 check_return: Same as for |RunShellCommand|. 291 check_return: Same as for |RunShellCommand|.
292 as_root: Same as for |RunShellCommand|.
289 timeout: Same as for |IsOnline|. 293 timeout: Same as for |IsOnline|.
290 Raises: 294 Raises:
291 Same as for |RunShellCommand|. 295 Same as for |RunShellCommand|.
292 Returns: 296 Returns:
293 Same as for |RunShellCommand|. 297 Same as for |RunShellCommand|.
294 """ 298 """
295 if isinstance(cmd, list): 299 if isinstance(cmd, list):
296 cmd = ' '.join(cmd) 300 cmd = ' '.join(cmd)
297 if root and not self.HasRoot(): 301 if as_root and not self.HasRoot():
298 cmd = 'su -c %s' % cmd 302 cmd = 'su -c %s' % cmd
299 if check_return: 303 if check_return:
300 code, output = self.old_interface.GetShellCommandStatusAndOutput( 304 code, output = self.old_interface.GetShellCommandStatusAndOutput(
301 cmd, timeout_time=timeout) 305 cmd, timeout_time=timeout)
302 if int(code) != 0: 306 if int(code) != 0:
303 raise device_errors.CommandFailedError( 307 raise device_errors.AdbCommandFailedError(
304 cmd.split(), 'Nonzero exit code (%d)' % code) 308 cmd.split(), 'Nonzero exit code (%d)' % code, device=str(self))
305 else: 309 else:
306 output = self.old_interface.RunShellCommand(cmd, timeout_time=timeout) 310 output = self.old_interface.RunShellCommand(cmd, timeout_time=timeout)
307 return output 311 return output
308 312
313 @decorators.WithTimeoutAndRetriesFromInstance()
314 def KillAll(self, process_name, signum=9, as_root=False, blocking=False,
315 timeout=None, retries=None):
316 """Kill all processes with the given name on the device.
317
318 Args:
319 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
321 to 9 (SIGKILL).
322 as_root: A boolean indicating whether the kill should be executed with
323 root priveleges.
324 blocking: A boolean indicating whether we should wait until all processes
325 with the given |process_name| are dead.
326 timeout: Same as for |IsOnline|.
327 retries: Same as for |IsOnline|.
328 Raises:
329 CommandFailedError if no process was killed.
330 """
331 pids = self.old_interface.ExtractPid(process_name)
332 if len(pids) == 0:
333 raise device_errors.CommandFailedError(
334 'No process "%s"' % process_name, device=str(self))
335
336 if blocking:
337 total_killed = self.old_interface.KillAllBlocking(
338 process_name, signum=signum, with_su=as_root, timeout_sec=timeout)
339 else:
340 total_killed = self.old_interface.KillAll(
341 process_name, signum=signum, with_su=as_root)
342 if total_killed == 0:
343 raise device_errors.CommandFailedError(
344 'Failed to kill "%s"' % process_name, device=str(self))
345
346 @decorators.WithTimeoutAndRetriesFromInstance()
347 def StartActivity(self, intent, blocking=False, trace_file_name=None,
348 force_stop=False, timeout=None, retries=None):
349 """Start package's activity on the device.
350
351 Args:
352 intent: An Intent to send.
353 blocking: A boolean indicating whether we should wait for the activity to
354 finish launching.
355 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
357 trace should be saved.
358 force_stop: A boolean indicating whether we should stop the activity
359 before starting it.
360 timeout: Same as for |IsOnline|.
361 retries: Same as for |IsOnline|.
362 Raises:
363 CommandFailedError if the activity could not be started.
364 """
365 single_category = (intent.category[0] if isinstance(intent.category, list)
366 else intent.category)
367 output = self.old_interface.StartActivity(
368 intent.package, intent.activity, wait_for_completion=blocking,
369 action=intent.action, category=single_category, data=intent.data,
370 extras=intent.extras, trace_file_name=trace_file_name,
371 force_stop=force_stop, flags=intent.flags)
372 for l in output:
373 if l.startswith('Error:'):
374 raise device_errors.CommandFailedError(l, device=str(self))
375
376 @decorators.WithTimeoutAndRetriesFromInstance()
377 def BroadcastIntent(self, intent, timeout=None, retries=None):
378 """Send a broadcast intent.
379
380 Args:
381 intent: An Intent to broadcast.
382 timeout: Same as for |IsOnline|.
383 retries: Same as for |IsOnline|.
384 """
385 package, old_intent = intent.action.rsplit('.', 1)
386 if intent.extras is None:
387 args = []
388 else:
389 args = ['-e %s%s' % (k, ' "%s"' % v if v else '')
390 for k, v in intent.extras.items() if len(k) > 0]
391 self.old_interface.BroadcastIntent(package, old_intent, *args)
392
309 def __str__(self): 393 def __str__(self):
310 """Returns the device serial.""" 394 """Returns the device serial."""
311 return self.old_interface.GetDevice() 395 return self.old_interface.GetDevice()
312 396
313 @staticmethod 397 @staticmethod
314 def parallel(devices=None, async=False): 398 def parallel(devices=None, async=False):
315 """Creates a Parallelizer to operate over the provided list of devices. 399 """Creates a Parallelizer to operate over the provided list of devices.
316 400
317 If |devices| is either |None| or an empty list, the Parallelizer will 401 If |devices| is either |None| or an empty list, the Parallelizer will
318 operate over all attached devices. 402 operate over all attached devices.
319 403
320 Args: 404 Args:
321 devices: A list of either DeviceUtils instances or objects from 405 devices: A list of either DeviceUtils instances or objects from
322 from which DeviceUtils instances can be constructed. If None, 406 from which DeviceUtils instances can be constructed. If None,
323 all attached devices will be used. 407 all attached devices will be used.
324 async: If true, returns a Parallelizer that runs operations 408 async: If true, returns a Parallelizer that runs operations
325 asynchronously. 409 asynchronously.
326 Returns: 410 Returns:
327 A Parallelizer operating over |devices|. 411 A Parallelizer operating over |devices|.
328 """ 412 """
329 if not devices or len(devices) == 0: 413 if not devices or len(devices) == 0:
330 devices = pylib.android_commands.GetAttachedDevices() 414 devices = pylib.android_commands.GetAttachedDevices()
331 parallelizer_type = (parallelizer.Parallelizer if async 415 parallelizer_type = (parallelizer.Parallelizer if async
332 else parallelizer.SyncParallelizer) 416 else parallelizer.SyncParallelizer)
333 return parallelizer_type([ 417 return parallelizer_type([
334 d if isinstance(d, DeviceUtils) else DeviceUtils(d) 418 d if isinstance(d, DeviceUtils) else DeviceUtils(d)
335 for d in devices]) 419 for d in devices])
336 420
OLDNEW
« no previous file with comments | « build/android/pylib/device/device_errors.py ('k') | build/android/pylib/device/device_utils_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698