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