Make touch-action apply to double-tap zoom
[chromium-blink-merge.git] / build / android / install_emulator_deps.py
blobfcb09541170c448256c812801728ae32585aac5a
1 #!/usr/bin/env python
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
4 # found in the LICENSE file.
6 """Installs deps for using SDK emulator for testing.
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.
10 """
13 import logging
14 import optparse
15 import os
16 import re
17 import shutil
18 import sys
20 from pylib import cmd_helper
21 from pylib import constants
22 from pylib import pexpect
23 from pylib.utils import run_tests_helper
25 # Android API level
26 DEFAULT_ANDROID_API_LEVEL = constants.ANDROID_SDK_VERSION
28 # From the Android Developer's website.
29 # Keep this up to date; the user can install older API levels as necessary.
30 SDK_BASE_URL = 'http://dl.google.com/android/adt'
31 SDK_ZIP = 'adt-bundle-linux-x86_64-20131030.zip'
33 # Android x86 system image from the Intel website:
34 # http://software.intel.com/en-us/articles/intel-eula-x86-android-4-2-jelly-bean-bin
35 # These don't exist prior to Android-15.
36 # As of 08 Nov 2013, Android-19 is not yet available either.
37 X86_IMG_URLS = {
38 15: 'http://download-software.intel.com/sites/landingpage/android/sysimg_x86-15_r01.zip',
39 16: 'http://download-software.intel.com/sites/landingpage/android/sysimg_x86-16_r01.zip',
40 17: 'http://download-software.intel.com/sites/landingpage/android/sysimg_x86-17_r01.zip',
41 18: 'http://download-software.intel.com/sites/landingpage/android/sysimg_x86-18_r01.zip',
42 19: 'http://download-software.intel.com/sites/landingpage/android/sysimg_x86-19_r01.zip'}
44 def CheckSDK():
45 """Check if SDK is already installed.
47 Returns:
48 True if the emulator SDK directory (src/android_emulator_sdk/) exists.
49 """
50 return os.path.exists(constants.EMULATOR_SDK_ROOT)
53 def CheckSDKPlatform(api_level=DEFAULT_ANDROID_API_LEVEL):
54 """Check if the "SDK Platform" for the specified API level is installed.
55 This is necessary in order for the emulator to run when the target
56 is specified.
58 Args:
59 api_level: the Android API level to check; defaults to the latest API.
61 Returns:
62 True if the platform is already installed.
63 """
64 android_binary = os.path.join(constants.EMULATOR_SDK_ROOT,
65 'sdk', 'tools', 'android')
66 pattern = re.compile('id: [0-9]+ or "android-%d"' % api_level)
67 try:
68 exit_code, stdout = cmd_helper.GetCmdStatusAndOutput(
69 [android_binary, 'list'])
70 if exit_code != 0:
71 raise Exception('\'android list\' command failed')
72 for line in stdout.split('\n'):
73 if pattern.match(line):
74 return True
75 return False
76 except OSError:
77 logging.exception('Unable to execute \'android list\'')
78 return False
81 def CheckX86Image(api_level=DEFAULT_ANDROID_API_LEVEL):
82 """Check if Android system images have been installed.
84 Args:
85 api_level: the Android API level to check for; defaults to the latest API.
87 Returns:
88 True if sdk/system-images/android-<api_level>/x86 exists inside
89 EMULATOR_SDK_ROOT.
90 """
91 api_target = 'android-%d' % api_level
92 return os.path.exists(os.path.join(constants.EMULATOR_SDK_ROOT,
93 'sdk', 'system-images',
94 api_target, 'x86'))
97 def CheckKVM():
98 """Quickly check whether KVM is enabled.
100 Returns:
101 True iff /dev/kvm exists (Linux only).
103 return os.path.exists('/dev/kvm')
106 def RunKvmOk():
107 """Run kvm-ok as root to check that KVM is properly enabled after installation
108 of the required packages.
110 Returns:
111 True iff KVM is enabled (/dev/kvm exists). On failure, returns False
112 but also print detailed information explaining why KVM isn't enabled
113 (e.g. CPU doesn't support it, or BIOS disabled it).
115 try:
116 # Note: kvm-ok is in /usr/sbin, so always use 'sudo' to run it.
117 return not cmd_helper.RunCmd(['sudo', 'kvm-ok'])
118 except OSError:
119 logging.info('kvm-ok not installed')
120 return False
123 def GetSDK():
124 """Download the SDK and unzip it into EMULATOR_SDK_ROOT."""
125 logging.info('Download Android SDK.')
126 sdk_url = '%s/%s' % (SDK_BASE_URL, SDK_ZIP)
127 try:
128 cmd_helper.RunCmd(['curl', '-o', '/tmp/sdk.zip', sdk_url])
129 print 'curled unzipping...'
130 rc = cmd_helper.RunCmd(['unzip', '-o', '/tmp/sdk.zip', '-d', '/tmp/'])
131 if rc:
132 raise Exception('ERROR: could not download/unzip Android SDK.')
133 # Get the name of the sub-directory that everything will be extracted to.
134 dirname, _ = os.path.splitext(SDK_ZIP)
135 zip_dir = '/tmp/%s' % dirname
136 # Move the extracted directory to EMULATOR_SDK_ROOT
137 shutil.move(zip_dir, constants.EMULATOR_SDK_ROOT)
138 finally:
139 os.unlink('/tmp/sdk.zip')
142 def InstallKVM():
143 """Installs KVM packages."""
144 rc = cmd_helper.RunCmd(['sudo', 'apt-get', 'install', 'kvm'])
145 if rc:
146 logging.critical('ERROR: Did not install KVM. Make sure hardware '
147 'virtualization is enabled in BIOS (i.e. Intel VT-x or '
148 'AMD SVM).')
149 # TODO(navabi): Use modprobe kvm-amd on AMD processors.
150 rc = cmd_helper.RunCmd(['sudo', 'modprobe', 'kvm-intel'])
151 if rc:
152 logging.critical('ERROR: Did not add KVM module to Linux Kernel. Make sure '
153 'hardware virtualization is enabled in BIOS.')
154 # Now check to ensure KVM acceleration can be used.
155 if not RunKvmOk():
156 logging.critical('ERROR: Can not use KVM acceleration. Make sure hardware '
157 'virtualization is enabled in BIOS (i.e. Intel VT-x or '
158 'AMD SVM).')
161 def GetX86Image(api_level=DEFAULT_ANDROID_API_LEVEL):
162 """Download x86 system image from Intel's website.
164 Args:
165 api_level: the Android API level to download for.
167 logging.info('Download x86 system image directory into sdk directory.')
168 # TODO(andrewhayden): Use python tempfile lib instead
169 temp_file = '/tmp/x86_img_android-%d.zip' % api_level
170 if api_level not in X86_IMG_URLS:
171 raise Exception('ERROR: no URL known for x86 image for android-%s' %
172 api_level)
173 try:
174 cmd_helper.RunCmd(['curl', '-o', temp_file, X86_IMG_URLS[api_level]])
175 rc = cmd_helper.RunCmd(['unzip', '-o', temp_file, '-d', '/tmp/'])
176 if rc:
177 raise Exception('ERROR: Could not download/unzip image zip.')
178 api_target = 'android-%d' % api_level
179 sys_imgs = os.path.join(constants.EMULATOR_SDK_ROOT, 'sdk',
180 'system-images', api_target, 'x86')
181 logging.info('Deploying system image to %s' % sys_imgs)
182 shutil.move('/tmp/x86', sys_imgs)
183 finally:
184 os.unlink(temp_file)
187 def GetSDKPlatform(api_level=DEFAULT_ANDROID_API_LEVEL):
188 """Update the SDK to include the platform specified.
190 Args:
191 api_level: the Android API level to download
193 android_binary = os.path.join(constants.EMULATOR_SDK_ROOT,
194 'sdk', 'tools', 'android')
195 pattern = re.compile('\s*([0-9]+)- SDK Platform Android [\.,0-9]+, API %d.*' %
196 api_level)
197 # Example:
198 # 2- SDK Platform Android 4.3, API 18, revision 2
199 exit_code, stdout = cmd_helper.GetCmdStatusAndOutput(
200 [android_binary, 'list', 'sdk'])
201 if exit_code != 0:
202 raise Exception('\'android list sdk\' command return %d' % exit_code)
203 for line in stdout.split('\n'):
204 match = pattern.match(line)
205 if match:
206 index = match.group(1)
207 print('package %s corresponds to platform level %d' % (index, api_level))
208 # update sdk --no-ui --filter $INDEX
209 update_command = [android_binary,
210 'update', 'sdk', '--no-ui', '--filter', index]
211 update_command_str = ' '.join(update_command)
212 logging.info('running update command: %s' % update_command_str)
213 update_process = pexpect.spawn(update_command_str)
214 # TODO(andrewhayden): Do we need to bug the user about this?
215 if update_process.expect('Do you accept the license') != 0:
216 raise Exception('License agreement check failed')
217 update_process.sendline('y')
218 if update_process.expect('Done. 1 package installed.') == 0:
219 print('Successfully installed platform for API level %d' % api_level)
220 return
221 else:
222 raise Exception('Failed to install platform update')
223 raise Exception('Could not find android-%d update for the SDK!' % api_level)
226 def main(argv):
227 opt_parser = optparse.OptionParser(
228 description='Install dependencies for running the Android emulator')
229 opt_parser.add_option('--api-level', dest='api_level',
230 help='The API level (e.g., 19 for Android 4.4) to ensure is available',
231 type='int', default=DEFAULT_ANDROID_API_LEVEL)
232 opt_parser.add_option('-v', dest='verbose', action='store_true',
233 help='enable verbose logging')
234 options, _ = opt_parser.parse_args(argv[1:])
236 # run_tests_helper will set logging to INFO or DEBUG
237 # We achieve verbose output by configuring it with 2 (==DEBUG)
238 verbosity = 1
239 if (options.verbose):
240 verbosity = 2
241 logging.basicConfig(level=logging.INFO,
242 format='# %(asctime)-15s: %(message)s')
243 run_tests_helper.SetLogLevel(verbose_count=verbosity)
245 # Calls below will download emulator SDK and/or system images only if needed.
246 if CheckSDK():
247 logging.info('android_emulator_sdk/ already exists, skipping download.')
248 else:
249 GetSDK()
251 # Check target. The target has to be installed in order to run the emulator.
252 if CheckSDKPlatform(options.api_level):
253 logging.info('SDK platform android-%d already present, skipping.' %
254 options.api_level)
255 else:
256 logging.info('SDK platform android-%d not present, installing.' %
257 options.api_level)
258 GetSDKPlatform(options.api_level)
260 # Download the x86 system image only if needed.
261 if CheckX86Image(options.api_level):
262 logging.info('x86 image for android-%d already present, skipping.' %
263 options.api_level)
264 else:
265 GetX86Image(options.api_level)
267 # Make sure KVM packages are installed and enabled.
268 if CheckKVM():
269 logging.info('KVM already installed and enabled.')
270 else:
271 InstallKVM()
274 if __name__ == '__main__':
275 sys.exit(main(sys.argv))