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

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

Issue 839893004: Refactor test scripts for android to improve performance (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Cache application paths Created 5 years, 11 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 | « no previous file | build/android/pylib/gtest/test_package_apk.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
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 self.old_interface = pylib.android_commands.AndroidCommands(str(device)) 119 self.old_interface = pylib.android_commands.AndroidCommands(str(device))
120 elif isinstance(device, pylib.android_commands.AndroidCommands): 120 elif isinstance(device, pylib.android_commands.AndroidCommands):
121 self.adb = adb_wrapper.AdbWrapper(device.GetDevice()) 121 self.adb = adb_wrapper.AdbWrapper(device.GetDevice())
122 self.old_interface = device 122 self.old_interface = device
123 else: 123 else:
124 raise ValueError('Unsupported device value: %r' % device) 124 raise ValueError('Unsupported device value: %r' % device)
125 self._commands_installed = None 125 self._commands_installed = None
126 self._default_timeout = default_timeout 126 self._default_timeout = default_timeout
127 self._default_retries = default_retries 127 self._default_retries = default_retries
128 self._cache = {} 128 self._cache = {}
129 self._cache['application_paths'] = {}
129 assert hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR) 130 assert hasattr(self, decorators.DEFAULT_TIMEOUT_ATTR)
130 assert hasattr(self, decorators.DEFAULT_RETRIES_ATTR) 131 assert hasattr(self, decorators.DEFAULT_RETRIES_ATTR)
131 132
132 @decorators.WithTimeoutAndRetriesFromInstance() 133 @decorators.WithTimeoutAndRetriesFromInstance()
133 def IsOnline(self, timeout=None, retries=None): 134 def IsOnline(self, timeout=None, retries=None):
134 """Checks whether the device is online. 135 """Checks whether the device is online.
135 136
136 Args: 137 Args:
137 timeout: timeout in seconds 138 timeout: timeout in seconds
138 retries: number of retries 139 retries: number of retries
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 Args: 273 Args:
273 package: Name of the package. 274 package: Name of the package.
274 275
275 Returns: 276 Returns:
276 Path to the apk on the device if it exists, None otherwise. 277 Path to the apk on the device if it exists, None otherwise.
277 """ 278 """
278 # 'pm path' is liable to incorrectly exit with a nonzero number starting 279 # 'pm path' is liable to incorrectly exit with a nonzero number starting
279 # in Lollipop. 280 # in Lollipop.
280 # TODO(jbudorick): Check if this is fixed as new Android versions are 281 # TODO(jbudorick): Check if this is fixed as new Android versions are
281 # released to put an upper bound on this. 282 # released to put an upper bound on this.
283 application_paths = self._cache['application_paths']
jbudorick 2015/01/21 22:54:09 If we stay with the cache, please move this above
284 if package in application_paths:
285 return application_paths[package]
286
282 should_check_return = (self.build_version_sdk < 287 should_check_return = (self.build_version_sdk <
jbudorick 2015/01/21 22:54:09 w.r.t. my tuning suggestion: we already have some
283 constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP) 288 constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP)
284 output = self.RunShellCommand(['pm', 'path', package], single_line=True, 289 output = self.RunShellCommand(['pm', 'path', package], single_line=True,
285 check_return=should_check_return) 290 check_return=should_check_return)
286 if not output: 291 if not output:
287 return None 292 return None
288 if not output.startswith('package:'): 293 if not output.startswith('package:'):
289 raise device_errors.CommandFailedError('pm path returned: %r' % output, 294 raise device_errors.CommandFailedError('pm path returned: %r' % output,
290 str(self)) 295 str(self))
291 return output[len('package:'):] 296 application_paths[package] = output[len('package:'):]
297 return application_paths[package]
292 298
293 @decorators.WithTimeoutAndRetriesFromInstance() 299 @decorators.WithTimeoutAndRetriesFromInstance()
294 def WaitUntilFullyBooted(self, wifi=False, timeout=None, retries=None): 300 def WaitUntilFullyBooted(self, wifi=False, timeout=None, retries=None):
295 """Wait for the device to fully boot. 301 """Wait for the device to fully boot.
296 302
297 This means waiting for the device to boot, the package manager to be 303 This means waiting for the device to boot, the package manager to be
298 available, and the SD card to be ready. It can optionally mean waiting 304 available, and the SD card to be ready. It can optionally mean waiting
299 for wifi to come up, too. 305 for wifi to come up, too.
300 306
301 Args: 307 Args:
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 358
353 Raises: 359 Raises:
354 CommandTimeoutError on timeout. 360 CommandTimeoutError on timeout.
355 DeviceUnreachableError on missing device. 361 DeviceUnreachableError on missing device.
356 """ 362 """
357 def device_offline(): 363 def device_offline():
358 return not self.IsOnline() 364 return not self.IsOnline()
359 365
360 self.adb.Reboot() 366 self.adb.Reboot()
361 self._cache = {} 367 self._cache = {}
368 self._cache['application_paths'] = {}
362 timeout_retry.WaitFor(device_offline, wait_period=1) 369 timeout_retry.WaitFor(device_offline, wait_period=1)
363 if block: 370 if block:
364 self.WaitUntilFullyBooted() 371 self.WaitUntilFullyBooted()
365 372
366 INSTALL_DEFAULT_TIMEOUT = 4 * _DEFAULT_TIMEOUT 373 INSTALL_DEFAULT_TIMEOUT = 4 * _DEFAULT_TIMEOUT
367 INSTALL_DEFAULT_RETRIES = _DEFAULT_RETRIES 374 INSTALL_DEFAULT_RETRIES = _DEFAULT_RETRIES
368 375
369 @decorators.WithTimeoutAndRetriesDefaults( 376 @decorators.WithTimeoutAndRetriesDefaults(
370 INSTALL_DEFAULT_TIMEOUT, 377 INSTALL_DEFAULT_TIMEOUT,
371 INSTALL_DEFAULT_RETRIES) 378 INSTALL_DEFAULT_RETRIES)
(...skipping 17 matching lines...) Expand all
389 device_path = self.GetApplicationPath(package_name) 396 device_path = self.GetApplicationPath(package_name)
390 if device_path is not None: 397 if device_path is not None:
391 should_install = bool(self._GetChangedFilesImpl(apk_path, device_path)) 398 should_install = bool(self._GetChangedFilesImpl(apk_path, device_path))
392 if should_install and not reinstall: 399 if should_install and not reinstall:
393 self.adb.Uninstall(package_name) 400 self.adb.Uninstall(package_name)
394 else: 401 else:
395 should_install = True 402 should_install = True
396 if should_install: 403 if should_install:
397 self.adb.Install(apk_path, reinstall=reinstall) 404 self.adb.Install(apk_path, reinstall=reinstall)
398 405
406 application_paths = self._cache['application_paths']
407 if package_name in application_paths:
408 del application_paths[package_name]
409
399 @decorators.WithTimeoutAndRetriesFromInstance() 410 @decorators.WithTimeoutAndRetriesFromInstance()
400 def RunShellCommand(self, cmd, check_return=False, cwd=None, env=None, 411 def RunShellCommand(self, cmd, check_return=False, cwd=None, env=None,
401 as_root=False, single_line=False, 412 as_root=False, single_line=False,
402 timeout=None, retries=None): 413 timeout=None, retries=None):
403 """Run an ADB shell command. 414 """Run an ADB shell command.
404 415
405 The command to run |cmd| should be a sequence of program arguments or else 416 The command to run |cmd| should be a sequence of program arguments or else
406 a single string. 417 a single string.
407 418
408 When |cmd| is a sequence, it is assumed to contain the name of the command 419 When |cmd| is a sequence, it is assumed to contain the name of the command
409 to run followed by its arguments. In this case, arguments are passed to the 420 to run followed by its arguments. In this case, arguments are passed to the
410 command exactly as given, without any further processing by the shell. This 421 command exactly as given, without any further processing by the shell. This
411 allows to easily pass arguments containing spaces or special characters 422 allows to easily pass arguments containing spaces or special characters
412 without having to worry about getting quoting right. Whenever possible, it 423 without having to worry about getting quoting right. Whenever possible, it
413 is recomended to pass |cmd| as a sequence. 424 is recomended to pass |cmd| as a sequence.
414 425
415 When |cmd| is given as a string, it will be interpreted and run by the 426 When |cmd| is given as a string, it will be interpreted and run by the
416 shell on the device. 427 shell on the device.
417 428
418 This behaviour is consistent with that of command runners in cmd_helper as 429 This behaviour is consistent with that of command runners in cmd_helper as
419 well as Python's own subprocess.Popen. 430 well as Python's own subprocess.Popen.
420 431
421 TODO(perezju) Change the default of |check_return| to True when callers 432 TODO(perezju) Change the default of |check_return| to True when callers
422 have switched to the new behaviour. 433 have switched to the new behaviour.
423 434
435 TODO(jaekyun) Should clear some of non-RO cache items if this command
436 affects them.
437
424 Args: 438 Args:
425 cmd: A string with the full command to run on the device, or a sequence 439 cmd: A string with the full command to run on the device, or a sequence
426 containing the command and its arguments. 440 containing the command and its arguments.
427 check_return: A boolean indicating whether or not the return code should 441 check_return: A boolean indicating whether or not the return code should
428 be checked. 442 be checked.
429 cwd: The device directory in which the command should be run. 443 cwd: The device directory in which the command should be run.
430 env: The environment variables with which the command should be run. 444 env: The environment variables with which the command should be run.
431 as_root: A boolean indicating whether the shell command should be run 445 as_root: A boolean indicating whether the shell command should be run
432 with root privileges. 446 with root privileges.
433 single_line: A boolean indicating if only a single line of output is 447 single_line: A boolean indicating if only a single line of output is
(...skipping 15 matching lines...) Expand all
449 DeviceUnreachableError on missing device. 463 DeviceUnreachableError on missing device.
450 """ 464 """
451 def env_quote(key, value): 465 def env_quote(key, value):
452 if not DeviceUtils._VALID_SHELL_VARIABLE.match(key): 466 if not DeviceUtils._VALID_SHELL_VARIABLE.match(key):
453 raise KeyError('Invalid shell variable name %r' % key) 467 raise KeyError('Invalid shell variable name %r' % key)
454 # using double quotes here to allow interpolation of shell variables 468 # using double quotes here to allow interpolation of shell variables
455 return '%s=%s' % (key, cmd_helper.DoubleQuote(value)) 469 return '%s=%s' % (key, cmd_helper.DoubleQuote(value))
456 470
457 if not isinstance(cmd, basestring): 471 if not isinstance(cmd, basestring):
458 cmd = ' '.join(cmd_helper.SingleQuote(s) for s in cmd) 472 cmd = ' '.join(cmd_helper.SingleQuote(s) for s in cmd)
473
474 if cmd.startswith('pm install') or cmd.startswith('pm uninstall'):
jbudorick 2015/01/21 22:54:09 O_O This looks _extremely_ dangerous / flaky / te
475 self._cache['application_paths'] = {}
476
459 if env: 477 if env:
460 env = ' '.join(env_quote(k, v) for k, v in env.iteritems()) 478 env = ' '.join(env_quote(k, v) for k, v in env.iteritems())
461 cmd = '%s %s' % (env, cmd) 479 cmd = '%s %s' % (env, cmd)
462 if cwd: 480 if cwd:
463 cmd = 'cd %s && %s' % (cmd_helper.SingleQuote(cwd), cmd) 481 cmd = 'cd %s && %s' % (cmd_helper.SingleQuote(cwd), cmd)
464 if as_root and self.NeedsSU(): 482 if as_root and self.NeedsSU():
465 # "su -c sh -c" allows using shell features in |cmd| 483 # "su -c sh -c" allows using shell features in |cmd|
466 cmd = 'su -c sh -c %s' % cmd_helper.SingleQuote(cmd) 484 cmd = 'su -c sh -c %s' % cmd_helper.SingleQuote(cmd)
467 if timeout is None: 485 if timeout is None:
468 timeout = self._default_timeout 486 timeout = self._default_timeout
(...skipping 816 matching lines...) Expand 10 before | Expand all | Expand 10 after
1285 Returns: 1303 Returns:
1286 A Parallelizer operating over |devices|. 1304 A Parallelizer operating over |devices|.
1287 """ 1305 """
1288 if not devices: 1306 if not devices:
1289 devices = adb_wrapper.AdbWrapper.GetDevices() 1307 devices = adb_wrapper.AdbWrapper.GetDevices()
1290 devices = [d if isinstance(d, cls) else cls(d) for d in devices] 1308 devices = [d if isinstance(d, cls) else cls(d) for d in devices]
1291 if async: 1309 if async:
1292 return parallelizer.Parallelizer(devices) 1310 return parallelizer.Parallelizer(devices)
1293 else: 1311 else:
1294 return parallelizer.SyncParallelizer(devices) 1312 return parallelizer.SyncParallelizer(devices)
OLDNEW
« no previous file with comments | « no previous file | build/android/pylib/gtest/test_package_apk.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698