Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(499)

Side by Side Diff: build/android/install_emulator_deps.py

Issue 1341503002: fix emulator.py by using Android SDK in third_party/android_tools instead of downloading adt (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « build/android/avd.py ('k') | build/android/pylib/constants/__init__.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 shutil
18 import sys 17 import sys
19 18
20 from devil.utils import cmd_helper 19 from devil.utils import cmd_helper
21 from devil.utils import run_tests_helper 20 from devil.utils import run_tests_helper
22 from pylib import constants 21 from pylib import constants
23 from pylib import pexpect 22 from pylib import pexpect
24 23
25 # Android API level 24 # Android API level
26 DEFAULT_ANDROID_API_LEVEL = constants.ANDROID_SDK_VERSION 25 DEFAULT_ANDROID_API_LEVEL = constants.ANDROID_SDK_VERSION
mikecase (-- gone --) 2015/09/15 22:26:55 nit: If you want you can go ahead and replace DEFA
27 26
28 # From the Android Developer's website. 27 # From the Android Developer's website.
29 # Keep this up to date; the user can install older API levels as necessary. 28 # Keep this up to date; the user can install older API levels as necessary.
30 SDK_BASE_URL = 'http://dl.google.com/android/adt' 29 SDK_BASE_URL = 'http://dl.google.com/android/adt'
31 SDK_ZIP = 'adt-bundle-linux-x86_64-20131030.zip' 30 SDK_ZIP = 'adt-bundle-linux-x86_64-20131030.zip'
32 31
33 # pylint: disable=line-too-long 32 # pylint: disable=line-too-long
34 # Android x86 system image from the Intel website: 33 # Android x86 system image from the Intel website:
35 # http://software.intel.com/en-us/articles/intel-eula-x86-android-4-2-jelly-bean -bin 34 # http://software.intel.com/en-us/articles/intel-eula-x86-android-4-2-jelly-bean -bin
36 # These don't exist prior to Android-15. 35 # These don't exist prior to Android-15.
37 # As of 08 Nov 2013, Android-19 is not yet available either. 36 # As of 08 Nov 2013, Android-19 is not yet available either.
38 X86_IMG_URLS = { 37 X86_IMG_URLS = {
39 15: 'https://software.intel.com/sites/landingpage/android/sysimg_x86-15_r01.zi p', 38 15: 'https://software.intel.com/sites/landingpage/android/sysimg_x86-15_r01.zi p',
40 16: 'https://software.intel.com/sites/landingpage/android/sysimg_x86-16_r01.zi p', 39 16: 'https://software.intel.com/sites/landingpage/android/sysimg_x86-16_r01.zi p',
41 17: 'https://software.intel.com/sites/landingpage/android/sysimg_x86-17_r01.zi p', 40 17: 'https://software.intel.com/sites/landingpage/android/sysimg_x86-17_r01.zi p',
42 18: 'https://software.intel.com/sites/landingpage/android/sysimg_x86-18_r01.zi p', 41 18: 'https://software.intel.com/sites/landingpage/android/sysimg_x86-18_r01.zi p',
43 19: 'https://software.intel.com/sites/landingpage/android/sysimg_x86-19_r01.zi p'} 42 19: 'https://software.intel.com/sites/landingpage/android/sysimg_x86-19_r01.zi p'}
44 #pylint: enable=line-too-long 43 #pylint: enable=line-too-long
45 44
46 def CheckSDK(): 45 def CheckSDK():
47 """Check if SDK is already installed. 46 """Check if SDK is already installed.
48 47
49 Returns: 48 Returns:
50 True if the emulator SDK directory (src/android_emulator_sdk/) exists. 49 True if the emulator SDK directory (src/android_emulator_sdk/) exists.
51 """ 50 """
52 return os.path.exists(constants.EMULATOR_SDK_ROOT) 51 return os.path.exists(constants.ANDROID_SDK_ROOT)
53 52
54 53
55 def CheckSDKPlatform(api_level=DEFAULT_ANDROID_API_LEVEL): 54 def CheckSDKPlatform(api_level=DEFAULT_ANDROID_API_LEVEL):
56 """Check if the "SDK Platform" for the specified API level is installed. 55 """Check if the "SDK Platform" for the specified API level is installed.
57 This is necessary in order for the emulator to run when the target 56 This is necessary in order for the emulator to run when the target
58 is specified. 57 is specified.
59 58
60 Args: 59 Args:
61 api_level: the Android API level to check; defaults to the latest API. 60 api_level: the Android API level to check; defaults to the latest API.
62 61
63 Returns: 62 Returns:
64 True if the platform is already installed. 63 True if the platform is already installed.
65 """ 64 """
66 android_binary = os.path.join(constants.EMULATOR_SDK_ROOT, 65 android_binary = os.path.join(constants.ANDROID_SDK_ROOT, 'tools', 'android')
67 'sdk', 'tools', 'android')
68 pattern = re.compile('id: [0-9]+ or "android-%d"' % api_level) 66 pattern = re.compile('id: [0-9]+ or "android-%d"' % api_level)
69 try: 67 try:
70 exit_code, stdout = cmd_helper.GetCmdStatusAndOutput( 68 exit_code, stdout = cmd_helper.GetCmdStatusAndOutput(
71 [android_binary, 'list']) 69 [android_binary, 'list'])
72 if exit_code != 0: 70 if exit_code != 0:
73 raise Exception('\'android list\' command failed') 71 raise Exception('\'android list\' command failed')
74 for line in stdout.split('\n'): 72 for line in stdout.split('\n'):
75 if pattern.match(line): 73 if pattern.match(line):
76 return True 74 return True
77 return False 75 return False
78 except OSError: 76 except OSError:
79 logging.exception('Unable to execute \'android list\'') 77 logging.exception('Unable to execute \'android list\'')
80 return False 78 return False
81 79
82 80
83 def CheckX86Image(api_level=DEFAULT_ANDROID_API_LEVEL): 81 def CheckX86Image(api_level=DEFAULT_ANDROID_API_LEVEL):
84 """Check if Android system images have been installed. 82 """Check if Android system images have been installed.
85 83
86 Args: 84 Args:
87 api_level: the Android API level to check for; defaults to the latest API. 85 api_level: the Android API level to check for; defaults to the latest API.
88 86
89 Returns: 87 Returns:
90 True if sdk/system-images/android-<api_level>/x86 exists inside 88 True if sdk/system-images/android-<api_level>/default/x86 exists inside
91 EMULATOR_SDK_ROOT. 89 ANDROID_SDK_ROOT.
92 """ 90 """
93 api_target = 'android-%d' % api_level 91 api_target = 'android-%d' % api_level
94 return os.path.exists(os.path.join(constants.EMULATOR_SDK_ROOT, 92 return os.path.exists(os.path.join(constants.ANDROID_SDK_ROOT,
95 'sdk', 'system-images', 93 'system-images', api_target, 'default',
96 api_target, 'x86')) 94 'x86'))
97 95
98 96
99 def CheckKVM(): 97 def CheckKVM():
100 """Quickly check whether KVM is enabled. 98 """Quickly check whether KVM is enabled.
101 99
102 Returns: 100 Returns:
103 True iff /dev/kvm exists (Linux only). 101 True iff /dev/kvm exists (Linux only).
104 """ 102 """
105 return os.path.exists('/dev/kvm') 103 return os.path.exists('/dev/kvm')
106 104
107 105
108 def RunKvmOk(): 106 def RunKvmOk():
109 """Run kvm-ok as root to check that KVM is properly enabled after installation 107 """Run kvm-ok as root to check that KVM is properly enabled after installation
110 of the required packages. 108 of the required packages.
111 109
112 Returns: 110 Returns:
113 True iff KVM is enabled (/dev/kvm exists). On failure, returns False 111 True iff KVM is enabled (/dev/kvm exists). On failure, returns False
114 but also print detailed information explaining why KVM isn't enabled 112 but also print detailed information explaining why KVM isn't enabled
115 (e.g. CPU doesn't support it, or BIOS disabled it). 113 (e.g. CPU doesn't support it, or BIOS disabled it).
116 """ 114 """
117 try: 115 try:
118 # Note: kvm-ok is in /usr/sbin, so always use 'sudo' to run it. 116 # Note: kvm-ok is in /usr/sbin, so always use 'sudo' to run it.
119 return not cmd_helper.RunCmd(['sudo', 'kvm-ok']) 117 return not cmd_helper.RunCmd(['sudo', 'kvm-ok'])
120 except OSError: 118 except OSError:
121 logging.info('kvm-ok not installed') 119 logging.info('kvm-ok not installed')
122 return False 120 return False
123 121
124 122
125 def GetSDK():
126 """Download the SDK and unzip it into EMULATOR_SDK_ROOT."""
127 logging.info('Download Android SDK.')
128 sdk_url = '%s/%s' % (SDK_BASE_URL, SDK_ZIP)
129 try:
130 cmd_helper.RunCmd(['curl', '-o', '/tmp/sdk.zip', sdk_url])
131 print 'curled unzipping...'
132 rc = cmd_helper.RunCmd(['unzip', '-o', '/tmp/sdk.zip', '-d', '/tmp/'])
133 if rc:
134 raise Exception('ERROR: could not download/unzip Android SDK.')
135 # Get the name of the sub-directory that everything will be extracted to.
136 dirname, _ = os.path.splitext(SDK_ZIP)
137 zip_dir = '/tmp/%s' % dirname
138 # Move the extracted directory to EMULATOR_SDK_ROOT
139 shutil.move(zip_dir, constants.EMULATOR_SDK_ROOT)
140 finally:
141 os.unlink('/tmp/sdk.zip')
142
143
144 def InstallKVM(): 123 def InstallKVM():
145 """Installs KVM packages.""" 124 """Installs KVM packages."""
146 rc = cmd_helper.RunCmd(['sudo', 'apt-get', 'install', 'kvm']) 125 rc = cmd_helper.RunCmd(['sudo', 'apt-get', 'install', 'kvm'])
147 if rc: 126 if rc:
148 logging.critical('ERROR: Did not install KVM. Make sure hardware ' 127 logging.critical('ERROR: Did not install KVM. Make sure hardware '
149 'virtualization is enabled in BIOS (i.e. Intel VT-x or ' 128 'virtualization is enabled in BIOS (i.e. Intel VT-x or '
150 'AMD SVM).') 129 'AMD SVM).')
151 # TODO(navabi): Use modprobe kvm-amd on AMD processors. 130 # TODO(navabi): Use modprobe kvm-amd on AMD processors.
152 rc = cmd_helper.RunCmd(['sudo', 'modprobe', 'kvm-intel']) 131 rc = cmd_helper.RunCmd(['sudo', 'modprobe', 'kvm-intel'])
153 if rc: 132 if rc:
154 logging.critical('ERROR: Did not add KVM module to Linux Kernel. Make sure ' 133 logging.critical('ERROR: Did not add KVM module to Linux Kernel. Make sure '
155 'hardware virtualization is enabled in BIOS.') 134 'hardware virtualization is enabled in BIOS.')
156 # Now check to ensure KVM acceleration can be used. 135 # Now check to ensure KVM acceleration can be used.
157 if not RunKvmOk(): 136 if not RunKvmOk():
158 logging.critical('ERROR: Can not use KVM acceleration. Make sure hardware ' 137 logging.critical('ERROR: Can not use KVM acceleration. Make sure hardware '
159 'virtualization is enabled in BIOS (i.e. Intel VT-x or ' 138 'virtualization is enabled in BIOS (i.e. Intel VT-x or '
160 'AMD SVM).') 139 'AMD SVM).')
161 140
162 141
142 def UpdateSDK(api_level, package_name, package_pattern, timeout=30):
mikecase (-- gone --) 2015/09/15 22:26:55 I would factor out this 30 to the top of the modul
Yoland Yan(Google) 2015/09/20 21:57:37 Done
143 '''This function update SDK with a filter index.
144
145 Args:
146 api_level: the Android API level to download for.
147 package_pattern: the mattern to match the filter index from
mikecase (-- gone --) 2015/09/15 22:26:55 missing description of "package_name" parameter
Yoland Yan(Google) 2015/09/20 21:57:37 Done
148 timeout: the amount of time wait for update command
149 '''
150 android_binary = os.path.join(constants.ANDROID_SDK_ROOT, 'tools', 'android')
151
152 list_sdk_repo_command = [android_binary, 'list', 'sdk', '--all']
153
154 exit_code, stdout = cmd_helper.GetCmdStatusAndOutput(list_sdk_repo_command)
155
156 if exit_code != 0:
157 raise Exception('\'android list sdk --all\' command return %d' % exit_code)
158
159 for line in stdout.split('\n'):
160 match = package_pattern.match(line)
161 if match:
162 index = match.group(1)
163 logging.info('package %s corresponds to %s with api level %d'
164 % (index, package_name, api_level))
165 update_command = [android_binary, 'update', 'sdk', '--no-ui', '--all',
166 '--filter', index]
167 update_command_str = ' '.join(update_command)
168 logging.info('running update command: %s', update_command_str)
169 update_process = pexpect.spawn(update_command_str)
170
171 if update_process.expect('Do you accept the license') != 0:
172 raise Exception('License agreement check failed')
173 update_process.sendline('y')
174 if update_process.expect(
175 'Done. 1 package installed.', timeout=timeout) == 0:
176 logging.info('Successfully installed %s for API level %d'
177 % (package_name, api_level))
mikecase (-- gone --) 2015/09/15 22:26:55 nit: single extra space before the %
Yoland Yan(Google) 2015/09/20 21:57:36 Done
178 return
179 else:
180 raise Exception('Failed to install platform update')
181 raise Exception('Could not find android-%d update for the SDK!' % api_level)
182
163 def GetX86Image(api_level=DEFAULT_ANDROID_API_LEVEL): 183 def GetX86Image(api_level=DEFAULT_ANDROID_API_LEVEL):
164 """Download x86 system image from Intel's website. 184 """Download x86 system image from Intel's website.
165 185
166 Args: 186 Args:
167 api_level: the Android API level to download for. 187 api_level: the Android API level to download for.
168 """ 188 """
169 logging.info('Download x86 system image directory into sdk directory.') 189 logging.info('Download x86 system image directory into sdk directory.')
170 # TODO(andrewhayden): Use python tempfile lib instead
171 temp_file = '/tmp/x86_img_android-%d.zip' % api_level
172 if api_level not in X86_IMG_URLS:
173 raise Exception('ERROR: no URL known for x86 image for android-%s' %
174 api_level)
175 try:
176 cmd_helper.RunCmd(['curl', '-o', temp_file, X86_IMG_URLS[api_level]])
177 rc = cmd_helper.RunCmd(['unzip', '-o', temp_file, '-d', '/tmp/'])
178 if rc:
179 raise Exception('ERROR: Could not download/unzip image zip.')
180 api_target = 'android-%d' % api_level
181 sys_imgs = os.path.join(constants.EMULATOR_SDK_ROOT, 'sdk',
182 'system-images', api_target, 'x86')
183 logging.info('Deploying system image to %s', sys_imgs)
184 shutil.move('/tmp/x86', sys_imgs)
185 finally:
186 os.unlink(temp_file)
187 190
191 x86_package_pattern = re.compile(
192 r'\s*([0-9]+)- Intel x86 Atom System Image, Android API %d.*' % api_level)
193
194 UpdateSDK(api_level, 'x86 system image', x86_package_pattern, 60)
mikecase (-- gone --) 2015/09/15 22:26:55 I would factor out this 60 to the top of the modul
Yoland Yan(Google) 2015/09/20 21:57:37 Done
188 195
189 def GetSDKPlatform(api_level=DEFAULT_ANDROID_API_LEVEL): 196 def GetSDKPlatform(api_level=DEFAULT_ANDROID_API_LEVEL):
190 """Update the SDK to include the platform specified. 197 """Update the SDK to include the platform specified.
191 198
192 Args: 199 Args:
193 api_level: the Android API level to download 200 api_level: the Android API level to download
194 """ 201 """
195 android_binary = os.path.join(constants.EMULATOR_SDK_ROOT, 202 logging.info('Download SDK Platform directory into sdk directory.')
196 'sdk', 'tools', 'android') 203
197 pattern = re.compile( 204 platform_package_pattern = re.compile(
198 r'\s*([0-9]+)- SDK Platform Android [\.,0-9]+, API %d.*' % api_level) 205 r'\s*([0-9]+)- SDK Platform Android [\.,0-9]+, API %d.*' % api_level)
199 # Example: 206
200 # 2- SDK Platform Android 4.3, API 18, revision 2 207 UpdateSDK(api_level, 'SDK Platform', platform_package_pattern)
201 exit_code, stdout = cmd_helper.GetCmdStatusAndOutput(
202 [android_binary, 'list', 'sdk'])
203 if exit_code != 0:
204 raise Exception('\'android list sdk\' command return %d' % exit_code)
205 for line in stdout.split('\n'):
206 match = pattern.match(line)
207 if match:
208 index = match.group(1)
209 print 'package %s corresponds to platform level %d' % (index, api_level)
210 # update sdk --no-ui --filter $INDEX
211 update_command = [android_binary,
212 'update', 'sdk', '--no-ui', '--filter', index]
213 update_command_str = ' '.join(update_command)
214 logging.info('running update command: %s', update_command_str)
215 update_process = pexpect.spawn(update_command_str)
216 # TODO(andrewhayden): Do we need to bug the user about this?
217 if update_process.expect('Do you accept the license') != 0:
218 raise Exception('License agreement check failed')
219 update_process.sendline('y')
220 if update_process.expect('Done. 1 package installed.') == 0:
221 print 'Successfully installed platform for API level %d' % api_level
222 return
223 else:
224 raise Exception('Failed to install platform update')
225 raise Exception('Could not find android-%d update for the SDK!' % api_level)
226 208
227 209
228 def main(argv): 210 def main(argv):
229 opt_parser = optparse.OptionParser( 211 opt_parser = optparse.OptionParser(
230 description='Install dependencies for running the Android emulator') 212 description='Install dependencies for running the Android emulator')
231 opt_parser.add_option('--api-level', dest='api_level', 213 opt_parser.add_option('--api-level', dest='api_level',
232 help='The API level (e.g., 19 for Android 4.4) to ensure is available', 214 help='The API level (e.g., 19 for Android 4.4) to ensure is available',
233 type='int', default=DEFAULT_ANDROID_API_LEVEL) 215 type='int', default=DEFAULT_ANDROID_API_LEVEL)
234 opt_parser.add_option('-v', dest='verbose', action='store_true', 216 opt_parser.add_option('-v', dest='verbose', action='store_true',
235 help='enable verbose logging') 217 help='enable verbose logging')
236 options, _ = opt_parser.parse_args(argv[1:]) 218 options, _ = opt_parser.parse_args(argv[1:])
237 219
238 # run_tests_helper will set logging to INFO or DEBUG 220 # run_tests_helper will set logging to INFO or DEBUG
239 # We achieve verbose output by configuring it with 2 (==DEBUG) 221 # We achieve verbose output by configuring it with 2 (==DEBUG)
240 verbosity = 1 222 verbosity = 1
241 if options.verbose: 223 if options.verbose:
242 verbosity = 2 224 verbosity = 2
243 logging.basicConfig(level=logging.INFO, 225 logging.basicConfig(level=logging.INFO,
244 format='# %(asctime)-15s: %(message)s') 226 format='# %(asctime)-15s: %(message)s')
mikecase (-- gone --) 2015/09/15 22:26:55 nit: Consider making this logging setup simpler.
245 run_tests_helper.SetLogLevel(verbose_count=verbosity) 227 run_tests_helper.SetLogLevel(verbose_count=verbosity)
246 228
247 # Calls below will download emulator SDK and/or system images only if needed. 229 # Calls below will download emulator SDK and/or system images only if needed.
248 if CheckSDK(): 230 if CheckSDK():
249 logging.info('android_emulator_sdk/ already exists, skipping download.') 231 logging.info('android_emulator_sdk/ already exists, skipping download.')
250 else: 232 else:
251 GetSDK() 233 logging.critical('ERROR: Emulator SDK not installed in %s'
234 % constants.ANDROID_SDK_ROOT)
235 return 1
252 236
253 # Check target. The target has to be installed in order to run the emulator. 237 # Check target. The target has to be installed in order to run the emulator.
254 if CheckSDKPlatform(options.api_level): 238 if CheckSDKPlatform(options.api_level):
255 logging.info('SDK platform android-%d already present, skipping.', 239 logging.info('SDK platform android-%d already present, skipping.',
256 options.api_level) 240 options.api_level)
257 else: 241 else:
258 logging.info('SDK platform android-%d not present, installing.', 242 logging.info('SDK platform android-%d not present, installing.',
259 options.api_level) 243 options.api_level)
260 GetSDKPlatform(options.api_level) 244 GetSDKPlatform(options.api_level)
261 245
262 # Download the x86 system image only if needed. 246 # Download the x86 system image only if needed.
263 if CheckX86Image(options.api_level): 247 if CheckX86Image(options.api_level):
264 logging.info('x86 image for android-%d already present, skipping.', 248 logging.info('x86 image for android-%d already present, skipping.',
265 options.api_level) 249 options.api_level)
266 else: 250 else:
267 GetX86Image(options.api_level) 251 GetX86Image(options.api_level)
268 252
269 # Make sure KVM packages are installed and enabled. 253 # Make sure KVM packages are installed and enabled.
270 if CheckKVM(): 254 if CheckKVM():
271 logging.info('KVM already installed and enabled.') 255 logging.info('KVM already installed and enabled.')
272 else: 256 else:
273 InstallKVM() 257 InstallKVM()
274 258
275 259
276 if __name__ == '__main__': 260 if __name__ == '__main__':
277 sys.exit(main(sys.argv)) 261 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « build/android/avd.py ('k') | build/android/pylib/constants/__init__.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698