OLD | NEW |
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 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 # the time to launch the emulator and a wait-for-device command. | 106 # the time to launch the emulator and a wait-for-device command. |
107 _LAUNCH_TIMEOUT = 120 | 107 _LAUNCH_TIMEOUT = 120 |
108 | 108 |
109 # Timeout interval of wait-for-device command before bouncing to a a | 109 # Timeout interval of wait-for-device command before bouncing to a a |
110 # process life check. | 110 # process life check. |
111 _WAITFORDEVICE_TIMEOUT = 5 | 111 _WAITFORDEVICE_TIMEOUT = 5 |
112 | 112 |
113 # Time to wait for a "wait for boot complete" (property set on device). | 113 # Time to wait for a "wait for boot complete" (property set on device). |
114 _WAITFORBOOT_TIMEOUT = 300 | 114 _WAITFORBOOT_TIMEOUT = 300 |
115 | 115 |
116 def __init__(self, fast_and_loose=False): | 116 def __init__(self, new_avd_name, fast_and_loose): |
117 """Init an Emulator. | 117 """Init an Emulator. |
118 | 118 |
119 Args: | 119 Args: |
| 120 nwe_avd_name: If set, will create a new temporary AVD. |
120 fast_and_loose: Loosen up the rules for reliable running for speed. | 121 fast_and_loose: Loosen up the rules for reliable running for speed. |
121 Intended for quick testing or re-testing. | 122 Intended for quick testing or re-testing. |
122 | 123 |
123 """ | 124 """ |
124 try: | 125 try: |
125 android_sdk_root = os.environ['ANDROID_SDK_ROOT'] | 126 android_sdk_root = os.environ['ANDROID_SDK_ROOT'] |
126 except KeyError: | 127 except KeyError: |
127 logging.critical('The ANDROID_SDK_ROOT must be set to run the test on ' | 128 logging.critical('The ANDROID_SDK_ROOT must be set to run the test on ' |
128 'emulator.') | 129 'emulator.') |
129 raise | 130 raise |
130 self.emulator = os.path.join(android_sdk_root, 'tools', 'emulator') | 131 self.emulator = os.path.join(android_sdk_root, 'tools', 'emulator') |
| 132 self.android = os.path.join(android_sdk_root, 'tools', 'android') |
131 self.popen = None | 133 self.popen = None |
132 self.device = None | 134 self.device = None |
| 135 self.default_avd = True |
133 self.fast_and_loose = fast_and_loose | 136 self.fast_and_loose = fast_and_loose |
| 137 self.abi = 'armeabi-v7a' |
| 138 self.avd = 'avd_armeabi' |
| 139 if 'x86' in os.environ.get('TARGET_PRODUCT', ''): |
| 140 self.abi = 'x86' |
| 141 self.avd = 'avd_x86' |
| 142 if new_avd_name: |
| 143 self.default_avd = False |
| 144 self.avd = self._CreateAVD(new_avd_name) |
134 | 145 |
135 def _DeviceName(self): | 146 def _DeviceName(self): |
136 """Return our device name.""" | 147 """Return our device name.""" |
137 port = _GetAvailablePort() | 148 port = _GetAvailablePort() |
138 return ('emulator-%d' % port, port) | 149 return ('emulator-%d' % port, port) |
139 | 150 |
| 151 def _CreateAVD(self, avd_name): |
| 152 avd_command = [ |
| 153 self.android, |
| 154 '--silent', |
| 155 'create', 'avd', |
| 156 '--name', avd_name, |
| 157 '--abi', self.abi, |
| 158 '--target', 'android-15', |
| 159 '-c', '64M', |
| 160 '--force', |
| 161 ] |
| 162 avd_process = subprocess.Popen(args=avd_command, |
| 163 stdin=subprocess.PIPE, |
| 164 stdout=subprocess.PIPE, |
| 165 stderr=subprocess.STDOUT) |
| 166 avd_process.stdin.write('no\n') |
| 167 avd_process.wait() |
| 168 logging.info('Create AVD command: %s', ' '.join(avd_command)) |
| 169 return self.avd |
| 170 |
| 171 def _DeleteAVD(self): |
| 172 avd_command = [ |
| 173 self.android, |
| 174 '--silent', |
| 175 'delete', |
| 176 'avd', |
| 177 '--name', self.avd, |
| 178 ] |
| 179 avd_process = subprocess.Popen(args=avd_command, |
| 180 stdout=subprocess.PIPE, |
| 181 stderr=subprocess.STDOUT) |
| 182 logging.info('Delete AVD command: %s', ' '.join(avd_command)) |
| 183 avd_process.wait() |
| 184 |
140 def Launch(self, kill_all_emulators): | 185 def Launch(self, kill_all_emulators): |
141 """Launches the emulator asynchronously. Call ConfirmLaunch() to ensure the | 186 """Launches the emulator asynchronously. Call ConfirmLaunch() to ensure the |
142 emulator is ready for use. | 187 emulator is ready for use. |
143 | 188 |
144 If fails, an exception will be raised. | 189 If fails, an exception will be raised. |
145 """ | 190 """ |
146 if kill_all_emulators: | 191 if kill_all_emulators: |
147 _KillAllEmulators() # just to be sure | 192 _KillAllEmulators() # just to be sure |
148 if not self.fast_and_loose: | 193 if not self.fast_and_loose: |
149 self._AggressiveImageCleanup() | 194 self._AggressiveImageCleanup() |
150 (self.device, port) = self._DeviceName() | 195 (self.device, port) = self._DeviceName() |
151 abi = 'armeabi' | |
152 if 'x86' in os.environ.get('TARGET_PRODUCT', ''): | |
153 abi = 'x86' | |
154 emulator_command = [ | 196 emulator_command = [ |
155 self.emulator, | 197 self.emulator, |
156 # Speed up emulator launch by 40%. Really. | 198 # Speed up emulator launch by 40%. Really. |
157 '-no-boot-anim', | 199 '-no-boot-anim', |
158 # The default /data size is 64M. | 200 # The default /data size is 64M. |
159 # That's not enough for 8 unit test bundles and their data. | 201 # That's not enough for 8 unit test bundles and their data. |
160 '-partition-size', '512', | 202 '-partition-size', '512', |
161 # Use a familiar name and port. | 203 # Use a familiar name and port. |
162 '-avd', 'avd_' + abi, | 204 '-avd', self.avd, |
163 '-port', str(port)] | 205 '-port', str(port)] |
164 if not self.fast_and_loose: | 206 if not self.fast_and_loose: |
165 emulator_command.extend([ | 207 emulator_command.extend([ |
166 # Wipe the data. We've seen cases where an emulator | 208 # Wipe the data. We've seen cases where an emulator |
167 # gets 'stuck' if we don't do this (every thousand runs or | 209 # gets 'stuck' if we don't do this (every thousand runs or |
168 # so). | 210 # so). |
169 '-wipe-data', | 211 '-wipe-data', |
170 ]) | 212 ]) |
171 logging.info('Emulator launch command: %s', ' '.join(emulator_command)) | 213 logging.info('Emulator launch command: %s', ' '.join(emulator_command)) |
172 self.popen = subprocess.Popen(args=emulator_command, | 214 self.popen = subprocess.Popen(args=emulator_command, |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 raise EmulatorLaunchException('TIMEOUT with wait-for-device') | 263 raise EmulatorLaunchException('TIMEOUT with wait-for-device') |
222 logging.info('Seconds waited on wait-for-device: %d', seconds_waited) | 264 logging.info('Seconds waited on wait-for-device: %d', seconds_waited) |
223 if wait_for_boot: | 265 if wait_for_boot: |
224 # Now that we checked for obvious problems, wait for a boot complete. | 266 # Now that we checked for obvious problems, wait for a boot complete. |
225 # Waiting for the package manager is sometimes problematic. | 267 # Waiting for the package manager is sometimes problematic. |
226 a = android_commands.AndroidCommands(self.device) | 268 a = android_commands.AndroidCommands(self.device) |
227 a.WaitForSystemBootCompleted(self._WAITFORBOOT_TIMEOUT) | 269 a.WaitForSystemBootCompleted(self._WAITFORBOOT_TIMEOUT) |
228 | 270 |
229 def Shutdown(self): | 271 def Shutdown(self): |
230 """Shuts down the process started by launch.""" | 272 """Shuts down the process started by launch.""" |
| 273 if not self.default_avd: |
| 274 self._DeleteAVD() |
231 if self.popen: | 275 if self.popen: |
232 self.popen.poll() | 276 self.popen.poll() |
233 if self.popen.returncode == None: | 277 if self.popen.returncode == None: |
234 self.popen.kill() | 278 self.popen.kill() |
235 self.popen = None | 279 self.popen = None |
236 | 280 |
237 def _ShutdownOnSignal(self, signum, frame): | 281 def _ShutdownOnSignal(self, signum, frame): |
238 logging.critical('emulator _ShutdownOnSignal') | 282 logging.critical('emulator _ShutdownOnSignal') |
239 for sig in self._SIGNALS: | 283 for sig in self._SIGNALS: |
240 signal.signal(sig, signal.SIG_DFL) | 284 signal.signal(sig, signal.SIG_DFL) |
241 self.Shutdown() | 285 self.Shutdown() |
242 raise KeyboardInterrupt # print a stack | 286 raise KeyboardInterrupt # print a stack |
243 | 287 |
244 def _InstallKillHandler(self): | 288 def _InstallKillHandler(self): |
245 """Install a handler to kill the emulator when we exit unexpectedly.""" | 289 """Install a handler to kill the emulator when we exit unexpectedly.""" |
246 for sig in self._SIGNALS: | 290 for sig in self._SIGNALS: |
247 signal.signal(sig, self._ShutdownOnSignal) | 291 signal.signal(sig, self._ShutdownOnSignal) |
248 | 292 |
249 def main(argv): | 293 def main(argv): |
250 Emulator(True).Launch(True) | 294 Emulator(None, True).Launch(True) |
251 | 295 |
252 | 296 |
253 if __name__ == '__main__': | 297 if __name__ == '__main__': |
254 main(sys.argv) | 298 main(sys.argv) |
OLD | NEW |