OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2013 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 """Installs deps for using SDK emulator for testing. | 6 """Installs deps for using SDK emulator for testing. |
7 | 7 |
8 The script will download the SDK and system images, if they are not present, and | 8 The script will download the SDK and system images, if they are not present, and |
9 install and enable KVM, if virtualization has been enabled in the BIOS. | 9 install and enable KVM, if virtualization has been enabled in the BIOS. |
10 """ | 10 """ |
11 | 11 |
12 | 12 |
13 import logging | 13 import logging |
14 import optparse | 14 import optparse |
15 import os | 15 import os |
16 import re | 16 import re |
17 import sys | 17 import sys |
18 | 18 |
19 from devil.utils import cmd_helper | 19 from devil.utils import cmd_helper |
20 from devil.utils import run_tests_helper | 20 from devil.utils import run_tests_helper |
21 from pylib import constants | 21 from pylib import constants |
22 from pylib import pexpect | 22 from pylib import pexpect |
23 | 23 |
24 # Android API level | 24 # Android API level |
25 DEFAULT_ANDROID_API_LEVEL = constants.ANDROID_SDK_VERSION | 25 DEFAULT_ANDROID_API_LEVEL = constants.ANDROID_SDK_VERSION |
| 26 # Android ABI/Arch |
| 27 DEFAULT_ABI = 'x86' |
26 | 28 |
27 # Default Time out for downloading SDK component | 29 # Default Time out for downloading SDK component |
28 DOWNLOAD_SYSTEM_IMAGE_TIMEOUT = 30 | 30 DOWNLOAD_SYSTEM_IMAGE_TIMEOUT = 30 |
29 DOWNLOAD_SDK_PLATFORM_TIMEOUT = 60 | 31 DOWNLOAD_SDK_PLATFORM_TIMEOUT = 60 |
30 | 32 |
31 def CheckSDK(): | 33 def CheckSDK(): |
32 """Check if SDK is already installed. | 34 """Check if SDK is already installed. |
33 | 35 |
34 Returns: | 36 Returns: |
35 True if the emulator SDK directory (src/android_emulator_sdk/) exists. | 37 True if the emulator SDK directory (src/android_emulator_sdk/) exists. |
36 """ | 38 """ |
37 return os.path.exists(constants.ANDROID_SDK_ROOT) | 39 return os.path.exists(constants.ANDROID_SDK_ROOT) |
38 | 40 |
39 | 41 |
40 def CheckSDKPlatform(api_level=DEFAULT_ANDROID_API_LEVEL): | 42 def CheckSDKPlatform(api_level=DEFAULT_ANDROID_API_LEVEL, google=False): |
41 """Check if the "SDK Platform" for the specified API level is installed. | 43 """Check if the "SDK Platform" for the specified API level is installed. |
42 This is necessary in order for the emulator to run when the target | 44 This is necessary in order for the emulator to run when the target |
43 is specified. | 45 is specified. |
44 | 46 |
45 Args: | 47 Args: |
| 48 abi: target abi, x86 or arm |
46 api_level: the Android API level to check; defaults to the latest API. | 49 api_level: the Android API level to check; defaults to the latest API. |
| 50 google: use Google build system image instead of AOSP build |
47 | 51 |
48 Returns: | 52 Returns: |
49 True if the platform is already installed. | 53 True if the platform is already installed. |
50 """ | 54 """ |
51 android_binary = os.path.join(constants.ANDROID_SDK_ROOT, 'tools', 'android') | 55 android_binary = os.path.join(constants.ANDROID_SDK_ROOT, 'tools', 'android') |
52 pattern = re.compile('id: [0-9]+ or "android-%d"' % api_level) | 56 if google: |
| 57 pattern = re.compile('id: [0-9]+ or "Google Inc.:Google APIs:%s"' % |
| 58 api_level) |
| 59 else: |
| 60 pattern = re.compile('id: [0-9]+ or "android-%d"' % api_level) |
| 61 |
53 try: | 62 try: |
54 exit_code, stdout = cmd_helper.GetCmdStatusAndOutput( | 63 exit_code, stdout = cmd_helper.GetCmdStatusAndOutput( |
55 [android_binary, 'list']) | 64 [android_binary, 'list']) |
56 if exit_code != 0: | 65 if exit_code != 0: |
57 raise Exception('\'android list\' command failed') | 66 raise Exception('\'android list\' command failed') |
58 for line in stdout.split('\n'): | 67 for line in stdout.split('\n'): |
59 if pattern.match(line): | 68 if pattern.match(line): |
60 return True | 69 return True |
61 return False | 70 return False |
62 except OSError: | 71 except OSError: |
63 logging.exception('Unable to execute \'android list\'') | 72 logging.exception('Unable to execute \'android list\'') |
64 return False | 73 return False |
65 | 74 |
66 | 75 |
67 def CheckX86Image(api_level=DEFAULT_ANDROID_API_LEVEL): | 76 def CheckSystemImage(abi, api_level=DEFAULT_ANDROID_API_LEVEL, google=False): |
68 """Check if Android system images have been installed. | 77 """Check if Android system images have been installed. |
69 | 78 |
70 Args: | 79 Args: |
| 80 abi: target abi, x86 or arm |
71 api_level: the Android API level to check for; defaults to the latest API. | 81 api_level: the Android API level to check for; defaults to the latest API. |
| 82 google: use Google build system image instead of AOSP build |
72 | 83 |
73 Returns: | 84 Returns: |
74 True if x86 image has been previously downloaded. | 85 True if x86 image has been previously downloaded. |
75 """ | 86 """ |
76 api_target = 'android-%d' % api_level | 87 api_target = 'android-%d' % api_level |
77 return os.path.exists(os.path.join(constants.ANDROID_SDK_ROOT, | 88 system_image_root = os.path.join(constants.ANDROID_SDK_ROOT, |
78 'system-images', api_target, 'default', | 89 'system-images', api_target) |
79 'x86')) | 90 if abi == 'x86': |
80 | 91 if google: |
| 92 return os.path.exists(os.path.join(system_image_root, 'google_apis', |
| 93 'x86')) |
| 94 else: |
| 95 return os.path.exists(os.path.join(system_image_root, 'default', 'x86')) |
| 96 elif abi == 'arm': |
| 97 if google: |
| 98 return os.path.exists(os.path.join(system_image_root, 'google_apis', |
| 99 'armeabi-v7a')) |
| 100 else: |
| 101 return os.path.exists(os.path.join(system_image_root, 'default', |
| 102 'armeabi-v7a')) |
| 103 else: |
| 104 raise Exception("abi option invalid") |
81 | 105 |
82 def CheckKVM(): | 106 def CheckKVM(): |
83 """Quickly check whether KVM is enabled. | 107 """Quickly check whether KVM is enabled. |
84 | 108 |
85 Returns: | 109 Returns: |
86 True iff /dev/kvm exists (Linux only). | 110 True iff /dev/kvm exists (Linux only). |
87 """ | 111 """ |
88 return os.path.exists('/dev/kvm') | 112 return os.path.exists('/dev/kvm') |
89 | 113 |
90 | |
91 def RunKvmOk(): | 114 def RunKvmOk(): |
92 """Run kvm-ok as root to check that KVM is properly enabled after installation | 115 """Run kvm-ok as root to check that KVM is properly enabled after installation |
93 of the required packages. | 116 of the required packages. |
94 | 117 |
95 Returns: | 118 Returns: |
96 True iff KVM is enabled (/dev/kvm exists). On failure, returns False | 119 True iff KVM is enabled (/dev/kvm exists). On failure, returns False |
97 but also print detailed information explaining why KVM isn't enabled | 120 but also print detailed information explaining why KVM isn't enabled |
98 (e.g. CPU doesn't support it, or BIOS disabled it). | 121 (e.g. CPU doesn't support it, or BIOS disabled it). |
99 """ | 122 """ |
100 try: | 123 try: |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 update_process.sendline('y') | 182 update_process.sendline('y') |
160 if update_process.expect( | 183 if update_process.expect( |
161 'Done. 1 package installed.', timeout=timeout) == 0: | 184 'Done. 1 package installed.', timeout=timeout) == 0: |
162 logging.info('Successfully installed %s for API level %d', | 185 logging.info('Successfully installed %s for API level %d', |
163 package_name, api_level) | 186 package_name, api_level) |
164 return | 187 return |
165 else: | 188 else: |
166 raise Exception('Failed to install platform update') | 189 raise Exception('Failed to install platform update') |
167 raise Exception('Could not find android-%d update for the SDK!' % api_level) | 190 raise Exception('Could not find android-%d update for the SDK!' % api_level) |
168 | 191 |
169 def GetX86Image(api_level=DEFAULT_ANDROID_API_LEVEL): | 192 def GetSystemImage(abi, api_level=DEFAULT_ANDROID_API_LEVEL, google=False): |
170 """Download x86 system image from Intel's website. | 193 """Download system image files |
171 | 194 |
172 Args: | 195 Args: |
| 196 abi: target abi, x86 or arm |
173 api_level: the Android API level to download for. | 197 api_level: the Android API level to download for. |
| 198 google: use Google build system image instead of AOSP build |
174 """ | 199 """ |
175 logging.info('Download x86 system image directory into sdk directory.') | 200 logging.info('Download x86 system image directory into sdk directory.') |
176 | 201 |
177 x86_package_pattern = re.compile( | 202 if abi == 'x86': |
178 r'\s*([0-9]+)- Intel x86 Atom System Image, Android API %d.*' % api_level) | 203 if google: |
| 204 package_name = 'Google Intel x86 Atom System Image' |
| 205 pattern = re.compile( |
| 206 r'\s*([0-9]+)- Google APIs Intel x86 Atom System Image, Google Inc.' |
| 207 ' API %d.*' % api_level) |
| 208 else: |
| 209 package_name = 'Intel x86 system image' |
| 210 pattern = re.compile( |
| 211 r'\s*([0-9]+)- Intel x86 Atom System Image, Android API %d.*' |
| 212 % api_level) |
| 213 elif abi == 'arm': |
| 214 if google: |
| 215 package_name = 'Google arm system image' |
| 216 pattern = re.compile( |
| 217 r'\s*([0-9]+)- Google APIs ARM EABI v7a System Image, Google Inc. API ' |
| 218 '%d.*' % api_level) |
| 219 else: |
| 220 package_name = 'Android arm system image' |
| 221 pattern = re.compile( |
| 222 r'\s*([0-9]+)- ARM EABI v7a System Image, Android API %d.*' % api_level) |
| 223 else: |
| 224 raise Exception('abi option is invalid') |
179 | 225 |
180 UpdateSDK(api_level, 'x86 system image', x86_package_pattern, | 226 UpdateSDK(api_level, package_name, pattern, DOWNLOAD_SYSTEM_IMAGE_TIMEOUT) |
181 DOWNLOAD_SYSTEM_IMAGE_TIMEOUT) | |
182 | 227 |
183 def GetSDKPlatform(api_level=DEFAULT_ANDROID_API_LEVEL): | 228 def GetSDKPlatform(api_level=DEFAULT_ANDROID_API_LEVEL, google=False): |
184 """Update the SDK to include the platform specified. | 229 """Update the SDK to include the platform specified. |
185 | 230 |
186 Args: | 231 Args: |
187 api_level: the Android API level to download | 232 api_level: the Android API level to download |
| 233 google: use Google build system image instead of AOSP build |
188 """ | 234 """ |
189 logging.info('Download SDK Platform directory into sdk directory.') | 235 logging.info('Download SDK Platform directory into sdk directory.') |
190 | 236 |
191 platform_package_pattern = re.compile( | 237 platform_package_pattern = re.compile( |
192 r'\s*([0-9]+)- SDK Platform Android [\.,0-9]+, API %d.*' % api_level) | 238 r'\s*([0-9]+)- SDK Platform Android [\.,0-9]+, API %d.*' % api_level) |
193 | 239 |
194 UpdateSDK(api_level, 'SDK Platform', platform_package_pattern, | 240 UpdateSDK(api_level, 'SDK Platform', platform_package_pattern, |
195 DOWNLOAD_SDK_PLATFORM_TIMEOUT) | 241 DOWNLOAD_SDK_PLATFORM_TIMEOUT) |
196 | 242 |
| 243 if google: |
| 244 google_api_package_pattern = re.compile( |
| 245 r'\s*([0-9]+)- Google APIs, Android API %d.*' % api_level) |
| 246 UpdateSDK(api_level, 'Google APIs', google_api_package_pattern, |
| 247 DOWNLOAD_SDK_PLATFORM_TIMEOUT) |
| 248 |
197 | 249 |
198 def main(argv): | 250 def main(argv): |
199 opt_parser = optparse.OptionParser( | 251 opt_parser = optparse.OptionParser( |
200 description='Install dependencies for running the Android emulator') | 252 description='Install dependencies for running the Android emulator') |
| 253 opt_parser.add_option('--abi', |
| 254 dest='abi', |
| 255 help='The targeted abi for emulator system image', |
| 256 type='string', |
| 257 default=DEFAULT_ABI) |
201 opt_parser.add_option('--api-level', | 258 opt_parser.add_option('--api-level', |
202 dest='api_level', | 259 dest='api_level', |
203 help=('The API level (e.g., 19 for Android 4.4) to ' | 260 help=('The API level (e.g., 19 for Android 4.4) to ' |
204 'ensure is available'), | 261 'ensure is available'), |
205 type='int', | 262 type='int', |
206 default=DEFAULT_ANDROID_API_LEVEL) | 263 default=DEFAULT_ANDROID_API_LEVEL) |
207 opt_parser.add_option('-v', | 264 opt_parser.add_option('-v', |
208 dest='verbosity', | 265 dest='verbosity', |
209 default=1, | 266 default=1, |
210 action='count', | 267 action='count', |
211 help='Verbose level (multiple times for more)') | 268 help='Verbose level (multiple times for more)') |
| 269 opt_parser.add_option('--google', |
| 270 dest='google', |
| 271 action='store_true', |
| 272 default=False, |
| 273 help='Install Google System Image instead of AOSP') |
| 274 |
212 options, _ = opt_parser.parse_args(argv[1:]) | 275 options, _ = opt_parser.parse_args(argv[1:]) |
213 | 276 |
214 run_tests_helper.SetLogLevel(verbose_count=options.verbosity) | 277 run_tests_helper.SetLogLevel(verbose_count=options.verbosity) |
215 | 278 |
216 # Calls below will download emulator SDK and/or system images only if needed. | 279 # Calls below will download emulator SDK and/or system images only if needed. |
217 if CheckSDK(): | 280 if CheckSDK(): |
218 logging.info('android_emulator_sdk/ exists') | 281 logging.info('android_emulator_sdk/ exists') |
219 else: | 282 else: |
220 logging.critical('ERROR: Emulator SDK not installed in %s' | 283 logging.critical('ERROR: Emulator SDK not installed in %s' |
221 , constants.ANDROID_SDK_ROOT) | 284 , constants.ANDROID_SDK_ROOT) |
222 return 1 | 285 return 1 |
223 | 286 |
224 # Check target. The target has to be installed in order to run the emulator. | 287 # Check target. The target has to be installed in order to run the emulator. |
225 if CheckSDKPlatform(options.api_level): | 288 if CheckSDKPlatform(options.api_level, options.google): |
226 logging.info('SDK platform android-%d already present, skipping.', | 289 logging.info('SDK platform %s %s android-%d already present, skipping.', |
| 290 'Google' if options.google else 'AOSP', options.abi, |
227 options.api_level) | 291 options.api_level) |
228 else: | 292 else: |
229 logging.info('SDK platform android-%d not present, installing.', | 293 logging.info('SDK platform %s %s android-%d not present, installing.', |
| 294 'Google' if options.google else 'AOSP', options.abi, |
230 options.api_level) | 295 options.api_level) |
231 GetSDKPlatform(options.api_level) | 296 GetSDKPlatform(options.api_level, options.google) |
232 | 297 |
233 # Download the x86 system image only if needed. | 298 # Download the system image needed |
234 if CheckX86Image(options.api_level): | 299 if CheckSystemImage(options.abi, options.api_level, options.google): |
235 logging.info('x86 image for android-%d already present, skipping.', | 300 logging.info('system image for %s %s android-%d already present, skipping.', |
| 301 'Google' if options.google else 'AOSP', options.abi, |
236 options.api_level) | 302 options.api_level) |
237 else: | 303 else: |
238 GetX86Image(options.api_level) | 304 GetSystemImage(options.abi, options.api_level, options.google) |
239 | 305 |
240 # Make sure KVM packages are installed and enabled. | 306 # Make sure KVM packages are installed and enabled. |
241 if CheckKVM(): | 307 if options.abi == 'x86': |
242 logging.info('KVM already installed and enabled.') | 308 if CheckKVM(): |
243 else: | 309 logging.info('KVM already installed and enabled.') |
244 logging.warning('KVM is not installed or enabled.') | 310 else: |
| 311 logging.warning('KVM is not installed or enabled.') |
245 | 312 |
246 | 313 |
247 if __name__ == '__main__': | 314 if __name__ == '__main__': |
248 sys.exit(main(sys.argv)) | 315 sys.exit(main(sys.argv)) |
OLD | NEW |