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

Side by Side Diff: build/android/pylib/utils/emulator.py

Issue 13543008: Fix AVD configuration and defaults based on dogfooder input. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Use cmd_helper.RunCmd when output does not matter. Created 7 years, 8 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/install_emulator_deps.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 """Provides an interface to start and stop Android emulator. 7 """Provides an interface to start and stop Android emulator.
8 8
9 Assumes system environment ANDROID_NDK_ROOT has been set. 9 Assumes system environment ANDROID_NDK_ROOT has been set.
10 10
11 Emulator: The class provides the methods to launch/shutdown the emulator with 11 Emulator: The class provides the methods to launch/shutdown the emulator with
12 the android virtual device named 'avd_armeabi' . 12 the android virtual device named 'avd_armeabi' .
13 """ 13 """
14 14
15 import logging 15 import logging
16 import os 16 import os
17 import shutil
17 import signal 18 import signal
18 import subprocess 19 import subprocess
19 import sys 20 import sys
20 import time 21 import time
21 22
22 import time_profile 23 import time_profile
23 # TODO(craigdh): Move these pylib dependencies to pylib/utils/. 24 # TODO(craigdh): Move these pylib dependencies to pylib/utils/.
24 from pylib import android_commands 25 from pylib import android_commands
25 from pylib import cmd_helper 26 from pylib import cmd_helper
26 from pylib import constants 27 from pylib import constants
28 from pylib import pexpect
27 29
28 import errors 30 import errors
29 import run_command 31 import run_command
30 32
31 # Android API level 33 # Android API level
32 API_TARGET = 'android-%s' % constants.ANDROID_SDK_VERSION 34 API_TARGET = 'android-%s' % constants.ANDROID_SDK_VERSION
33 35
34 36
35 class EmulatorLaunchException(Exception): 37 class EmulatorLaunchException(Exception):
36 """Emulator failed to launch.""" 38 """Emulator failed to launch."""
37 pass 39 pass
38 40
39 def _KillAllEmulators(): 41 def _KillAllEmulators():
40 """Kill all running emulators that look like ones we started. 42 """Kill all running emulators that look like ones we started.
41 43
42 There are odd 'sticky' cases where there can be no emulator process 44 There are odd 'sticky' cases where there can be no emulator process
43 running but a device slot is taken. A little bot trouble and and 45 running but a device slot is taken. A little bot trouble and and
44 we're out of room forever. 46 we're out of room forever.
45 """ 47 """
46 emulators = android_commands.GetEmulators() 48 emulators = android_commands.GetEmulators()
47 if not emulators: 49 if not emulators:
48 return 50 return
49 for emu_name in emulators: 51 for emu_name in emulators:
50 cmd_helper.GetCmdOutput(['adb', '-s', emu_name, 'emu', 'kill']) 52 cmd_helper.RunCmd(['adb', '-s', emu_name, 'emu', 'kill'])
51 logging.info('Emulator killing is async; give a few seconds for all to die.') 53 logging.info('Emulator killing is async; give a few seconds for all to die.')
52 for i in range(5): 54 for i in range(5):
53 if not android_commands.GetEmulators(): 55 if not android_commands.GetEmulators():
54 return 56 return
55 time.sleep(1) 57 time.sleep(1)
56 58
57 59
58 def DeleteAllTempAVDs(): 60 def DeleteAllTempAVDs():
59 """Delete all temporary AVDs which are created for tests. 61 """Delete all temporary AVDs which are created for tests.
60 62
61 If the test exits abnormally and some temporary AVDs created when testing may 63 If the test exits abnormally and some temporary AVDs created when testing may
62 be left in the system. Clean these AVDs. 64 be left in the system. Clean these AVDs.
63 """ 65 """
64 avds = android_commands.GetAVDs() 66 avds = android_commands.GetAVDs()
65 if not avds: 67 if not avds:
66 return 68 return
67 for avd_name in avds: 69 for avd_name in avds:
68 if 'run_tests_avd' in avd_name: 70 if 'run_tests_avd' in avd_name:
69 cmd = ['android', '-s', 'delete', 'avd', '--name', avd_name] 71 cmd = ['android', '-s', 'delete', 'avd', '--name', avd_name]
70 cmd_helper.GetCmdOutput(cmd) 72 cmd_helper.RunCmd(cmd)
71 logging.info('Delete AVD %s' % avd_name) 73 logging.info('Delete AVD %s' % avd_name)
72 74
73 75
74 class PortPool(object): 76 class PortPool(object):
75 """Pool for emulator port starting position that changes over time.""" 77 """Pool for emulator port starting position that changes over time."""
76 _port_min = 5554 78 _port_min = 5554
77 _port_max = 5585 79 _port_max = 5585
78 _port_current_index = 0 80 _port_current_index = 0
79 81
80 @classmethod 82 @classmethod
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 # the time to launch the emulator and a wait-for-device command. 155 # the time to launch the emulator and a wait-for-device command.
154 _LAUNCH_TIMEOUT = 120 156 _LAUNCH_TIMEOUT = 120
155 157
156 # Timeout interval of wait-for-device command before bouncing to a a 158 # Timeout interval of wait-for-device command before bouncing to a a
157 # process life check. 159 # process life check.
158 _WAITFORDEVICE_TIMEOUT = 5 160 _WAITFORDEVICE_TIMEOUT = 5
159 161
160 # Time to wait for a "wait for boot complete" (property set on device). 162 # Time to wait for a "wait for boot complete" (property set on device).
161 _WAITFORBOOT_TIMEOUT = 300 163 _WAITFORBOOT_TIMEOUT = 300
162 164
163 def __init__(self, avd_name, abi='x86'): 165 def __init__(self, avd_name, abi):
164 """Init an Emulator. 166 """Init an Emulator.
165 167
166 Args: 168 Args:
167 avd_name: name of the AVD to create 169 avd_name: name of the AVD to create
168 abi: target platform for emulator being created 170 abi: target platform for emulator being created
169 """ 171 """
170 android_sdk_root = os.path.join(constants.EMULATOR_SDK_ROOT, 172 android_sdk_root = os.path.join(constants.EMULATOR_SDK_ROOT,
171 'android_tools', 'sdk') 173 'android_tools', 'sdk')
172 self.emulator = os.path.join(android_sdk_root, 'tools', 'emulator') 174 self.emulator = os.path.join(android_sdk_root, 'tools', 'emulator')
173 self.android = os.path.join(android_sdk_root, 'tools', 'android') 175 self.android = os.path.join(android_sdk_root, 'tools', 'android')
174 self.popen = None 176 self.popen = None
175 self.device = None 177 self.device = None
176 self.abi = abi 178 self.abi = abi
177 self.avd_name = avd_name 179 self.avd_name = avd_name
178 self._CreateAVD() 180 self._CreateAVD()
179 181
180 def _DeviceName(self): 182 def _DeviceName(self):
181 """Return our device name.""" 183 """Return our device name."""
182 port = _GetAvailablePort() 184 port = _GetAvailablePort()
183 return ('emulator-%d' % port, port) 185 return ('emulator-%d' % port, port)
184 186
185 def _CreateAVD(self): 187 def _CreateAVD(self):
186 """Creates an AVD with the given name. 188 """Creates an AVD with the given name.
187 189
188 Return avd_name. 190 Return avd_name.
189 """ 191 """
192
193 if self.abi == 'arm':
194 abi_option = 'armeabi-v7a'
195 else:
196 abi_option = 'x86'
197
190 avd_command = [ 198 avd_command = [
191 self.android, 199 self.android,
192 '--silent', 200 '--silent',
193 'create', 'avd', 201 'create', 'avd',
194 '--name', self.avd_name, 202 '--name', self.avd_name,
195 '--abi', self.abi, 203 '--abi', abi_option,
196 '--target', API_TARGET, 204 '--target', API_TARGET,
197 '-c', '128M',
198 '--force', 205 '--force',
199 ] 206 ]
200 avd_process = subprocess.Popen(args=avd_command, 207 avd_cmd_str = ' '.join(avd_command)
201 stdin=subprocess.PIPE, 208 logging.info('Create AVD command: %s', avd_cmd_str)
202 stdout=subprocess.PIPE, 209 avd_process = pexpect.spawn(avd_cmd_str)
203 stderr=subprocess.STDOUT) 210
204 avd_process.stdin.write('no\n') 211 # Instead of creating a custom profile, we overwrite config files.
205 avd_process.wait() 212 avd_process.expect('Do you wish to create a custom hardware profile')
206 logging.info('Create AVD command: %s', ' '.join(avd_command)) 213 avd_process.sendline('no\n')
214 avd_process.expect('Created AVD \'%s\'' % self.avd_name)
215
216 # Setup test device as default Galaxy Nexus AVD
217 avd_config_dir = os.path.join(constants.CHROME_DIR, 'build', 'android',
218 'avd_configs')
219 avd_config_ini = os.path.join(avd_config_dir,
220 'AVD_for_Galaxy_Nexus_by_Google_%s.avd' %
221 self.abi, 'config.ini')
222
223 # Replace current configuration with default Galaxy Nexus config.
224 avds_dir = os.path.join(os.path.expanduser('~'), '.android', 'avd')
225 ini_file = os.path.join(avds_dir, '%s.ini' % self.avd_name)
226 new_config_ini = os.path.join(avds_dir, '%s.avd' % self.avd_name,
227 'config.ini')
228
229 # Remove config files with defaults to replace with Google's GN settings.
230 os.unlink(ini_file)
231 os.unlink(new_config_ini)
232
233 # Create new configuration files with Galaxy Nexus by Google settings.
234 with open(ini_file, 'w') as new_ini:
235 new_ini.write('avd.ini.encoding=ISO-8859-1\n')
236 new_ini.write('target=%s\n' % API_TARGET)
237 new_ini.write('path=%s/%s.avd\n' % (avds_dir, self.avd_name))
238 new_ini.write('path.rel=avd/%s.avd\n' % self.avd_name)
239
240 shutil.copy(avd_config_ini, new_config_ini)
207 return self.avd_name 241 return self.avd_name
208 242
243
209 def _DeleteAVD(self): 244 def _DeleteAVD(self):
210 """Delete the AVD of this emulator.""" 245 """Delete the AVD of this emulator."""
211 avd_command = [ 246 avd_command = [
212 self.android, 247 self.android,
213 '--silent', 248 '--silent',
214 'delete', 249 'delete',
215 'avd', 250 'avd',
216 '--name', self.avd_name, 251 '--name', self.avd_name,
217 ] 252 ]
218 avd_process = subprocess.Popen(args=avd_command,
219 stdout=subprocess.PIPE,
220 stderr=subprocess.STDOUT)
221 logging.info('Delete AVD command: %s', ' '.join(avd_command)) 253 logging.info('Delete AVD command: %s', ' '.join(avd_command))
222 avd_process.wait() 254 cmd_helper.RunCmd(avd_command)
255
223 256
224 def Launch(self, kill_all_emulators): 257 def Launch(self, kill_all_emulators):
225 """Launches the emulator asynchronously. Call ConfirmLaunch() to ensure the 258 """Launches the emulator asynchronously. Call ConfirmLaunch() to ensure the
226 emulator is ready for use. 259 emulator is ready for use.
227 260
228 If fails, an exception will be raised. 261 If fails, an exception will be raised.
229 """ 262 """
230 if kill_all_emulators: 263 if kill_all_emulators:
231 _KillAllEmulators() # just to be sure 264 _KillAllEmulators() # just to be sure
232 self._AggressiveImageCleanup() 265 self._AggressiveImageCleanup()
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 logging.critical('emulator _ShutdownOnSignal') 359 logging.critical('emulator _ShutdownOnSignal')
327 for sig in self._SIGNALS: 360 for sig in self._SIGNALS:
328 signal.signal(sig, signal.SIG_DFL) 361 signal.signal(sig, signal.SIG_DFL)
329 self.Shutdown() 362 self.Shutdown()
330 raise KeyboardInterrupt # print a stack 363 raise KeyboardInterrupt # print a stack
331 364
332 def _InstallKillHandler(self): 365 def _InstallKillHandler(self):
333 """Install a handler to kill the emulator when we exit unexpectedly.""" 366 """Install a handler to kill the emulator when we exit unexpectedly."""
334 for sig in self._SIGNALS: 367 for sig in self._SIGNALS:
335 signal.signal(sig, self._ShutdownOnSignal) 368 signal.signal(sig, self._ShutdownOnSignal)
OLDNEW
« no previous file with comments | « build/android/install_emulator_deps.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698