| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Provides an interface to start and stop Android emulator. | 6 """Provides an interface to start and stop Android emulator. |
| 7 | 7 |
| 8 Assumes system environment ANDROID_NDK_ROOT has been set. | 8 Assumes system environment ANDROID_NDK_ROOT has been set. |
| 9 | 9 |
| 10 Emulator: The class provides the methods to launch/shutdown the emulator with | 10 Emulator: The class provides the methods to launch/shutdown the emulator with |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 self.emulator = os.path.join(android_sdk_root, 'tools', 'emulator') | 129 self.emulator = os.path.join(android_sdk_root, 'tools', 'emulator') |
| 130 self.popen = None | 130 self.popen = None |
| 131 self.device = None | 131 self.device = None |
| 132 self.fast_and_loose = fast_and_loose | 132 self.fast_and_loose = fast_and_loose |
| 133 | 133 |
| 134 def _DeviceName(self): | 134 def _DeviceName(self): |
| 135 """Return our device name.""" | 135 """Return our device name.""" |
| 136 port = _GetAvailablePort() | 136 port = _GetAvailablePort() |
| 137 return ('emulator-%d' % port, port) | 137 return ('emulator-%d' % port, port) |
| 138 | 138 |
| 139 def Launch(self): | 139 def Launch(self, kill_all_emulators): |
| 140 """Launches the emulator and waits for package manager to startup. | 140 """Launches the emulator asynchronously. Call ConfirmLaunch() to ensure the |
| 141 emulator is ready for use. |
| 141 | 142 |
| 142 If fails, an exception will be raised. | 143 If fails, an exception will be raised. |
| 143 """ | 144 """ |
| 144 _KillAllEmulators() # just to be sure | 145 if kill_all_emulators: |
| 146 _KillAllEmulators() # just to be sure |
| 145 if not self.fast_and_loose: | 147 if not self.fast_and_loose: |
| 146 self._AggressiveImageCleanup() | 148 self._AggressiveImageCleanup() |
| 147 (self.device, port) = self._DeviceName() | 149 (self.device, port) = self._DeviceName() |
| 148 emulator_command = [ | 150 emulator_command = [ |
| 149 self.emulator, | 151 self.emulator, |
| 150 # Speed up emulator launch by 40%. Really. | 152 # Speed up emulator launch by 40%. Really. |
| 151 '-no-boot-anim', | 153 '-no-boot-anim', |
| 152 # The default /data size is 64M. | 154 # The default /data size is 64M. |
| 153 # That's not enough for 4 unit test bundles and their data. | 155 # That's not enough for 4 unit test bundles and their data. |
| 154 '-partition-size', '256', | 156 '-partition-size', '256', |
| 155 # Use a familiar name and port. | 157 # Use a familiar name and port. |
| 156 '-avd', 'buildbot', | 158 '-avd', 'buildbot', |
| 157 '-port', str(port)] | 159 '-port', str(port)] |
| 158 if not self.fast_and_loose: | 160 if not self.fast_and_loose: |
| 159 emulator_command.extend([ | 161 emulator_command.extend([ |
| 160 # Wipe the data. We've seen cases where an emulator | 162 # Wipe the data. We've seen cases where an emulator |
| 161 # gets 'stuck' if we don't do this (every thousand runs or | 163 # gets 'stuck' if we don't do this (every thousand runs or |
| 162 # so). | 164 # so). |
| 163 '-wipe-data', | 165 '-wipe-data', |
| 164 ]) | 166 ]) |
| 165 logging.info('Emulator launch command: %s', ' '.join(emulator_command)) | 167 logging.info('Emulator launch command: %s', ' '.join(emulator_command)) |
| 166 self.popen = subprocess.Popen(args=emulator_command, | 168 self.popen = subprocess.Popen(args=emulator_command, |
| 167 stderr=subprocess.STDOUT) | 169 stderr=subprocess.STDOUT) |
| 168 self._InstallKillHandler() | 170 self._InstallKillHandler() |
| 169 self._ConfirmLaunch() | |
| 170 | 171 |
| 171 def _AggressiveImageCleanup(self): | 172 def _AggressiveImageCleanup(self): |
| 172 """Aggressive cleanup of emulator images. | 173 """Aggressive cleanup of emulator images. |
| 173 | 174 |
| 174 Experimentally it looks like our current emulator use on the bot | 175 Experimentally it looks like our current emulator use on the bot |
| 175 leaves image files around in /tmp/android-$USER. If a "random" | 176 leaves image files around in /tmp/android-$USER. If a "random" |
| 176 name gets reused, we choke with a 'File exists' error. | 177 name gets reused, we choke with a 'File exists' error. |
| 177 TODO(jrg): is there a less hacky way to accomplish the same goal? | 178 TODO(jrg): is there a less hacky way to accomplish the same goal? |
| 178 """ | 179 """ |
| 179 logging.info('Aggressive Image Cleanup') | 180 logging.info('Aggressive Image Cleanup') |
| 180 emulator_imagedir = '/tmp/android-%s' % os.environ['USER'] | 181 emulator_imagedir = '/tmp/android-%s' % os.environ['USER'] |
| 181 if not os.path.exists(emulator_imagedir): | 182 if not os.path.exists(emulator_imagedir): |
| 182 return | 183 return |
| 183 for image in os.listdir(emulator_imagedir): | 184 for image in os.listdir(emulator_imagedir): |
| 184 full_name = os.path.join(emulator_imagedir, image) | 185 full_name = os.path.join(emulator_imagedir, image) |
| 185 if 'emulator' in full_name: | 186 if 'emulator' in full_name: |
| 186 logging.info('Deleting emulator image %s', full_name) | 187 logging.info('Deleting emulator image %s', full_name) |
| 187 os.unlink(full_name) | 188 os.unlink(full_name) |
| 188 | 189 |
| 189 def _ConfirmLaunch(self, wait_for_boot=False): | 190 def ConfirmLaunch(self, wait_for_boot=False): |
| 190 """Confirm the emulator launched properly. | 191 """Confirm the emulator launched properly. |
| 191 | 192 |
| 192 Loop on a wait-for-device with a very small timeout. On each | 193 Loop on a wait-for-device with a very small timeout. On each |
| 193 timeout, check the emulator process is still alive. | 194 timeout, check the emulator process is still alive. |
| 194 After confirming a wait-for-device can be successful, make sure | 195 After confirming a wait-for-device can be successful, make sure |
| 195 it returns the right answer. | 196 it returns the right answer. |
| 196 """ | 197 """ |
| 197 a = android_commands.AndroidCommands(self.device, False) | 198 a = android_commands.AndroidCommands(self.device, False) |
| 198 seconds_waited = 0 | 199 seconds_waited = 0 |
| 199 number_of_waits = 2 # Make sure we can wfd twice | 200 number_of_waits = 2 # Make sure we can wfd twice |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 """Install a handler to kill the emulator when we exit unexpectedly.""" | 245 """Install a handler to kill the emulator when we exit unexpectedly.""" |
| 245 for sig in self._SIGNALS: | 246 for sig in self._SIGNALS: |
| 246 signal.signal(sig, self._ShutdownOnSignal) | 247 signal.signal(sig, self._ShutdownOnSignal) |
| 247 | 248 |
| 248 def main(argv): | 249 def main(argv): |
| 249 Emulator().launch() | 250 Emulator().launch() |
| 250 | 251 |
| 251 | 252 |
| 252 if __name__ == '__main__': | 253 if __name__ == '__main__': |
| 253 main(sys.argv) | 254 main(sys.argv) |
| OLD | NEW |