| OLD | NEW | 
|---|
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be | 
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. | 
| 4 | 4 | 
| 5 """Provides an interface to start and stop Android emulator. | 5 """Provides an interface to start and stop Android emulator. | 
| 6 | 6 | 
| 7 Assumes system environment ANDROID_NDK_ROOT has been set. | 7 Assumes system environment ANDROID_NDK_ROOT has been set. | 
| 8 | 8 | 
| 9   Emulator: The class provides the methods to launch/shutdown the emulator with | 9   Emulator: The class provides the methods to launch/shutdown the emulator with | 
| 10             the android virtual device named 'avd_armeabi' . | 10             the android virtual device named 'avd_armeabi' . | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 21 import time_profile | 21 import time_profile | 
| 22 # TODO(craigdh): Move these pylib dependencies to pylib/utils/. | 22 # TODO(craigdh): Move these pylib dependencies to pylib/utils/. | 
| 23 from pylib import android_commands | 23 from pylib import android_commands | 
| 24 from pylib import cmd_helper | 24 from pylib import cmd_helper | 
| 25 from pylib import constants | 25 from pylib import constants | 
| 26 from pylib import pexpect | 26 from pylib import pexpect | 
| 27 | 27 | 
| 28 import errors | 28 import errors | 
| 29 import run_command | 29 import run_command | 
| 30 | 30 | 
| 31 # Android API level |  | 
| 32 API_TARGET = 'android-%s' % constants.ANDROID_SDK_VERSION |  | 
| 33 |  | 
| 34 # SD card size | 31 # SD card size | 
| 35 SDCARD_SIZE = '512M' | 32 SDCARD_SIZE = '512M' | 
| 36 | 33 | 
|  | 34 # Template used to generate config.ini files for the emulator | 
|  | 35 CONFIG_TEMPLATE = """avd.ini.encoding=ISO-8859-1 | 
|  | 36 hw.dPad=no | 
|  | 37 hw.lcd.density=320 | 
|  | 38 sdcard.size=512M | 
|  | 39 hw.cpu.arch={hw.cpu.arch} | 
|  | 40 hw.device.hash=-708107041 | 
|  | 41 hw.camera.back=none | 
|  | 42 disk.dataPartition.size=800M | 
|  | 43 hw.gpu.enabled=yes | 
|  | 44 skin.path=720x1280 | 
|  | 45 skin.dynamic=yes | 
|  | 46 hw.keyboard=yes | 
|  | 47 hw.ramSize=1024 | 
|  | 48 hw.device.manufacturer=Google | 
|  | 49 hw.sdCard=yes | 
|  | 50 hw.mainKeys=no | 
|  | 51 hw.accelerometer=yes | 
|  | 52 skin.name=720x1280 | 
|  | 53 abi.type={abi.type} | 
|  | 54 hw.trackBall=no | 
|  | 55 hw.device.name=Galaxy Nexus | 
|  | 56 hw.battery=yes | 
|  | 57 hw.sensors.proximity=yes | 
|  | 58 image.sysdir.1=system-images/android-{api.level}/{abi.type}/ | 
|  | 59 hw.sensors.orientation=yes | 
|  | 60 hw.audioInput=yes | 
|  | 61 hw.camera.front=none | 
|  | 62 hw.gps=yes | 
|  | 63 vm.heapSize=128 | 
|  | 64 {extras}""" | 
|  | 65 | 
|  | 66 CONFIG_REPLACEMENTS = { | 
|  | 67   'x86': { | 
|  | 68     '{hw.cpu.arch}': 'x86', | 
|  | 69     '{abi.type}': 'x86', | 
|  | 70     '{extras}': '' | 
|  | 71   }, | 
|  | 72   'arm': { | 
|  | 73     '{hw.cpu.arch}': 'arm', | 
|  | 74     '{abi.type}': 'armeabi-v7a', | 
|  | 75     '{extras}': 'hw.cpu.model=cortex-a8\n' | 
|  | 76   }, | 
|  | 77   'mips': { | 
|  | 78     '{hw.cpu.arch}': 'mips', | 
|  | 79     '{abi.type}': 'mips', | 
|  | 80     '{extras}': '' | 
|  | 81   } | 
|  | 82 } | 
|  | 83 | 
| 37 class EmulatorLaunchException(Exception): | 84 class EmulatorLaunchException(Exception): | 
| 38   """Emulator failed to launch.""" | 85   """Emulator failed to launch.""" | 
| 39   pass | 86   pass | 
| 40 | 87 | 
| 41 def _KillAllEmulators(): | 88 def _KillAllEmulators(): | 
| 42   """Kill all running emulators that look like ones we started. | 89   """Kill all running emulators that look like ones we started. | 
| 43 | 90 | 
| 44   There are odd 'sticky' cases where there can be no emulator process | 91   There are odd 'sticky' cases where there can be no emulator process | 
| 45   running but a device slot is taken.  A little bot trouble and and | 92   running but a device slot is taken.  A little bot trouble and and | 
| 46   we're out of room forever. | 93   we're out of room forever. | 
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 97   """Returns an available TCP port for the console.""" | 144   """Returns an available TCP port for the console.""" | 
| 98   used_ports = [] | 145   used_ports = [] | 
| 99   emulators = android_commands.GetAttachedDevices(hardware=False) | 146   emulators = android_commands.GetAttachedDevices(hardware=False) | 
| 100   for emulator in emulators: | 147   for emulator in emulators: | 
| 101     used_ports.append(emulator.split('-')[1]) | 148     used_ports.append(emulator.split('-')[1]) | 
| 102   for port in PortPool.port_range(): | 149   for port in PortPool.port_range(): | 
| 103     if str(port) not in used_ports: | 150     if str(port) not in used_ports: | 
| 104       return port | 151       return port | 
| 105 | 152 | 
| 106 | 153 | 
| 107 def LaunchEmulators(emulator_count, abi, wait_for_boot=True): | 154 def LaunchEmulators(emulator_count, abi, api_level, wait_for_boot=True): | 
| 108   """Launch multiple emulators and wait for them to boot. | 155   """Launch multiple emulators and wait for them to boot. | 
| 109 | 156 | 
| 110   Args: | 157   Args: | 
| 111     emulator_count: number of emulators to launch. | 158     emulator_count: number of emulators to launch. | 
| 112     abi: the emulator target platform | 159     abi: the emulator target platform | 
|  | 160     api_level: the api level (e.g., 19 for Android v4.4 - KitKat release) | 
| 113     wait_for_boot: whether or not to wait for emulators to boot up | 161     wait_for_boot: whether or not to wait for emulators to boot up | 
| 114 | 162 | 
| 115   Returns: | 163   Returns: | 
| 116     List of emulators. | 164     List of emulators. | 
| 117   """ | 165   """ | 
| 118   emulators = [] | 166   emulators = [] | 
| 119   for n in xrange(emulator_count): | 167   for n in xrange(emulator_count): | 
| 120     t = time_profile.TimeProfile('Emulator launch %d' % n) | 168     t = time_profile.TimeProfile('Emulator launch %d' % n) | 
| 121     # Creates a temporary AVD. | 169     # Creates a temporary AVD. | 
| 122     avd_name = 'run_tests_avd_%d' % n | 170     avd_name = 'run_tests_avd_%d' % n | 
| 123     logging.info('Emulator launch %d with avd_name=%s', n, avd_name) | 171     logging.info('Emulator launch %d with avd_name=%s and api=%d', | 
| 124     emulator = Emulator(avd_name, abi) | 172         n, avd_name, api_level) | 
|  | 173     emulator = Emulator(avd_name, abi, api_level) | 
| 125     emulator.Launch(kill_all_emulators=n == 0) | 174     emulator.Launch(kill_all_emulators=n == 0) | 
| 126     t.Stop() | 175     t.Stop() | 
| 127     emulators.append(emulator) | 176     emulators.append(emulator) | 
| 128   # Wait for all emulators to boot completed. | 177   # Wait for all emulators to boot completed. | 
| 129   if wait_for_boot: | 178   if wait_for_boot: | 
| 130     for emulator in emulators: | 179     for emulator in emulators: | 
| 131       emulator.ConfirmLaunch(True) | 180       emulator.ConfirmLaunch(True) | 
| 132   return emulators | 181   return emulators | 
| 133 | 182 | 
| 134 | 183 | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 155   # the time to launch the emulator and a wait-for-device command. | 204   # the time to launch the emulator and a wait-for-device command. | 
| 156   _LAUNCH_TIMEOUT = 120 | 205   _LAUNCH_TIMEOUT = 120 | 
| 157 | 206 | 
| 158   # Timeout interval of wait-for-device command before bouncing to a a | 207   # Timeout interval of wait-for-device command before bouncing to a a | 
| 159   # process life check. | 208   # process life check. | 
| 160   _WAITFORDEVICE_TIMEOUT = 5 | 209   _WAITFORDEVICE_TIMEOUT = 5 | 
| 161 | 210 | 
| 162   # Time to wait for a "wait for boot complete" (property set on device). | 211   # Time to wait for a "wait for boot complete" (property set on device). | 
| 163   _WAITFORBOOT_TIMEOUT = 300 | 212   _WAITFORBOOT_TIMEOUT = 300 | 
| 164 | 213 | 
| 165   def __init__(self, avd_name, abi): | 214   def __init__(self, avd_name, abi, api_level): | 
| 166     """Init an Emulator. | 215     """Init an Emulator. | 
| 167 | 216 | 
| 168     Args: | 217     Args: | 
| 169       avd_name: name of the AVD to create | 218       avd_name: name of the AVD to create | 
| 170       abi: target platform for emulator being created | 219       abi: target platform for emulator being created, defaults to x86 | 
|  | 220       api_level: the api level of the image | 
| 171     """ | 221     """ | 
| 172     android_sdk_root = os.path.join(constants.EMULATOR_SDK_ROOT, 'sdk') | 222     android_sdk_root = os.path.join(constants.EMULATOR_SDK_ROOT, 'sdk') | 
| 173     self.emulator = os.path.join(android_sdk_root, 'tools', 'emulator') | 223     self.emulator = os.path.join(android_sdk_root, 'tools', 'emulator') | 
| 174     self.android = os.path.join(android_sdk_root, 'tools', 'android') | 224     self.android = os.path.join(android_sdk_root, 'tools', 'android') | 
| 175     self.popen = None | 225     self.popen = None | 
| 176     self.device = None | 226     self.device = None | 
| 177     self.abi = abi | 227     self.abi = abi | 
| 178     self.avd_name = avd_name | 228     self.avd_name = avd_name | 
|  | 229     self.api_level = api_level | 
| 179     self._CreateAVD() | 230     self._CreateAVD() | 
| 180 | 231 | 
| 181   def _DeviceName(self): | 232   def _DeviceName(self): | 
| 182     """Return our device name.""" | 233     """Return our device name.""" | 
| 183     port = _GetAvailablePort() | 234     port = _GetAvailablePort() | 
| 184     return ('emulator-%d' % port, port) | 235     return ('emulator-%d' % port, port) | 
| 185 | 236 | 
| 186   def _CreateAVD(self): | 237   def _CreateAVD(self): | 
| 187     """Creates an AVD with the given name. | 238     """Creates an AVD with the given name. | 
| 188 | 239 | 
| 189     Return avd_name. | 240     Return avd_name. | 
| 190     """ | 241     """ | 
| 191 | 242 | 
| 192     if self.abi == 'arm': | 243     if self.abi == 'arm': | 
| 193       abi_option = 'armeabi-v7a' | 244       abi_option = 'armeabi-v7a' | 
|  | 245     elif self.abi == 'mips': | 
|  | 246       abi_option = 'mips' | 
| 194     else: | 247     else: | 
| 195       abi_option = 'x86' | 248       abi_option = 'x86' | 
| 196 | 249 | 
|  | 250     api_target = 'android-%s' % self.api_level | 
|  | 251 | 
| 197     avd_command = [ | 252     avd_command = [ | 
| 198         self.android, | 253         self.android, | 
| 199         '--silent', | 254         '--silent', | 
| 200         'create', 'avd', | 255         'create', 'avd', | 
| 201         '--name', self.avd_name, | 256         '--name', self.avd_name, | 
| 202         '--abi', abi_option, | 257         '--abi', abi_option, | 
| 203         '--target', API_TARGET, | 258         '--target', api_target, | 
| 204         '--sdcard', SDCARD_SIZE, | 259         '--sdcard', SDCARD_SIZE, | 
| 205         '--force', | 260         '--force', | 
| 206     ] | 261     ] | 
| 207     avd_cmd_str = ' '.join(avd_command) | 262     avd_cmd_str = ' '.join(avd_command) | 
| 208     logging.info('Create AVD command: %s', avd_cmd_str) | 263     logging.info('Create AVD command: %s', avd_cmd_str) | 
| 209     avd_process = pexpect.spawn(avd_cmd_str) | 264     avd_process = pexpect.spawn(avd_cmd_str) | 
| 210 | 265 | 
| 211     # Instead of creating a custom profile, we overwrite config files. | 266     # Instead of creating a custom profile, we overwrite config files. | 
| 212     avd_process.expect('Do you wish to create a custom hardware profile') | 267     avd_process.expect('Do you wish to create a custom hardware profile') | 
| 213     avd_process.sendline('no\n') | 268     avd_process.sendline('no\n') | 
| 214     avd_process.expect('Created AVD \'%s\'' % self.avd_name) | 269     avd_process.expect('Created AVD \'%s\'' % self.avd_name) | 
| 215 | 270 | 
| 216     # Setup test device as default Galaxy Nexus AVD |  | 
| 217     avd_config_dir = os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'android', |  | 
| 218                                   'avd_configs') |  | 
| 219     avd_config_ini = os.path.join(avd_config_dir, |  | 
| 220                                   'AVD_for_Galaxy_Nexus_by_Google_%s.avd' % |  | 
| 221                                   self.abi, 'config.ini') |  | 
| 222 |  | 
| 223     # Replace current configuration with default Galaxy Nexus config. | 271     # Replace current configuration with default Galaxy Nexus config. | 
| 224     avds_dir = os.path.join(os.path.expanduser('~'), '.android', 'avd') | 272     avds_dir = os.path.join(os.path.expanduser('~'), '.android', 'avd') | 
| 225     ini_file = os.path.join(avds_dir, '%s.ini' % self.avd_name) | 273     ini_file = os.path.join(avds_dir, '%s.ini' % self.avd_name) | 
| 226     new_config_ini = os.path.join(avds_dir, '%s.avd' % self.avd_name, | 274     new_config_ini = os.path.join(avds_dir, '%s.avd' % self.avd_name, | 
| 227                                   'config.ini') | 275                                   'config.ini') | 
| 228 | 276 | 
| 229     # Remove config files with defaults to replace with Google's GN settings. | 277     # Remove config files with defaults to replace with Google's GN settings. | 
| 230     os.unlink(ini_file) | 278     os.unlink(ini_file) | 
| 231     os.unlink(new_config_ini) | 279     os.unlink(new_config_ini) | 
| 232 | 280 | 
| 233     # Create new configuration files with Galaxy Nexus by Google settings. | 281     # Create new configuration files with Galaxy Nexus by Google settings. | 
| 234     with open(ini_file, 'w') as new_ini: | 282     with open(ini_file, 'w') as new_ini: | 
| 235       new_ini.write('avd.ini.encoding=ISO-8859-1\n') | 283       new_ini.write('avd.ini.encoding=ISO-8859-1\n') | 
| 236       new_ini.write('target=%s\n' % API_TARGET) | 284       new_ini.write('target=%s\n' % api_target) | 
| 237       new_ini.write('path=%s/%s.avd\n' % (avds_dir, self.avd_name)) | 285       new_ini.write('path=%s/%s.avd\n' % (avds_dir, self.avd_name)) | 
| 238       new_ini.write('path.rel=avd/%s.avd\n' % self.avd_name) | 286       new_ini.write('path.rel=avd/%s.avd\n' % self.avd_name) | 
| 239 | 287 | 
| 240     shutil.copy(avd_config_ini, new_config_ini) | 288     custom_config = CONFIG_TEMPLATE | 
|  | 289     replacements = CONFIG_REPLACEMENTS[self.abi] | 
|  | 290     for key in replacements: | 
|  | 291       custom_config = custom_config.replace(key, replacements[key]) | 
|  | 292     custom_config = custom_config.replace('{api.level}', str(self.api_level)) | 
|  | 293 | 
|  | 294     with open(new_config_ini, 'w') as new_config_ini: | 
|  | 295       new_config_ini.write(custom_config) | 
|  | 296 | 
| 241     return self.avd_name | 297     return self.avd_name | 
| 242 | 298 | 
| 243 | 299 | 
| 244   def _DeleteAVD(self): | 300   def _DeleteAVD(self): | 
| 245     """Delete the AVD of this emulator.""" | 301     """Delete the AVD of this emulator.""" | 
| 246     avd_command = [ | 302     avd_command = [ | 
| 247         self.android, | 303         self.android, | 
| 248         '--silent', | 304         '--silent', | 
| 249         'delete', | 305         'delete', | 
| 250         'avd', | 306         'avd', | 
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 359     logging.critical('emulator _ShutdownOnSignal') | 415     logging.critical('emulator _ShutdownOnSignal') | 
| 360     for sig in self._SIGNALS: | 416     for sig in self._SIGNALS: | 
| 361       signal.signal(sig, signal.SIG_DFL) | 417       signal.signal(sig, signal.SIG_DFL) | 
| 362     self.Shutdown() | 418     self.Shutdown() | 
| 363     raise KeyboardInterrupt  # print a stack | 419     raise KeyboardInterrupt  # print a stack | 
| 364 | 420 | 
| 365   def _InstallKillHandler(self): | 421   def _InstallKillHandler(self): | 
| 366     """Install a handler to kill the emulator when we exit unexpectedly.""" | 422     """Install a handler to kill the emulator when we exit unexpectedly.""" | 
| 367     for sig in self._SIGNALS: | 423     for sig in self._SIGNALS: | 
| 368       signal.signal(sig, self._ShutdownOnSignal) | 424       signal.signal(sig, self._ShutdownOnSignal) | 
| OLD | NEW | 
|---|