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

Side by Side Diff: build/android/pylib/android_commands.py

Issue 10824227: Organize adb install cmds and reboot on failure (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 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 | Annotate | Revision Log
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 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 an interface to communicate with the device via the adb command. 5 """Provides an interface to communicate with the device via the adb command.
6 6
7 Assumes adb binary is currently on system path. 7 Assumes adb binary is currently on system path.
8 """ 8 """
9 9
10 import collections 10 import collections
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 """Reboots the device and waits for the package manager to return. 279 """Reboots the device and waits for the package manager to return.
280 280
281 Args: 281 Args:
282 full_reboot: Whether to fully reboot the device or just restart the shell. 282 full_reboot: Whether to fully reboot the device or just restart the shell.
283 """ 283 """
284 # TODO(torne): hive can't reboot the device either way without breaking the 284 # TODO(torne): hive can't reboot the device either way without breaking the
285 # connection; work out if we can handle this better 285 # connection; work out if we can handle this better
286 if os.environ.get('USING_HIVE'): 286 if os.environ.get('USING_HIVE'):
287 logging.warning('Ignoring reboot request as we are on hive') 287 logging.warning('Ignoring reboot request as we are on hive')
288 return 288 return
289 if full_reboot: 289 if full_reboot or not self.IsRootEnabled():
290 self._adb.SendCommand('reboot') 290 self._adb.SendCommand('reboot')
291 timeout = 300
291 else: 292 else:
292 self.RestartShell() 293 self.RestartShell()
294 timeout = 120
293 self.WaitForDevicePm() 295 self.WaitForDevicePm()
294 self.StartMonitoringLogcat(timeout=120) 296 self.StartMonitoringLogcat(timeout=timeout)
295 self.WaitForLogMatch(BOOT_COMPLETE_RE, None) 297 self.WaitForLogMatch(BOOT_COMPLETE_RE, None)
296 298
297 def Uninstall(self, package): 299 def Uninstall(self, package):
298 """Uninstalls the specified package from the device. 300 """Uninstalls the specified package from the device.
299 301
300 Args: 302 Args:
301 package: Name of the package to remove. 303 package: Name of the package to remove.
302 304
303 Returns: 305 Returns:
304 A status string returned by adb uninstall 306 A status string returned by adb uninstall
305 """ 307 """
306 uninstall_command = 'uninstall %s' % package 308 uninstall_command = 'uninstall %s' % package
307 309
308 logging.info('>>> $' + uninstall_command) 310 return self._adb.SendCommand(uninstall_command, timeout_time=60,
309 return self._adb.SendCommand(uninstall_command, timeout_time=60) 311 cmd_logger=logging)
310 312
311 def Install(self, package_file_path): 313 def Install(self, package_file_path, reinstall=False, retry_count=3):
312 """Installs the specified package to the device. 314 """Installs the specified package to the device.
313 315
314 Args: 316 Args:
315 package_file_path: Path to .apk file to install. 317 package_file_path: Path to .apk file to install.
318 reinstall: Whether to reinstall over existing package
bulach 2012/08/09 12:36:52 nit: remove retry_count from 313, since it's undoc
316 319
317 Returns: 320 Returns:
318 A status string returned by adb install 321 A status string returned by adb install
319 """ 322 """
320 assert os.path.isfile(package_file_path) 323 assert os.path.isfile(package_file_path)
321 324
322 install_command = 'install %s' % package_file_path 325 if reinstall:
326 install_cmd = 'install -r %s'
327 else:
328 install_cmd = 'install %s'
323 329
324 logging.info('>>> $' + install_command) 330 return self._adb.SendCommand(install_cmd % package_file_path,
325 return self._adb.SendCommand(install_command, timeout_time=2*60) 331 timeout_time=2*60, cmd_logger=logging,
bulach 2012/08/09 12:36:52 nit: I think it needs space around *, timeout_time
Isaac (away) 2012/08/10 04:44:35 It's like this a couple other places in this file.
332 retry_count=3)
333
334 def ManagedInstall(self, apk_path, keep_data, package_name=None,
335 reboots_on_failure=2):
336 """Installs the specified package to the device. Reboots the device on
337 package manager timeouts.
338
339 Args:
340 apk_path: Path to .apk file to install.
341 keep_data: Whether to keep data if package already exists
342 package_name: Package name (only needed if keep_data=False
bulach 2012/08/09 12:36:52 nit: )
343 reboots_on_failure: number of time to reboot if package manager is frozen.
344
345 Returns:
346 A status string returned by adb install
347 """
348 reboots_left = reboots_on_failure
349 while True:
350 try:
351 if not keep_data:
352 self.Uninstall(package_name)
353 install_status = self.Install(apk_path, keep_data, retry_count=0)
354 if 'Success' in install_status:
355 return install_status
356 except errors.WaitForResponseTimedOutError:
357 if reboots_left < 0:
bulach 2012/08/09 12:36:52 nit: seems that this should be <= 0, that is, pass
358 raise
359 # Force a hard reboot on last attempt
360 self.Reboot(full_reboot=(reboots_left==0))
bulach 2012/08/09 12:36:52 nit: space around ==
361 reboots_left -= 1
326 362
327 def MakeSystemFolderWritable(self): 363 def MakeSystemFolderWritable(self):
328 """Remounts the /system folder rw. """ 364 """Remounts the /system folder rw. """
329 out = self._adb.SendCommand('remount') 365 out = self._adb.SendCommand('remount')
330 if out.strip() != 'remount succeeded': 366 if out.strip() != 'remount succeeded':
331 raise errors.MsgException('Remount failed: %s' % out) 367 raise errors.MsgException('Remount failed: %s' % out)
332 368
333 def RestartAdbServer(self): 369 def RestartAdbServer(self):
334 """Restart the adb server.""" 370 """Restart the adb server."""
335 self.KillAdbServer() 371 self.KillAdbServer()
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 attempts += 1 414 attempts += 1
379 if not boot_completed: 415 if not boot_completed:
380 raise errors.WaitForResponseTimedOutError( 416 raise errors.WaitForResponseTimedOutError(
381 'sys.boot_completed flag was not set after %s seconds' % wait_time) 417 'sys.boot_completed flag was not set after %s seconds' % wait_time)
382 418
383 def WaitForSdCardReady(self, timeout_time): 419 def WaitForSdCardReady(self, timeout_time):
384 """Wait for the SD card ready before pushing data into it.""" 420 """Wait for the SD card ready before pushing data into it."""
385 logging.info('Waiting for SD card ready...') 421 logging.info('Waiting for SD card ready...')
386 sdcard_ready = False 422 sdcard_ready = False
387 attempts = 0 423 attempts = 0
388 wait_period = 5
389 while not sdcard_ready and attempts * wait_period < timeout_time: 424 while not sdcard_ready and attempts * wait_period < timeout_time:
390 output = self.RunShellCommand('ls /sdcard/') 425 output = self.RunShellCommand('ls /sdcard/')
391 if len(output) > 0: 426 if len(output) > 0:
392 sdcard_ready = True 427 sdcard_ready = True
393 else: 428 else:
394 time.sleep(wait_period) 429 time.sleep(wait_period)
395 attempts += 1 430 attempts += 1
396 if not sdcard_ready: 431 if not sdcard_ready:
397 raise errors.WaitForResponseTimedOutError( 432 raise errors.WaitForResponseTimedOutError(
398 'SD card not ready after %s seconds' % timeout_time) 433 'SD card not ready after %s seconds' % timeout_time)
399 434
400 # It is tempting to turn this function into a generator, however this is not 435 # It is tempting to turn this function into a generator, however this is not
401 # possible without using a private (local) adb_shell instance (to ensure no 436 # possible without using a private (local) adb_shell instance (to ensure no
402 # other command interleaves usage of it), which would defeat the main aim of 437 # other command interleaves usage of it), which would defeat the main aim of
403 # being able to reuse the adb shell instance across commands. 438 # being able to reuse the adb shell instance across commands.
404 def RunShellCommand(self, command, timeout_time=20, log_result=True): 439 def RunShellCommand(self, command, timeout_time=20, log_result=True):
405 """Send a command to the adb shell and return the result. 440 """Send a command to the adb shell and return the result.
406 441
407 Args: 442 Args:
408 command: String containing the shell command to send. Must not include 443 command: String containing the shell command to send. Must not include
409 the single quotes as we use them to escape the whole command. 444 the single quotes as we use them to escape the whole command.
410 timeout_time: Number of seconds to wait for command to respond before 445 timeout_time: Number of seconds to wait for command to respond before
411 retrying, used by AdbInterface.SendShellCommand. 446 retrying, used by AdbInterface.SendShellCommand.
412 log_result: Boolean to indicate whether we should log the result of the 447 log_result: Boolean to indicate whether we should log the result of the
413 shell command. 448 shell command.
414 449
415 Returns: 450 Returns:
416 list containing the lines of output received from running the command 451 list containing the lines of output received from running the command
417 """ 452 """
418 logging.info('>>> $' + command)
419 if "'" in command: logging.warning(command + " contains ' quotes") 453 if "'" in command: logging.warning(command + " contains ' quotes")
420 result = self._adb.SendShellCommand("'%s'" % command, 454 result = self._adb.SendShellCommand("'%s'" % command, timeout_time,
421 timeout_time).splitlines() 455 cmd_logger=logging).splitlines()
422 if log_result: 456 if log_result:
423 logging.info('\n>>> '.join(result)) 457 logging.info('\n>>> '.join(result))
424 return result 458 return result
425 459
426 def KillAll(self, process): 460 def KillAll(self, process):
427 """Android version of killall, connected via adb. 461 """Android version of killall, connected via adb.
428 462
429 Args: 463 Args:
430 process: name of the process to kill off 464 process: name of the process to kill off
431 465
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 elif isinstance(value, int): 507 elif isinstance(value, int):
474 cmd += ' --ei' 508 cmd += ' --ei'
475 else: 509 else:
476 raise NotImplementedError( 510 raise NotImplementedError(
477 'Need to teach StartActivity how to pass %s extras' % type(value)) 511 'Need to teach StartActivity how to pass %s extras' % type(value))
478 cmd += ' %s %s' % (key, value) 512 cmd += ' %s %s' % (key, value)
479 if trace_file_name: 513 if trace_file_name:
480 cmd += ' --start-profiler ' + trace_file_name 514 cmd += ' --start-profiler ' + trace_file_name
481 self.RunShellCommand(cmd) 515 self.RunShellCommand(cmd)
482 516
483
484 def CloseApplication(self, package): 517 def CloseApplication(self, package):
485 """Attempt to close down the application, using increasing violence. 518 """Attempt to close down the application, using increasing violence.
486 519
487 Args: 520 Args:
488 package: Name of the process to kill off, e.g. 521 package: Name of the process to kill off, e.g.
489 com.google.android.apps.chrome 522 com.google.android.apps.chrome
490 """ 523 """
491 self.RunShellCommand('am force-stop ' + package) 524 self.RunShellCommand('am force-stop ' + package)
492 525
493 def ClearApplicationState(self, package): 526 def ClearApplicationState(self, package):
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 return 566 return
534 567
535 # They don't match, so remove everything first and then create it. 568 # They don't match, so remove everything first and then create it.
536 if os.path.isdir(local_path): 569 if os.path.isdir(local_path):
537 self.RunShellCommand('rm -r %s' % device_path, timeout_time=2*60) 570 self.RunShellCommand('rm -r %s' % device_path, timeout_time=2*60)
538 self.RunShellCommand('mkdir -p %s' % device_path) 571 self.RunShellCommand('mkdir -p %s' % device_path)
539 572
540 # NOTE: We can't use adb_interface.Push() because it hardcodes a timeout of 573 # NOTE: We can't use adb_interface.Push() because it hardcodes a timeout of
541 # 60 seconds which isn't sufficient for a lot of users of this method. 574 # 60 seconds which isn't sufficient for a lot of users of this method.
542 push_command = 'push %s %s' % (local_path, device_path) 575 push_command = 'push %s %s' % (local_path, device_path)
543 logging.info('>>> $' + push_command) 576 output = self._adb.SendCommand(push_command, timeout_time=30*60,
544 output = self._adb.SendCommand(push_command, timeout_time=30*60) 577 cmd_logger=logging)
545 assert output 578 assert output
546 # Success looks like this: "3035 KB/s (12512056 bytes in 4.025s)" 579 # Success looks like this: "3035 KB/s (12512056 bytes in 4.025s)"
547 # Errors look like this: "failed to copy ... " 580 # Errors look like this: "failed to copy ... "
548 if not re.search('^[0-9]', output.splitlines()[-1]): 581 if not re.search('^[0-9]', output.splitlines()[-1]):
549 logging.critical('PUSH FAILED: ' + output) 582 logging.critical('PUSH FAILED: ' + output)
550 583
551 def GetFileContents(self, filename, log_result=True): 584 def GetFileContents(self, filename, log_result=True):
552 """Gets contents from the file specified by |filename|.""" 585 """Gets contents from the file specified by |filename|."""
553 return self.RunShellCommand('if [ -f "' + filename + '" ]; then cat "' + 586 return self.RunShellCommand('if [ -f "' + filename + '" ]; then cat "' +
554 filename + '"; fi', log_result=log_result) 587 filename + '"; fi', log_result=log_result)
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
945 if len(process_results) <= 8: 978 if len(process_results) <= 8:
946 continue 979 continue
947 # Column 0 is the executable name 980 # Column 0 is the executable name
948 # Column 1 is the pid 981 # Column 1 is the pid
949 # Column 8 is the Inode in use 982 # Column 8 is the Inode in use
950 if process_results[8] == socket_name: 983 if process_results[8] == socket_name:
951 pids.append( (int(process_results[1]), process_results[0]) ) 984 pids.append( (int(process_results[1]), process_results[0]) )
952 break 985 break
953 logging.info('PidsUsingDevicePort: %s', pids) 986 logging.info('PidsUsingDevicePort: %s', pids)
954 return pids 987 return pids
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698