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

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: 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
« no previous file with comments | « build/android/pylib/content_settings.py ('k') | build/android/pylib/device/intent.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 signal
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 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 out = self.old_interface.Install(apk_path, reinstall=reinstall) 238 out = self.old_interface.Install(apk_path, reinstall=reinstall)
238 for line in out.splitlines(): 239 for line in out.splitlines():
239 if 'Failure' in line: 240 if 'Failure' in line:
240 raise device_errors.CommandFailedError( 241 raise device_errors.CommandFailedError(
241 ['adb', 'install', apk_path], line.strip()) 242 ['adb', 'install', apk_path], line.strip())
242 except AssertionError as e: 243 except AssertionError as e:
243 raise device_errors.CommandFailedError( 244 raise device_errors.CommandFailedError(
244 ['adb', 'install', apk_path], str(e)) 245 ['adb', 'install', apk_path], str(e))
245 246
246 @decorators.WithTimeoutAndRetriesFromInstance() 247 @decorators.WithTimeoutAndRetriesFromInstance()
247 def RunShellCommand(self, cmd, check_return=False, root=False, timeout=None, 248 def RunShellCommand(self, cmd, check_return=False, as_root=False,
248 retries=None): 249 timeout=None, retries=None):
249 """Run an ADB shell command. 250 """Run an ADB shell command.
250 251
251 TODO(jbudorick) Switch the default value of check_return to True after 252 TODO(jbudorick) Switch the default value of check_return to True after
252 AndroidCommands is gone. 253 AndroidCommands is gone.
253 254
254 Args: 255 Args:
255 cmd: A list containing the command to run on the device and any arguments. 256 cmd: A list containing the command to run on the device and any arguments.
256 check_return: A boolean indicating whether or not the return code should 257 check_return: A boolean indicating whether or not the return code should
257 be checked. 258 be checked.
259 as_root: A boolean indicating whether the shell command should be run
260 with root privileges.
258 timeout: Same as for |IsOnline|. 261 timeout: Same as for |IsOnline|.
259 retries: Same as for |IsOnline|. 262 retries: Same as for |IsOnline|.
260 Raises: 263 Raises:
261 CommandFailedError if check_return is True and the return code is nozero. 264 CommandFailedError if check_return is True and the return code is nozero.
262 Returns: 265 Returns:
263 The output of the command. 266 The output of the command.
264 """ 267 """
265 return self._RunShellCommandImpl(cmd, check_return=check_return, root=root, 268 return self._RunShellCommandImpl(cmd, check_return=check_return,
266 timeout=timeout) 269 as_root=as_root, timeout=timeout)
267 270
268 def _RunShellCommandImpl(self, cmd, check_return=False, root=False, 271 def _RunShellCommandImpl(self, cmd, check_return=False, as_root=False,
269 timeout=None): 272 timeout=None):
270 """Implementation of RunShellCommand. 273 """Implementation of RunShellCommand.
271 274
272 This is split from RunShellCommand to allow other DeviceUtils methods to 275 This is split from RunShellCommand to allow other DeviceUtils methods to
273 call RunShellCommand without spawning a new timeout thread. 276 call RunShellCommand without spawning a new timeout thread.
274 277
275 TODO(jbudorick) Remove the timeout parameter once this is no longer 278 TODO(jbudorick) Remove the timeout parameter once this is no longer
276 implemented via AndroidCommands. 279 implemented via AndroidCommands.
277 280
278 Args: 281 Args:
279 cmd: Same as for |RunShellCommand|. 282 cmd: Same as for |RunShellCommand|.
280 check_return: Same as for |RunShellCommand|. 283 check_return: Same as for |RunShellCommand|.
284 as_root: Same as for |RunShellCommand|.
281 timeout: Same as for |IsOnline|. 285 timeout: Same as for |IsOnline|.
282 Raises: 286 Raises:
283 Same as for |RunShellCommand|. 287 Same as for |RunShellCommand|.
284 Returns: 288 Returns:
285 Same as for |RunShellCommand|. 289 Same as for |RunShellCommand|.
286 """ 290 """
287 if isinstance(cmd, list): 291 if isinstance(cmd, list):
288 cmd = ' '.join(cmd) 292 cmd = ' '.join(cmd)
289 if root and not self.HasRoot(): 293 if as_root and not self.HasRoot():
290 cmd = 'su -c %s' % cmd 294 cmd = 'su -c %s' % cmd
291 if check_return: 295 if check_return:
292 code, output = self.old_interface.GetShellCommandStatusAndOutput( 296 code, output = self.old_interface.GetShellCommandStatusAndOutput(
293 cmd, timeout_time=timeout) 297 cmd, timeout_time=timeout)
294 if int(code) != 0: 298 if int(code) != 0:
295 raise device_errors.CommandFailedError( 299 raise device_errors.CommandFailedError(
296 cmd, 'Nonzero exit code (%d)' % code) 300 cmd, 'Nonzero exit code (%d)' % code)
297 else: 301 else:
298 output = self.old_interface.RunShellCommand(cmd, timeout_time=timeout) 302 output = self.old_interface.RunShellCommand(cmd, timeout_time=timeout)
299 return output 303 return output
300 304
305 @decorators.WithTimeoutAndRetriesFromInstance()
306 def KillAll(self, process_name, signum=signal.SIGKILL, as_root=False,
307 blocking=False, timeout=None, retries=None):
308 """Kill all processes with the given name on the device.
309
frankf 2014/06/20 00:56:56 Update the docstring to include the exception
jbudorick 2014/06/23 16:44:02 Done.
310 Args:
311 process_name: A string containing the name of the process to kill.
312 signum: An integer containing the signal number to send to kill. Defaults
313 to 9 (SIGKILL).
314 as_root: A boolean indicating whether the kill should be executed with
315 root priveleges.
316 blocking: A boolean indicating whether we should wait until all processes
317 with the given |process_name| are dead.
318 timeout: Same as for |IsOnline|.
319 retries: Same as for |IsOnline|.
320 """
321 pids = self.old_interface.ExtractPid(process_name)
322 if len(pids) == 0:
323 raise device_errors.CommandFailedError(
324 ['adb', 'shell', 'kill'], 'No process "%s"' % process_name)
frankf 2014/06/20 00:56:55 Why does this include such a command list? You hav
jbudorick 2014/06/23 16:44:02 Created a new AdbCommandFailedError that derives f
325
326 if blocking:
327 total_killed = self.old_interface.KillAllBlocking(
328 process_name, signum=signum, with_su=as_root, timeout_sec=timeout)
329 else:
330 total_killed = self.old_interface.KillAll(
331 process_name, signum=signum, with_su=as_root)
332 if total_killed == 0:
333 raise device_errors.CommandFailedError(
334 ['adb', 'shell', 'kill'], 'Failed to kill "%s"' % process_name)
335
336 @decorators.WithTimeoutAndRetriesFromInstance()
337 def StartActivity(self, intent, blocking=False, trace_file_name=None,
338 force_stop=False, timeout=None, retries=None):
339 """Start package's activity on the device.
340
341 Args:
342 intent: An Intent to send.
343 blocking: A boolean indicating whether we should wait for the activity to
344 finish launching.
345 trace_file_name: If present, a string that both indicates that we want to
346 profile the activity and contains the path to which the
347 trace should be saved.
348 force_stop: A boolean indicating whether we should stop the activity
349 before starting it.
350 timeout: Same as for |IsOnline|.
351 retries: Same as for |IsOnline|.
352 """
353 output = self.old_interface.StartActivity(
354 intent.package, intent.activity, wait_for_completion=blocking,
355 action=intent.action, category=intent.category, data=intent.data,
356 extras=intent.extras, trace_file_name=trace_file_name,
357 force_stop=force_stop, flags=intent.flags)
358 for l in output:
359 if l.startswith('Error:'):
360 raise device_errors.CommandFailedError(
361 ['adb', 'shell', 'am', 'start'], l)
frankf 2014/06/20 00:56:55 same here
jbudorick 2014/06/23 16:44:02 using the reworked CommandFailedError, as describe
362
363 @decorators.WithTimeoutAndRetriesFromInstance()
364 def BroadcastIntent(self, intent, timeout=None, retries=None):
365 """Send a broadcast intent.
366
367 Args:
368 intent: An Intent to broadcast.
369 timeout: Same as for |IsOnline|.
370 retries: Same as for |IsOnline|.
371 """
372 package, old_intent = intent.action.rsplit('.', 1)
373 if intent.extras is None:
374 args = []
375 else:
376 args = ['-e %s%s' % (k, ' "%s"' % v if v else '')
377 for k, v in intent.extras.items() if len(k) > 0]
378 self.old_interface.BroadcastIntent(package, old_intent, *args)
379
301 def __str__(self): 380 def __str__(self):
302 """Returns the device serial.""" 381 """Returns the device serial."""
303 return self.old_interface.GetDevice() 382 return self.old_interface.GetDevice()
304 383
305 @staticmethod 384 @staticmethod
306 def parallel(devices=None, async=False): 385 def parallel(devices=None, async=False):
307 """Creates a Parallelizer to operate over the provided list of devices. 386 """Creates a Parallelizer to operate over the provided list of devices.
308 387
309 If |devices| is either |None| or an empty list, the Parallelizer will 388 If |devices| is either |None| or an empty list, the Parallelizer will
310 operate over all attached devices. 389 operate over all attached devices.
311 390
312 Args: 391 Args:
313 devices: A list of either DeviceUtils instances or objects from 392 devices: A list of either DeviceUtils instances or objects from
314 from which DeviceUtils instances can be constructed. If None, 393 from which DeviceUtils instances can be constructed. If None,
315 all attached devices will be used. 394 all attached devices will be used.
316 async: If true, returns a Parallelizer that runs operations 395 async: If true, returns a Parallelizer that runs operations
317 asynchronously. 396 asynchronously.
318 Returns: 397 Returns:
319 A Parallelizer operating over |devices|. 398 A Parallelizer operating over |devices|.
320 """ 399 """
321 if not devices or len(devices) == 0: 400 if not devices or len(devices) == 0:
322 devices = pylib.android_commands.GetAttachedDevices() 401 devices = pylib.android_commands.GetAttachedDevices()
323 parallelizer_type = (parallelizer.Parallelizer if async 402 parallelizer_type = (parallelizer.Parallelizer if async
324 else parallelizer.SyncParallelizer) 403 else parallelizer.SyncParallelizer)
325 return parallelizer_type([ 404 return parallelizer_type([
326 d if isinstance(d, DeviceUtils) else DeviceUtils(d) 405 d if isinstance(d, DeviceUtils) else DeviceUtils(d)
327 for d in devices]) 406 for d in devices])
328 407
OLDNEW
« no previous file with comments | « build/android/pylib/content_settings.py ('k') | build/android/pylib/device/intent.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698