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

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: Changed use of subprocess for avd create to pexpect. 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
frankf 2013/04/09 22:32:14 No longer used. Please run gpylint.
navabi 2013/04/09 22:40:05 That's not true. It is still used in this file (ju
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."""
(...skipping 116 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.GetCmdOutput(avd_command)
frankf 2013/04/09 22:37:29 Also just do cmd_helper.RunCmd if you don't need t
navabi 2013/04/09 22:44:33 Done. (along with two other instances).
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 17 matching lines...) Expand all
250 ] 283 ]
251 if self.abi == 'x86': 284 if self.abi == 'x86':
252 emulator_command.extend([ 285 emulator_command.extend([
253 # For x86 emulator --enable-kvm will fail early, avoiding accidental 286 # For x86 emulator --enable-kvm will fail early, avoiding accidental
254 # runs in a slow mode (i.e. without hardware virtualization support). 287 # runs in a slow mode (i.e. without hardware virtualization support).
255 '--enable-kvm', 288 '--enable-kvm',
256 ]) 289 ])
257 290
258 logging.info('Emulator launch command: %s', ' '.join(emulator_command)) 291 logging.info('Emulator launch command: %s', ' '.join(emulator_command))
259 self.popen = subprocess.Popen(args=emulator_command, 292 self.popen = subprocess.Popen(args=emulator_command,
260 stderr=subprocess.STDOUT) 293 stderr=subprocess.STDOUT)
navabi 2013/04/09 22:40:05 This one is not as easy to remove because we poll
261 self._InstallKillHandler() 294 self._InstallKillHandler()
262 295
263 def _AggressiveImageCleanup(self): 296 def _AggressiveImageCleanup(self):
264 """Aggressive cleanup of emulator images. 297 """Aggressive cleanup of emulator images.
265 298
266 Experimentally it looks like our current emulator use on the bot 299 Experimentally it looks like our current emulator use on the bot
267 leaves image files around in /tmp/android-$USER. If a "random" 300 leaves image files around in /tmp/android-$USER. If a "random"
268 name gets reused, we choke with a 'File exists' error. 301 name gets reused, we choke with a 'File exists' error.
269 TODO(jrg): is there a less hacky way to accomplish the same goal? 302 TODO(jrg): is there a less hacky way to accomplish the same goal?
270 """ 303 """
(...skipping 23 matching lines...) Expand all
294 run_command.RunCommand(adb_cmd, 327 run_command.RunCommand(adb_cmd,
295 timeout_time=self._WAITFORDEVICE_TIMEOUT, 328 timeout_time=self._WAITFORDEVICE_TIMEOUT,
296 retry_count=1) 329 retry_count=1)
297 number_of_waits -= 1 330 number_of_waits -= 1
298 if not number_of_waits: 331 if not number_of_waits:
299 break 332 break
300 except errors.WaitForResponseTimedOutError as e: 333 except errors.WaitForResponseTimedOutError as e:
301 seconds_waited += self._WAITFORDEVICE_TIMEOUT 334 seconds_waited += self._WAITFORDEVICE_TIMEOUT
302 adb_cmd = "adb -s %s %s" % (self.device, 'kill-server') 335 adb_cmd = "adb -s %s %s" % (self.device, 'kill-server')
303 run_command.RunCommand(adb_cmd) 336 run_command.RunCommand(adb_cmd)
304 self.popen.poll() 337 self.popen.poll()
navabi 2013/04/09 22:40:05 here will poll the subprocess.
305 if self.popen.returncode != None: 338 if self.popen.returncode != None:
306 raise EmulatorLaunchException('EMULATOR DIED') 339 raise EmulatorLaunchException('EMULATOR DIED')
307 if seconds_waited >= self._LAUNCH_TIMEOUT: 340 if seconds_waited >= self._LAUNCH_TIMEOUT:
308 raise EmulatorLaunchException('TIMEOUT with wait-for-device') 341 raise EmulatorLaunchException('TIMEOUT with wait-for-device')
309 logging.info('Seconds waited on wait-for-device: %d', seconds_waited) 342 logging.info('Seconds waited on wait-for-device: %d', seconds_waited)
310 if wait_for_boot: 343 if wait_for_boot:
311 # Now that we checked for obvious problems, wait for a boot complete. 344 # Now that we checked for obvious problems, wait for a boot complete.
312 # Waiting for the package manager is sometimes problematic. 345 # Waiting for the package manager is sometimes problematic.
313 a = android_commands.AndroidCommands(self.device) 346 a = android_commands.AndroidCommands(self.device)
314 a.WaitForSystemBootCompleted(self._WAITFORBOOT_TIMEOUT) 347 a.WaitForSystemBootCompleted(self._WAITFORBOOT_TIMEOUT)
315 348
316 def Shutdown(self): 349 def Shutdown(self):
317 """Shuts down the process started by launch.""" 350 """Shuts down the process started by launch."""
318 self._DeleteAVD() 351 self._DeleteAVD()
319 if self.popen: 352 if self.popen:
320 self.popen.poll() 353 self.popen.poll()
navabi 2013/04/09 22:40:05 here too.
321 if self.popen.returncode == None: 354 if self.popen.returncode == None:
322 self.popen.kill() 355 self.popen.kill()
323 self.popen = None 356 self.popen = None
324 357
325 def _ShutdownOnSignal(self, signum, frame): 358 def _ShutdownOnSignal(self, signum, frame):
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