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

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 install stuff to install script and addressed reviews. 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
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(android_sdk_root, 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:
104 android_sdk_root: location of SDK with the system images installed
108 emulator_count: number of emulators to launch. 105 emulator_count: number of emulators to launch.
106 abi: the emulator target platform
107 wait_for_boot: whether or not to wait for emulators to boot up
109 108
110 Returns: 109 Returns:
111 List of emulators. 110 List of emulators.
112 """ 111 """
113 emulators = [] 112 emulators = []
113 print 'emulator_count: %s' % emulator_count
114 for n in xrange(emulator_count): 114 for n in xrange(emulator_count):
115 t = time_profile.TimeProfile('Emulator launch %d' % n) 115 t = time_profile.TimeProfile('Emulator launch %d' % n)
116 avd_name = None 116 # Creates a temporary AVD
pasko-google - do not use 2013/03/21 12:08:37 nitty nit: full stop at the end of the sentence
navabi 2013/03/26 21:27:30 Done (assuming you mean period at the end of the s
117 if n > 0: 117 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) 118 logging.info('Emulator launch %d with avd_name=%s', n, avd_name)
121 emulator = Emulator(avd_name) 119 emulator = Emulator(android_sdk_root, avd_name, abi)
122 emulator.Launch(kill_all_emulators=n == 0) 120 emulator.Launch(kill_all_emulators=n == 0)
123 t.Stop() 121 t.Stop()
124 emulators.append(emulator) 122 emulators.append(emulator)
125 # Wait for all emulators to boot completed. 123 # Wait for all emulators to boot completed.
126 if wait_for_boot: 124 if wait_for_boot:
127 for emulator in emulators: 125 for emulator in emulators:
128 emulator.ConfirmLaunch(True) 126 emulator.ConfirmLaunch(True)
129 return emulators 127 return emulators
130 128
131 129
(...skipping 20 matching lines...) Expand all
152 # the time to launch the emulator and a wait-for-device command. 150 # the time to launch the emulator and a wait-for-device command.
153 _LAUNCH_TIMEOUT = 120 151 _LAUNCH_TIMEOUT = 120
154 152
155 # Timeout interval of wait-for-device command before bouncing to a a 153 # Timeout interval of wait-for-device command before bouncing to a a
156 # process life check. 154 # process life check.
157 _WAITFORDEVICE_TIMEOUT = 5 155 _WAITFORDEVICE_TIMEOUT = 5
158 156
159 # Time to wait for a "wait for boot complete" (property set on device). 157 # Time to wait for a "wait for boot complete" (property set on device).
160 _WAITFORBOOT_TIMEOUT = 300 158 _WAITFORBOOT_TIMEOUT = 300
161 159
162 def __init__(self, new_avd_name): 160 def __init__(self, android_sdk_root, avd_name, abi='x86'):
163 """Init an Emulator. 161 """Init an Emulator.
164 162
165 Args: 163 Args:
166 nwe_avd_name: If set, will create a new temporary AVD. 164 android_sdk_root: location of SDK with the system images installed
165 avd_name: name of the AVD to create
166 abi: target platform for emulator being created
167 """ 167 """
168 try:
169 android_sdk_root = os.environ['ANDROID_SDK_ROOT']
170 except KeyError:
171 logging.critical('The ANDROID_SDK_ROOT must be set to run the test on '
172 'emulator.')
173 raise
174 self.emulator = os.path.join(android_sdk_root, 'tools', 'emulator') 168 self.emulator = os.path.join(android_sdk_root, 'tools', 'emulator')
175 self.android = os.path.join(android_sdk_root, 'tools', 'android') 169 self.android = os.path.join(android_sdk_root, 'tools', 'android')
176 self.popen = None 170 self.popen = None
177 self.device = None 171 self.device = None
178 self.default_avd = True 172 self.abi = abi
179 self.abi = 'armeabi-v7a' 173 self.avd_name = avd_name
180 self.avd = 'avd_armeabi' 174 self._CreateAVD()
181 if 'x86' in os.environ.get('TARGET_PRODUCT', ''):
182 self.abi = 'x86'
183 self.avd = 'avd_x86'
184 if new_avd_name:
185 self.default_avd = False
186 self.avd = self._CreateAVD(new_avd_name)
187 175
188 def _DeviceName(self): 176 def _DeviceName(self):
189 """Return our device name.""" 177 """Return our device name."""
190 port = _GetAvailablePort() 178 port = _GetAvailablePort()
191 return ('emulator-%d' % port, port) 179 return ('emulator-%d' % port, port)
192 180
193 def _CreateAVD(self, avd_name): 181 def _CreateAVD(self):
194 """Creates an AVD with the given name. 182 """Creates an AVD with the given name.
195 183
196 Return avd_name. 184 Return avd_name.
197 """ 185 """
186 print 'self.android: ' + self.android
198 avd_command = [ 187 avd_command = [
199 self.android, 188 self.android,
200 '--silent', 189 '--silent',
201 'create', 'avd', 190 'create', 'avd',
202 '--name', avd_name, 191 '--name', self.avd_name,
203 '--abi', self.abi, 192 '--abi', self.abi,
204 '--target', 'android-16', 193 '--target', 'android-17',
pasko-google - do not use 2013/03/21 12:08:37 we are repeating 'android-17' here and in install-
navabi 2013/03/26 21:27:30 Done.
205 '-c', '128M', 194 '-c', '128M',
206 '--force', 195 '--force',
207 ] 196 ]
208 avd_process = subprocess.Popen(args=avd_command, 197 avd_process = subprocess.Popen(args=avd_command,
209 stdin=subprocess.PIPE, 198 stdin=subprocess.PIPE,
210 stdout=subprocess.PIPE, 199 stdout=subprocess.PIPE,
211 stderr=subprocess.STDOUT) 200 stderr=subprocess.STDOUT)
212 avd_process.stdin.write('no\n') 201 avd_process.stdin.write('no\n')
213 avd_process.wait() 202 avd_process.wait()
214 logging.info('Create AVD command: %s', ' '.join(avd_command)) 203 logging.info('Create AVD command: %s', ' '.join(avd_command))
215 return avd_name 204 return self.avd_name
216 205
217 def _DeleteAVD(self): 206 def _DeleteAVD(self):
218 """Delete the AVD of this emulator.""" 207 """Delete the AVD of this emulator."""
219 avd_command = [ 208 avd_command = [
220 self.android, 209 self.android,
221 '--silent', 210 '--silent',
222 'delete', 211 'delete',
223 'avd', 212 'avd',
224 '--name', self.avd, 213 '--name', self.avd,
225 ] 214 ]
(...skipping 13 matching lines...) Expand all
239 _KillAllEmulators() # just to be sure 228 _KillAllEmulators() # just to be sure
240 self._AggressiveImageCleanup() 229 self._AggressiveImageCleanup()
241 (self.device, port) = self._DeviceName() 230 (self.device, port) = self._DeviceName()
242 emulator_command = [ 231 emulator_command = [
243 self.emulator, 232 self.emulator,
244 # Speed up emulator launch by 40%. Really. 233 # Speed up emulator launch by 40%. Really.
245 '-no-boot-anim', 234 '-no-boot-anim',
246 # The default /data size is 64M. 235 # The default /data size is 64M.
247 # That's not enough for 8 unit test bundles and their data. 236 # That's not enough for 8 unit test bundles and their data.
248 '-partition-size', '512', 237 '-partition-size', '512',
238 # Use a familiar name and port.
239 '-avd', self.avd_name,
240 '-port', str(port),
241 # Wipe the data. We've seen cases where an emulator gets 'stuck' if we
242 # don't do this (every thousand runs or so).
243 '-wipe-data',
249 # Enable GPU by default. 244 # Enable GPU by default.
250 '-gpu', 'on', 245 '-gpu', 'on',
251 # Use a familiar name and port. 246 '-qemu', '-m', '1024',
252 '-avd', self.avd, 247 ]
253 '-port', str(port)] 248 print 'self.abi = %s' % self.abi
254 emulator_command.extend([ 249 if self.abi == 'x86':
255 # Wipe the data. We've seen cases where an emulator 250 emulator_command.extend([
256 # gets 'stuck' if we don't do this (every thousand runs or 251 # For x86 emulator --enable-kvm will fail early, avoiding accidental
257 # so). 252 # runs in a slow mode (i.e. without Intel's virtualization support).
pasko-google - do not use 2013/03/21 12:08:37 s/Intel's/hardware/
navabi 2013/03/26 21:27:30 Done.
258 '-wipe-data', 253 '--enable-kvm',
259 ]) 254 ])
255
260 logging.info('Emulator launch command: %s', ' '.join(emulator_command)) 256 logging.info('Emulator launch command: %s', ' '.join(emulator_command))
261 self.popen = subprocess.Popen(args=emulator_command, 257 self.popen = subprocess.Popen(args=emulator_command,
262 stderr=subprocess.STDOUT) 258 stderr=subprocess.STDOUT)
263 self._InstallKillHandler() 259 self._InstallKillHandler()
264 260
265 def _AggressiveImageCleanup(self): 261 def _AggressiveImageCleanup(self):
266 """Aggressive cleanup of emulator images. 262 """Aggressive cleanup of emulator images.
267 263
268 Experimentally it looks like our current emulator use on the bot 264 Experimentally it looks like our current emulator use on the bot
269 leaves image files around in /tmp/android-$USER. If a "random" 265 leaves image files around in /tmp/android-$USER. If a "random"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 raise EmulatorLaunchException('TIMEOUT with wait-for-device') 306 raise EmulatorLaunchException('TIMEOUT with wait-for-device')
311 logging.info('Seconds waited on wait-for-device: %d', seconds_waited) 307 logging.info('Seconds waited on wait-for-device: %d', seconds_waited)
312 if wait_for_boot: 308 if wait_for_boot:
313 # Now that we checked for obvious problems, wait for a boot complete. 309 # Now that we checked for obvious problems, wait for a boot complete.
314 # Waiting for the package manager is sometimes problematic. 310 # Waiting for the package manager is sometimes problematic.
315 a = android_commands.AndroidCommands(self.device) 311 a = android_commands.AndroidCommands(self.device)
316 a.WaitForSystemBootCompleted(self._WAITFORBOOT_TIMEOUT) 312 a.WaitForSystemBootCompleted(self._WAITFORBOOT_TIMEOUT)
317 313
318 def Shutdown(self): 314 def Shutdown(self):
319 """Shuts down the process started by launch.""" 315 """Shuts down the process started by launch."""
320 if not self.default_avd: 316 if not self.default_avd:
pasko-google - do not use 2013/03/21 12:08:37 this condition is always true, simplify?
navabi 2013/03/26 21:27:30 Done.
321 self._DeleteAVD() 317 self._DeleteAVD()
322 if self.popen: 318 if self.popen:
323 self.popen.poll() 319 self.popen.poll()
324 if self.popen.returncode == None: 320 if self.popen.returncode == None:
325 self.popen.kill() 321 self.popen.kill()
326 self.popen = None 322 self.popen = None
327 323
328 def _ShutdownOnSignal(self, signum, frame): 324 def _ShutdownOnSignal(self, signum, frame):
329 logging.critical('emulator _ShutdownOnSignal') 325 logging.critical('emulator _ShutdownOnSignal')
330 for sig in self._SIGNALS: 326 for sig in self._SIGNALS:
331 signal.signal(sig, signal.SIG_DFL) 327 signal.signal(sig, signal.SIG_DFL)
332 self.Shutdown() 328 self.Shutdown()
333 raise KeyboardInterrupt # print a stack 329 raise KeyboardInterrupt # print a stack
334 330
335 def _InstallKillHandler(self): 331 def _InstallKillHandler(self):
336 """Install a handler to kill the emulator when we exit unexpectedly.""" 332 """Install a handler to kill the emulator when we exit unexpectedly."""
337 for sig in self._SIGNALS: 333 for sig in self._SIGNALS:
338 signal.signal(sig, self._ShutdownOnSignal) 334 signal.signal(sig, self._ShutdownOnSignal)
OLDNEW
« build/android/install-emulator-deps.py ('K') | « build/android/install-emulator-deps.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698