1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#!/usr/bin/env python
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# Copyright (c) 2013 The Chromium Authors. All rights reserved.
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# found in the LICENSE file.
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)"""Installs deps for using SDK emulator for testing.
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)The script will download the SDK and system images, if they are not present, and
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)install and enable KVM, if virtualization has been enabled in the BIOS.
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)"""
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import logging
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import optparse
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import os
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import re
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import shutil
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import sys
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)from pylib import cmd_helper
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)from pylib import constants
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)from pylib import pexpect
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)from pylib.utils import run_tests_helper
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# Android API level
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)DEFAULT_ANDROID_API_LEVEL = constants.ANDROID_SDK_VERSION
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# From the Android Developer's website.
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# Keep this up to date; the user can install older API levels as necessary.
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)SDK_BASE_URL = 'http://dl.google.com/android/adt'
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)SDK_ZIP = 'adt-bundle-linux-x86_64-20131030.zip'
32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
33effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch# pylint: disable=C0301
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# Android x86 system image from the Intel website:
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# http://software.intel.com/en-us/articles/intel-eula-x86-android-4-2-jelly-bean-bin
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# These don't exist prior to Android-15.
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# As of 08 Nov 2013, Android-19 is not yet available either.
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)X86_IMG_URLS = {
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  15: 'https://software.intel.com/sites/landingpage/android/sysimg_x86-15_r01.zip',
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  16: 'https://software.intel.com/sites/landingpage/android/sysimg_x86-16_r01.zip',
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  17: 'https://software.intel.com/sites/landingpage/android/sysimg_x86-17_r01.zip',
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  18: 'https://software.intel.com/sites/landingpage/android/sysimg_x86-18_r01.zip',
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  19: 'https://software.intel.com/sites/landingpage/android/sysimg_x86-19_r01.zip'}
44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#pylint: enable=C0301
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def CheckSDK():
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  """Check if SDK is already installed.
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Returns:
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    True if the emulator SDK directory (src/android_emulator_sdk/) exists.
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  """
524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return os.path.exists(constants.EMULATOR_SDK_ROOT)
53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)def CheckSDKPlatform(api_level=DEFAULT_ANDROID_API_LEVEL):
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  """Check if the "SDK Platform" for the specified API level is installed.
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     This is necessary in order for the emulator to run when the target
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     is specified.
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Args:
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    api_level: the Android API level to check; defaults to the latest API.
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Returns:
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    True if the platform is already installed.
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  """
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  android_binary = os.path.join(constants.EMULATOR_SDK_ROOT,
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                'sdk', 'tools', 'android')
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pattern = re.compile('id: [0-9]+ or "android-%d"' % api_level)
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  try:
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    exit_code, stdout = cmd_helper.GetCmdStatusAndOutput(
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        [android_binary, 'list'])
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if exit_code != 0:
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      raise Exception('\'android list\' command failed')
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for line in stdout.split('\n'):
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if pattern.match(line):
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return True
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return False
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  except OSError:
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    logging.exception('Unable to execute \'android list\'')
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return False
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)def CheckX86Image(api_level=DEFAULT_ANDROID_API_LEVEL):
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  """Check if Android system images have been installed.
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Args:
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    api_level: the Android API level to check for; defaults to the latest API.
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Returns:
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    True if sdk/system-images/android-<api_level>/x86 exists inside
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    EMULATOR_SDK_ROOT.
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  """
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  api_target = 'android-%d' % api_level
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return os.path.exists(os.path.join(constants.EMULATOR_SDK_ROOT,
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                     'sdk', 'system-images',
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                     api_target, 'x86'))
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def CheckKVM():
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  """Quickly check whether KVM is enabled.
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Returns:
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    True iff /dev/kvm exists (Linux only).
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  """
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return os.path.exists('/dev/kvm')
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def RunKvmOk():
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  """Run kvm-ok as root to check that KVM is properly enabled after installation
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     of the required packages.
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Returns:
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    True iff KVM is enabled (/dev/kvm exists). On failure, returns False
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    but also print detailed information explaining why KVM isn't enabled
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    (e.g. CPU doesn't support it, or BIOS disabled it).
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  """
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  try:
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # Note: kvm-ok is in /usr/sbin, so always use 'sudo' to run it.
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return not cmd_helper.RunCmd(['sudo', 'kvm-ok'])
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  except OSError:
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    logging.info('kvm-ok not installed')
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return False
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def GetSDK():
1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  """Download the SDK and unzip it into EMULATOR_SDK_ROOT."""
1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  logging.info('Download Android SDK.')
1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  sdk_url = '%s/%s' % (SDK_BASE_URL, SDK_ZIP)
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  try:
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    cmd_helper.RunCmd(['curl', '-o', '/tmp/sdk.zip', sdk_url])
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    print 'curled unzipping...'
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    rc = cmd_helper.RunCmd(['unzip', '-o', '/tmp/sdk.zip', '-d', '/tmp/'])
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if rc:
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      raise Exception('ERROR: could not download/unzip Android SDK.')
1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    # Get the name of the sub-directory that everything will be extracted to.
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    dirname, _ = os.path.splitext(SDK_ZIP)
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    zip_dir = '/tmp/%s' % dirname
1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    # Move the extracted directory to EMULATOR_SDK_ROOT
1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    shutil.move(zip_dir, constants.EMULATOR_SDK_ROOT)
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  finally:
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    os.unlink('/tmp/sdk.zip')
1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def InstallKVM():
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  """Installs KVM packages."""
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rc = cmd_helper.RunCmd(['sudo', 'apt-get', 'install', 'kvm'])
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if rc:
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    logging.critical('ERROR: Did not install KVM. Make sure hardware '
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     'virtualization is enabled in BIOS (i.e. Intel VT-x or '
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     'AMD SVM).')
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  # TODO(navabi): Use modprobe kvm-amd on AMD processors.
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rc = cmd_helper.RunCmd(['sudo', 'modprobe', 'kvm-intel'])
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if rc:
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    logging.critical('ERROR: Did not add KVM module to Linux Kernel. Make sure '
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     'hardware virtualization is enabled in BIOS.')
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  # Now check to ensure KVM acceleration can be used.
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if not RunKvmOk():
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    logging.critical('ERROR: Can not use KVM acceleration. Make sure hardware '
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     'virtualization is enabled in BIOS (i.e. Intel VT-x or '
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     'AMD SVM).')
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)def GetX86Image(api_level=DEFAULT_ANDROID_API_LEVEL):
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  """Download x86 system image from Intel's website.
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Args:
167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    api_level: the Android API level to download for.
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  """
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  logging.info('Download x86 system image directory into sdk directory.')
170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  # TODO(andrewhayden): Use python tempfile lib instead
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  temp_file = '/tmp/x86_img_android-%d.zip' % api_level
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if api_level not in X86_IMG_URLS:
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    raise Exception('ERROR: no URL known for x86 image for android-%s' %
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                    api_level)
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  try:
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    cmd_helper.RunCmd(['curl', '-o', temp_file, X86_IMG_URLS[api_level]])
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    rc = cmd_helper.RunCmd(['unzip', '-o', temp_file, '-d', '/tmp/'])
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if rc:
179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      raise Exception('ERROR: Could not download/unzip image zip.')
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    api_target = 'android-%d' % api_level
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    sys_imgs = os.path.join(constants.EMULATOR_SDK_ROOT, 'sdk',
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            'system-images', api_target, 'x86')
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    logging.info('Deploying system image to %s' % sys_imgs)
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    shutil.move('/tmp/x86', sys_imgs)
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  finally:
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    os.unlink(temp_file)
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)def GetSDKPlatform(api_level=DEFAULT_ANDROID_API_LEVEL):
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  """Update the SDK to include the platform specified.
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Args:
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    api_level: the Android API level to download
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  """
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  android_binary = os.path.join(constants.EMULATOR_SDK_ROOT,
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                'sdk', 'tools', 'android')
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pattern = re.compile('\s*([0-9]+)- SDK Platform Android [\.,0-9]+, API %d.*' %
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                       api_level)
199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  # Example:
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  #   2- SDK Platform Android 4.3, API 18, revision 2
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  exit_code, stdout = cmd_helper.GetCmdStatusAndOutput(
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      [android_binary, 'list', 'sdk'])
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if exit_code != 0:
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    raise Exception('\'android list sdk\' command return %d' % exit_code)
205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for line in stdout.split('\n'):
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    match = pattern.match(line)
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if match:
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      index = match.group(1)
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      print('package %s corresponds to platform level %d' % (index, api_level))
210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      # update sdk --no-ui --filter $INDEX
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      update_command = [android_binary,
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        'update', 'sdk', '--no-ui', '--filter', index]
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      update_command_str = ' '.join(update_command)
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      logging.info('running update command: %s' % update_command_str)
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      update_process = pexpect.spawn(update_command_str)
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      # TODO(andrewhayden): Do we need to bug the user about this?
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if update_process.expect('Do you accept the license') != 0:
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        raise Exception('License agreement check failed')
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      update_process.sendline('y')
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if update_process.expect('Done. 1 package installed.') == 0:
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        print('Successfully installed platform for API level %d' % api_level)
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      else:
224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        raise Exception('Failed to install platform update')
225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  raise Exception('Could not find android-%d update for the SDK!' % api_level)
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def main(argv):
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  opt_parser = optparse.OptionParser(
230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      description='Install dependencies for running the Android emulator')
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  opt_parser.add_option('--api-level', dest='api_level',
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      help='The API level (e.g., 19 for Android 4.4) to ensure is available',
233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      type='int', default=DEFAULT_ANDROID_API_LEVEL)
234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  opt_parser.add_option('-v', dest='verbose', action='store_true',
235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      help='enable verbose logging')
236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  options, _ = opt_parser.parse_args(argv[1:])
237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  # run_tests_helper will set logging to INFO or DEBUG
239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  # We achieve verbose output by configuring it with 2 (==DEBUG)
240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  verbosity = 1
241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (options.verbose):
242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    verbosity = 2
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  logging.basicConfig(level=logging.INFO,
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      format='# %(asctime)-15s: %(message)s')
245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  run_tests_helper.SetLogLevel(verbose_count=verbosity)
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  # Calls below will download emulator SDK and/or system images only if needed.
2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if CheckSDK():
2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    logging.info('android_emulator_sdk/ already exists, skipping download.')
250d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  else:
2514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    GetSDK()
252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  # Check target. The target has to be installed in order to run the emulator.
254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if CheckSDKPlatform(options.api_level):
255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    logging.info('SDK platform android-%d already present, skipping.' %
256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 options.api_level)
257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  else:
258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    logging.info('SDK platform android-%d not present, installing.' %
259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 options.api_level)
260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    GetSDKPlatform(options.api_level)
261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  # Download the x86 system image only if needed.
263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if CheckX86Image(options.api_level):
264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    logging.info('x86 image for android-%d already present, skipping.' %
265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                 options.api_level)
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else:
267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    GetX86Image(options.api_level)
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  # Make sure KVM packages are installed and enabled.
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if CheckKVM():
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    logging.info('KVM already installed and enabled.')
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else:
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    InstallKVM()
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)if __name__ == '__main__':
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sys.exit(main(sys.argv))
278