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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 """Return our device name.""" | 107 """Return our device name.""" |
108 port = _GetAvailablePort() | 108 port = _GetAvailablePort() |
109 return ('emulator-%d' % port, port) | 109 return ('emulator-%d' % port, port) |
110 | 110 |
111 def Launch(self): | 111 def Launch(self): |
112 """Launches the emulator and waits for package manager to startup. | 112 """Launches the emulator and waits for package manager to startup. |
113 | 113 |
114 If fails, an exception will be raised. | 114 If fails, an exception will be raised. |
115 """ | 115 """ |
116 _KillAllEmulators() # just to be sure | 116 _KillAllEmulators() # just to be sure |
| 117 self._AggressiveImageCleanup() |
117 (self.device, port) = self._DeviceName() | 118 (self.device, port) = self._DeviceName() |
118 emulator_command = [ | 119 emulator_command = [ |
119 self.emulator, | 120 self.emulator, |
120 # Speed up emulator launch by 40%. Really. | 121 # Speed up emulator launch by 40%. Really. |
121 '-no-boot-anim', | 122 '-no-boot-anim', |
122 # The default /data size is 64M. | 123 # The default /data size is 64M. |
123 # That's not enough for 4 unit test bundles and their data. | 124 # That's not enough for 4 unit test bundles and their data. |
124 '-partition-size', '256', | 125 '-partition-size', '256', |
125 # ALWAYS wipe the data. We've seen cases where an emulator | 126 # ALWAYS wipe the data. We've seen cases where an emulator |
126 # gets 'stuck' if we don't do this (every thousand runs or | 127 # gets 'stuck' if we don't do this (every thousand runs or |
127 # so). | 128 # so). |
128 '-wipe-data', | 129 '-wipe-data', |
129 # Use a familiar name and port. | 130 # Use a familiar name and port. |
130 '-avd', 'buildbot', | 131 '-avd', 'buildbot', |
131 '-port', str(port)] | 132 '-port', str(port)] |
132 logging.info('Emulator launch command: %s', ' '.join(emulator_command)) | 133 logging.info('Emulator launch command: %s', ' '.join(emulator_command)) |
133 self.popen = subprocess.Popen(args=emulator_command, | 134 self.popen = subprocess.Popen(args=emulator_command, |
134 stderr=subprocess.STDOUT) | 135 stderr=subprocess.STDOUT) |
135 self._InstallKillHandler() | 136 self._InstallKillHandler() |
136 self._ConfirmLaunch() | 137 self._ConfirmLaunch() |
137 | 138 |
| 139 def _AggressiveImageCleanup(self): |
| 140 """Aggressive cleanup of emulator images. |
| 141 |
| 142 Experimentally it looks like our current emulator use on the bot |
| 143 leaves image files around in /tmp/android-$USER. If a "random" |
| 144 name gets reused, we choke with a 'File exists' error. |
| 145 TODO(jrg): is there a less hacky way to accomplish the same goal? |
| 146 """ |
| 147 logging.info('Aggressive Image Cleanup') |
| 148 emulator_imagedir = '/tmp/android-%s' % os.environ['USER'] |
| 149 for image in os.listdir(emulator_imagedir): |
| 150 full_name = os.path.join(emulator_imagedir, image) |
| 151 if 'emulator' in full_name: |
| 152 logging.info('Deleting emulator image %s', full_name) |
| 153 os.unlink(full_name) |
| 154 |
138 def _ConfirmLaunch(self, wait_for_boot=False): | 155 def _ConfirmLaunch(self, wait_for_boot=False): |
139 """Confirm the emulator launched properly. | 156 """Confirm the emulator launched properly. |
140 | 157 |
141 Loop on a wait-for-device with a very small timeout. On each | 158 Loop on a wait-for-device with a very small timeout. On each |
142 timeout, check the emulator process is still alive. | 159 timeout, check the emulator process is still alive. |
143 After confirming a wait-for-device can be successful, make sure | 160 After confirming a wait-for-device can be successful, make sure |
144 it returns the right answer. | 161 it returns the right answer. |
145 """ | 162 """ |
146 a = android_commands.AndroidCommands(self.device, False) | 163 a = android_commands.AndroidCommands(self.device, False) |
147 seconds_waited = 0 | 164 seconds_waited = 0 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 """Install a handler to kill the emulator when we exit unexpectedly.""" | 210 """Install a handler to kill the emulator when we exit unexpectedly.""" |
194 for sig in self._SIGNALS: | 211 for sig in self._SIGNALS: |
195 signal.signal(sig, self._ShutdownOnSignal) | 212 signal.signal(sig, self._ShutdownOnSignal) |
196 | 213 |
197 def main(argv): | 214 def main(argv): |
198 Emulator().launch() | 215 Emulator().launch() |
199 | 216 |
200 | 217 |
201 if __name__ == '__main__': | 218 if __name__ == '__main__': |
202 main(sys.argv) | 219 main(sys.argv) |
OLD | NEW |