1 #!/usr/bin/env python 2 # 3 # Copyright (c) 2013 The Chromium Authors. All rights reserved. 4 # Use of this source code is governed by a BSD-style license that can be 5 # found in the LICENSE file. 6 7 """Provisions Android devices with settings required for bots. 8 9 Usage: 10 ./provision_devices.py [-d <device serial number>] 11 """ 12 13 import optparse 14 import os 15 import re 16 import subprocess 17 import sys 18 import time 19 20 from pylib import android_commands 21 from pylib import constants 22 23 def KillHostHeartbeat(): 24 ps = subprocess.Popen(['ps', 'aux'], stdout = subprocess.PIPE) 25 stdout, _ = ps.communicate() 26 matches = re.findall('\\n.*host_heartbeat.*', stdout) 27 for match in matches: 28 print 'An instance of host heart beart running... will kill' 29 pid = re.findall('(\d+)', match)[1] 30 subprocess.call(['kill', str(pid)]) 31 32 33 def LaunchHostHeartbeat(): 34 # Kill if existing host_heartbeat 35 KillHostHeartbeat() 36 # Launch a new host_heartbeat 37 print 'Spawning host heartbeat...' 38 subprocess.Popen([os.path.join(constants.DIR_SOURCE_ROOT, 39 'build/android/host_heartbeat.py')]) 40 41 42 def PushAndLaunchAdbReboot(devices, target): 43 """Pushes and launches the adb_reboot binary on the device. 44 45 Arguments: 46 devices: The list of serial numbers of the device to which the 47 adb_reboot binary should be pushed. 48 target : The build target (example, Debug or Release) which helps in 49 locating the adb_reboot binary. 50 """ 51 for device in devices: 52 print 'Will push and launch adb_reboot on %s' % device 53 android_cmd = android_commands.AndroidCommands(device) 54 # Kill if adb_reboot is already running. 55 android_cmd.KillAllBlocking('adb_reboot', 2) 56 # Push adb_reboot 57 print ' Pushing adb_reboot ...' 58 adb_reboot = os.path.join(constants.DIR_SOURCE_ROOT, 59 'out/%s/adb_reboot' % target) 60 android_cmd.PushIfNeeded(adb_reboot, '/data/local/tmp/') 61 # Launch adb_reboot 62 print ' Launching adb_reboot ...' 63 p = subprocess.Popen(['adb', '-s', device, 'shell'], stdin=subprocess.PIPE) 64 p.communicate('/data/local/tmp/adb_reboot; exit\n') 65 LaunchHostHeartbeat() 66 67 68 def ProvisionDevices(options): 69 if options.device is not None: 70 devices = [options.device] 71 else: 72 devices = android_commands.GetAttachedDevices() 73 for device in devices: 74 android_cmd = android_commands.AndroidCommands(device) 75 android_cmd.RunShellCommandWithSU('date -u %f' % time.time()) 76 if options.auto_reconnect: 77 PushAndLaunchAdbReboot(devices, options.target) 78 79 80 def main(argv): 81 parser = optparse.OptionParser() 82 parser.add_option('-d', '--device', 83 help='The serial number of the device to be provisioned') 84 parser.add_option('-t', '--target', default='Debug', help='The build target') 85 parser.add_option( 86 '-r', '--auto-reconnect', action='store_true', 87 help='Push binary which will reboot the device on adb disconnections.') 88 options, args = parser.parse_args(argv[1:]) 89 constants.SetBuildType(options.target) 90 91 if args: 92 print >> sys.stderr, 'Unused args %s' % args 93 return 1 94 95 ProvisionDevices(options) 96 97 98 if __name__ == '__main__': 99 sys.exit(main(sys.argv)) 100