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

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

Powered by Google App Engine
This is Rietveld 408576698