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

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

Issue 12407004: Add script to download SDK, system images and create and start AVDs for testing. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removed old emulator driver script. Created 7 years, 9 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
« build/android/avd.py ('K') | « build/android/emulator.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 signal 17 import signal
18 import subprocess 18 import subprocess
19 import sys 19 import sys
20 import time 20 import time
21 21
22 import time_profile 22 import time_profile
23 # TODO(craigdh): Move these pylib dependencies to pylib/utils/. 23 # TODO(craigdh): Move these pylib dependencies to pylib/utils/.
24 from pylib import android_commands 24 from pylib import android_commands
25 from pylib import cmd_helper 25 from pylib import cmd_helper
26 26
27 # adb_interface.py is under ../../third_party/android_testrunner/
28 sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), '..',
29 '..', 'third_party', 'android_testrunner'))
30 import adb_interface
31 import errors 27 import errors
32 import run_command 28 import run_command
33 29
34 class EmulatorLaunchException(Exception): 30 class EmulatorLaunchException(Exception):
35 """Emulator failed to launch.""" 31 """Emulator failed to launch."""
36 pass 32 pass
37 33
38 def _KillAllEmulators(): 34 def _KillAllEmulators():
39 """Kill all running emulators that look like ones we started. 35 """Kill all running emulators that look like ones we started.
40 36
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 """Returns an available TCP port for the console.""" 90 """Returns an available TCP port for the console."""
95 used_ports = [] 91 used_ports = []
96 emulators = android_commands.GetEmulators() 92 emulators = android_commands.GetEmulators()
97 for emulator in emulators: 93 for emulator in emulators:
98 used_ports.append(emulator.split('-')[1]) 94 used_ports.append(emulator.split('-')[1])
99 for port in PortPool.port_range(): 95 for port in PortPool.port_range():
100 if str(port) not in used_ports: 96 if str(port) not in used_ports:
101 return port 97 return port
102 98
103 99
104 def LaunchEmulators(emulator_count, wait_for_boot=True): 100 def LaunchEmulators(emulator_count, abi, wait_for_boot=True):
105 """Launch multiple emulators and wait for them to boot. 101 """Launch multiple emulators and wait for them to boot.
106 102
107 Args: 103 Args:
108 emulator_count: number of emulators to launch. 104 emulator_count: number of emulators to launch.
navabi 2013/03/14 02:39:47 need to add abi to arg list.
pasko-google - do not use 2013/03/14 15:46:28 I assume you are going to do it? Or there a dedica
navabi 2013/03/20 21:40:16 Haha. Yeah, I'm still in the process of arguing wi
105 wait_for_boot: whether or not to wait for emulators to boot up
109 106
110 Returns: 107 Returns:
111 List of emulators. 108 List of emulators.
112 """ 109 """
113 emulators = [] 110 emulators = []
114 for n in xrange(emulator_count): 111 for n in xrange(emulator_count):
115 t = time_profile.TimeProfile('Emulator launch %d' % n) 112 t = time_profile.TimeProfile('Emulator launch %d' % n)
116 avd_name = None 113 # Creates a temporary AVD
117 if n > 0: 114 avd_name = 'run_tests_avd_%d' % n
118 # Creates a temporary AVD for the extra emulators.
119 avd_name = 'run_tests_avd_%d' % n
120 logging.info('Emulator launch %d with avd_name=%s', n, avd_name) 115 logging.info('Emulator launch %d with avd_name=%s', n, avd_name)
121 emulator = Emulator(avd_name) 116 emulator = Emulator(avd_name, abi)
122 emulator.Launch(kill_all_emulators=n == 0) 117 emulator.Launch(kill_all_emulators=n == 0)
123 t.Stop() 118 t.Stop()
124 emulators.append(emulator) 119 emulators.append(emulator)
125 # Wait for all emulators to boot completed. 120 # Wait for all emulators to boot completed.
126 if wait_for_boot: 121 if wait_for_boot:
127 for emulator in emulators: 122 for emulator in emulators:
128 emulator.ConfirmLaunch(True) 123 emulator.ConfirmLaunch(True)
129 return emulators 124 return emulators
130 125
131 126
(...skipping 20 matching lines...) Expand all
152 # the time to launch the emulator and a wait-for-device command. 147 # the time to launch the emulator and a wait-for-device command.
153 _LAUNCH_TIMEOUT = 120 148 _LAUNCH_TIMEOUT = 120
154 149
155 # Timeout interval of wait-for-device command before bouncing to a a 150 # Timeout interval of wait-for-device command before bouncing to a a
156 # process life check. 151 # process life check.
157 _WAITFORDEVICE_TIMEOUT = 5 152 _WAITFORDEVICE_TIMEOUT = 5
158 153
159 # Time to wait for a "wait for boot complete" (property set on device). 154 # Time to wait for a "wait for boot complete" (property set on device).
160 _WAITFORBOOT_TIMEOUT = 300 155 _WAITFORBOOT_TIMEOUT = 300
161 156
162 def __init__(self, new_avd_name): 157 def __init__(self, avd_name, abi='armeabi-v7a'):
163 """Init an Emulator. 158 """Init an Emulator.
164 159
165 Args: 160 Args:
166 nwe_avd_name: If set, will create a new temporary AVD. 161 avd_name: name of the AVD to create
162 abi: target platform for emulator being created
navabi 2013/03/14 02:39:47 should make default abi x86, since that is the mor
navabi 2013/03/20 21:40:16 Done.
167 """ 163 """
168 try: 164 try:
169 android_sdk_root = os.environ['ANDROID_SDK_ROOT'] 165 android_sdk_root = os.environ['ANDROID_SDK_ROOT']
navabi 2013/03/20 21:40:16 While the emulator requires this to be set, I have
170 except KeyError: 166 except KeyError:
171 logging.critical('The ANDROID_SDK_ROOT must be set to run the test on ' 167 logging.critical('The ANDROID_SDK_ROOT must be set to run the test on '
172 'emulator.') 168 'emulator.')
173 raise 169 raise
174 self.emulator = os.path.join(android_sdk_root, 'tools', 'emulator') 170 self.emulator = os.path.join(android_sdk_root, 'tools', 'emulator')
175 self.android = os.path.join(android_sdk_root, 'tools', 'android') 171 self.android = os.path.join(android_sdk_root, 'tools', 'android')
176 self.popen = None 172 self.popen = None
177 self.device = None 173 self.device = None
178 self.default_avd = True 174 self.abi = abi
179 self.abi = 'armeabi-v7a' 175 if 'ia32' in os.environ.get('target_arch', ''):
pasko-google - do not use 2013/03/14 15:46:28 For future CLs: I may want to override this settin
navabi 2013/03/20 21:40:16 Done. We actually don't need this here. The avd.py
180 self.avd = 'avd_armeabi'
181 if 'x86' in os.environ.get('TARGET_PRODUCT', ''):
182 self.abi = 'x86' 176 self.abi = 'x86'
183 self.avd = 'avd_x86' 177 self.avd_name = avd_name
184 if new_avd_name: 178 self._CreateAVD()
185 self.default_avd = False
186 self.avd = self._CreateAVD(new_avd_name)
187 179
188 def _DeviceName(self): 180 def _DeviceName(self):
189 """Return our device name.""" 181 """Return our device name."""
190 port = _GetAvailablePort() 182 port = _GetAvailablePort()
191 return ('emulator-%d' % port, port) 183 return ('emulator-%d' % port, port)
192 184
193 def _CreateAVD(self, avd_name): 185 def _CreateAVD(self):
194 """Creates an AVD with the given name. 186 """Creates an AVD with the given name.
195 187
196 Return avd_name. 188 Return avd_name.
197 """ 189 """
190 print 'self.android: ' + self.android
198 avd_command = [ 191 avd_command = [
199 self.android, 192 self.android,
200 '--silent', 193 '--silent',
201 'create', 'avd', 194 'create', 'avd',
202 '--name', avd_name, 195 '--name', self.avd_name,
203 '--abi', self.abi, 196 '--abi', self.abi,
204 '--target', 'android-16', 197 '--target', 'android-17',
205 '-c', '128M', 198 '-c', '128M',
206 '--force', 199 '--force',
207 ] 200 ]
208 avd_process = subprocess.Popen(args=avd_command, 201 avd_process = subprocess.Popen(args=avd_command,
209 stdin=subprocess.PIPE, 202 stdin=subprocess.PIPE,
210 stdout=subprocess.PIPE, 203 stdout=subprocess.PIPE,
211 stderr=subprocess.STDOUT) 204 stderr=subprocess.STDOUT)
212 avd_process.stdin.write('no\n') 205 avd_process.stdin.write('no\n')
213 avd_process.wait() 206 avd_process.wait()
214 logging.info('Create AVD command: %s', ' '.join(avd_command)) 207 logging.info('Create AVD command: %s', ' '.join(avd_command))
215 return avd_name 208 return self.avd_name
216 209
217 def _DeleteAVD(self): 210 def _DeleteAVD(self):
218 """Delete the AVD of this emulator.""" 211 """Delete the AVD of this emulator."""
219 avd_command = [ 212 avd_command = [
220 self.android, 213 self.android,
221 '--silent', 214 '--silent',
222 'delete', 215 'delete',
223 'avd', 216 'avd',
224 '--name', self.avd, 217 '--name', self.avd,
225 ] 218 ]
(...skipping 13 matching lines...) Expand all
239 _KillAllEmulators() # just to be sure 232 _KillAllEmulators() # just to be sure
240 self._AggressiveImageCleanup() 233 self._AggressiveImageCleanup()
241 (self.device, port) = self._DeviceName() 234 (self.device, port) = self._DeviceName()
242 emulator_command = [ 235 emulator_command = [
243 self.emulator, 236 self.emulator,
244 # Speed up emulator launch by 40%. Really. 237 # Speed up emulator launch by 40%. Really.
245 '-no-boot-anim', 238 '-no-boot-anim',
246 # The default /data size is 64M. 239 # The default /data size is 64M.
247 # That's not enough for 8 unit test bundles and their data. 240 # That's not enough for 8 unit test bundles and their data.
248 '-partition-size', '512', 241 '-partition-size', '512',
242 # Use a familiar name and port.
243 '-avd', self.avd_name,
244 '-port', str(port),
245 # Wipe the data. We've seen cases where an emulator gets 'stuck' if we
246 # don't do this (every thousand runs or so).
247 '-wipe-data',
249 # Enable GPU by default. 248 # Enable GPU by default.
250 '-gpu', 'on', 249 '-gpu', 'on',
251 # Use a familiar name and port. 250 '-qemu', '-m', '512',
pasko-google - do not use 2013/03/14 15:46:28 1024
navabi 2013/03/20 21:40:16 Done.
252 '-avd', self.avd, 251 ]
253 '-port', str(port)] 252 print 'self.abi = %s' % self.abi
254 emulator_command.extend([ 253 if self.abi == 'x86':
255 # Wipe the data. We've seen cases where an emulator 254 emulator_command.extend([
256 # gets 'stuck' if we don't do this (every thousand runs or 255 # For x86 emulator --enable-kvm will makes explicit as to whether or
257 # so). 256 # not Intel's virtualization support is being used.
pasko-google - do not use 2013/03/14 15:46:28 It is not quite clear what the word "explicit" mea
navabi 2013/03/20 21:40:16 Done.
258 '-wipe-data', 257 '--enable-kvm',
259 ]) 258 ])
259
260 logging.info('Emulator launch command: %s', ' '.join(emulator_command)) 260 logging.info('Emulator launch command: %s', ' '.join(emulator_command))
261 self.popen = subprocess.Popen(args=emulator_command, 261 self.popen = subprocess.Popen(args=emulator_command,
262 stderr=subprocess.STDOUT) 262 stderr=subprocess.STDOUT)
263 self._InstallKillHandler() 263 self._InstallKillHandler()
264 264
265 def _AggressiveImageCleanup(self): 265 def _AggressiveImageCleanup(self):
266 """Aggressive cleanup of emulator images. 266 """Aggressive cleanup of emulator images.
267 267
268 Experimentally it looks like our current emulator use on the bot 268 Experimentally it looks like our current emulator use on the bot
269 leaves image files around in /tmp/android-$USER. If a "random" 269 leaves image files around in /tmp/android-$USER. If a "random"
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 logging.critical('emulator _ShutdownOnSignal') 329 logging.critical('emulator _ShutdownOnSignal')
330 for sig in self._SIGNALS: 330 for sig in self._SIGNALS:
331 signal.signal(sig, signal.SIG_DFL) 331 signal.signal(sig, signal.SIG_DFL)
332 self.Shutdown() 332 self.Shutdown()
333 raise KeyboardInterrupt # print a stack 333 raise KeyboardInterrupt # print a stack
334 334
335 def _InstallKillHandler(self): 335 def _InstallKillHandler(self):
336 """Install a handler to kill the emulator when we exit unexpectedly.""" 336 """Install a handler to kill the emulator when we exit unexpectedly."""
337 for sig in self._SIGNALS: 337 for sig in self._SIGNALS:
338 signal.signal(sig, self._ShutdownOnSignal) 338 signal.signal(sig, self._ShutdownOnSignal)
OLDNEW
« build/android/avd.py ('K') | « build/android/emulator.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698