1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
#!/usr/bin/env python
#
# Copyright (c) 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Provisions Android devices with settings required for bots.
Usage:
./provision_devices.py [-d <device serial number>]
"""
import logging
import optparse
import os
import re
import subprocess
import sys
import time
from pylib import android_commands
from pylib import constants
from pylib import device_settings
from pylib.cmd_helper import GetCmdOutput
from pylib.device import device_utils
def KillHostHeartbeat():
ps = subprocess.Popen(['ps', 'aux'], stdout = subprocess.PIPE)
stdout, _ = ps.communicate()
matches = re.findall('\\n.*host_heartbeat.*', stdout)
for match in matches:
print 'An instance of host heart beart running... will kill'
pid = re.findall('(\d+)', match)[1]
subprocess.call(['kill', str(pid)])
def LaunchHostHeartbeat():
# Kill if existing host_heartbeat
KillHostHeartbeat()
# Launch a new host_heartbeat
print 'Spawning host heartbeat...'
subprocess.Popen([os.path.join(constants.DIR_SOURCE_ROOT,
'build/android/host_heartbeat.py')])
def PushAndLaunchAdbReboot(devices, target):
"""Pushes and launches the adb_reboot binary on the device.
Arguments:
devices: The list of serial numbers of the device to which the
adb_reboot binary should be pushed.
target : The build target (example, Debug or Release) which helps in
locating the adb_reboot binary.
"""
for device_serial in devices:
print 'Will push and launch adb_reboot on %s' % device_serial
device = device_utils.DeviceUtils(device_serial)
# Kill if adb_reboot is already running.
device.old_interface.KillAllBlocking('adb_reboot', 2)
# Push adb_reboot
print ' Pushing adb_reboot ...'
adb_reboot = os.path.join(constants.DIR_SOURCE_ROOT,
'out/%s/adb_reboot' % target)
device.old_interface.PushIfNeeded(adb_reboot, '/data/local/tmp/')
# Launch adb_reboot
print ' Launching adb_reboot ...'
# TODO(jbudorick) Try to convert this to RunShellCommand.
p = subprocess.Popen(['adb', '-s', device_serial, 'shell'],
stdin=subprocess.PIPE)
p.communicate('/data/local/tmp/adb_reboot; exit\n')
LaunchHostHeartbeat()
def _ConfigureLocalProperties(device):
"""Set standard readonly testing device properties prior to reboot."""
local_props = [
'ro.monkey=1',
'ro.test_harness=1',
'ro.audio.silent=1',
'ro.setupwizard.mode=DISABLED',
]
device.old_interface.SetProtectedFileContents(
constants.DEVICE_LOCAL_PROPERTIES_PATH,
'\n'.join(local_props))
# Android will not respect the local props file if it is world writable.
device.old_interface.RunShellCommandWithSU(
'chmod 644 %s' % constants.DEVICE_LOCAL_PROPERTIES_PATH)
# LOCAL_PROPERTIES_PATH = '/data/local.prop'
def WipeDeviceData(device):
"""Wipes data from device, keeping only the adb_keys for authorization.
After wiping data on a device that has been authorized, adb can still
communicate with the device, but after reboot the device will need to be
re-authorized because the adb keys file is stored in /data/misc/adb/.
Thus, adb_keys file is rewritten so the device does not need to be
re-authorized.
Arguments:
device: the device to wipe
"""
device_authorized = device.old_interface.FileExistsOnDevice(
constants.ADB_KEYS_FILE)
if device_authorized:
adb_keys = device.old_interface.RunShellCommandWithSU(
'cat %s' % constants.ADB_KEYS_FILE)
device.old_interface.RunShellCommandWithSU('wipe data')
if device_authorized:
path_list = constants.ADB_KEYS_FILE.split('/')
dir_path = '/'.join(path_list[:len(path_list)-1])
device.old_interface.RunShellCommandWithSU('mkdir -p %s' % dir_path)
device.old_interface.RunShellCommand('echo %s > %s' %
(adb_keys[0], constants.ADB_KEYS_FILE))
for adb_key in adb_keys[1:]:
device.old_interface.RunShellCommand(
'echo %s >> %s' % (adb_key, constants.ADB_KEYS_FILE))
def ProvisionDevices(options):
if options.device is not None:
devices = [options.device]
else:
devices = android_commands.GetAttachedDevices()
for device_serial in devices:
device = device_utils.DeviceUtils(device_serial)
device.old_interface.EnableAdbRoot()
install_output = GetCmdOutput(
['%s/build/android/adb_install_apk.py' % constants.DIR_SOURCE_ROOT,
'--apk',
'%s/build/android/CheckInstallApk-debug.apk' % constants.DIR_SOURCE_ROOT
])
failure_string = 'Failure [INSTALL_FAILED_INSUFFICIENT_STORAGE]'
if failure_string in install_output:
WipeDeviceData(device)
_ConfigureLocalProperties(device)
device_settings.ConfigureContentSettingsDict(
device, device_settings.DETERMINISTIC_DEVICE_SETTINGS)
# TODO(tonyg): We eventually want network on. However, currently radios
# can cause perfbots to drain faster than they charge.
if 'perf' in os.environ.get('BUILDBOT_BUILDERNAME', '').lower():
device_settings.ConfigureContentSettingsDict(
device, device_settings.NETWORK_DISABLED_SETTINGS)
device.old_interface.RunShellCommandWithSU('date -u %f' % time.time())
(_, props) = device.old_interface.GetShellCommandStatusAndOutput('getprop')
for prop in props:
print prop
if options.auto_reconnect:
PushAndLaunchAdbReboot(devices, options.target)
def main(argv):
logging.basicConfig(level=logging.INFO)
parser = optparse.OptionParser()
parser.add_option('-w', '--wipe', action='store_true',
help='Wipe device data from all attached devices.')
parser.add_option('-d', '--device',
help='The serial number of the device to be provisioned')
parser.add_option('-t', '--target', default='Debug', help='The build target')
parser.add_option(
'-r', '--auto-reconnect', action='store_true',
help='Push binary which will reboot the device on adb disconnections.')
options, args = parser.parse_args(argv[1:])
constants.SetBuildType(options.target)
if args:
print >> sys.stderr, 'Unused args %s' % args
return 1
if options.wipe:
devices = android_commands.GetAttachedDevices()
for device_serial in devices:
device = device_utils.DeviceUtils(device_serial)
WipeDeviceData(device)
device_utils.RebootDevices()
else:
ProvisionDevices(options)
if __name__ == '__main__':
sys.exit(main(sys.argv))
|