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 |