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

Side by Side Diff: runtime/tools/android_finder.py

Issue 10916021: Fix android_finder.py (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Use startswith Created 8 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | runtime/tools/utils.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 2
3 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 3 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
4 # for details. All rights reserved. Use of this source code is governed by a 4 # for details. All rights reserved. Use of this source code is governed by a
5 # BSD-style license that can be found in the LICENSE file. 5 # BSD-style license that can be found in the LICENSE file.
6 6
7 """ 7 """
8 Find an Android device with a given ABI 8 Find an Android device with a given ABI.
9 9
10 The name of the Android device is printed to stdout 10 The name of the Android device is printed to stdout.
11 11
12 Optionally configure and launch an emulator if there's no existing device for a 12 Optionally configure and launch an emulator if there's no existing device for a
13 given ABI. Will download and install Android SDK components as needed. 13 given ABI. Will download and install Android SDK components as needed.
14 """ 14 """
15 15
16 import optparse 16 import optparse
17 import os 17 import os
18 import re 18 import re
19 import sys 19 import sys
20 import traceback 20 import traceback
21 import utils 21 import utils
22 22
23 23
24 DEBUG = False 24 DEBUG = False
25 VERBOSE = False 25 VERBOSE = False
26 26
27 27
28 def BuildOptions(): 28 def BuildOptions():
29 result = optparse.OptionParser() 29 result = optparse.OptionParser()
30 result.add_option( 30 result.add_option(
31 "-a", "--abi", 31 "-a", "--abi",
32 action="store", type="string", 32 action="store", type="string",
33 help="Desired ABI. armeabi-v7a or x86") 33 help="Desired ABI. armeabi-v7a or x86.")
34 result.add_option( 34 result.add_option(
35 "-b", "--bootstrap", 35 "-b", "--bootstrap",
36 help='Bootstrap - create an emulator, installing SDK packages if needed.', 36 help='Bootstrap - create an emulator, installing SDK packages if needed.',
37 default=False, action="store_true") 37 default=False, action="store_true")
38 result.add_option( 38 result.add_option(
39 "-d", "--debug", 39 "-d", "--debug",
40 help='Turn on debugging diagnostics.', 40 help='Turn on debugging diagnostics.',
41 default=False, action="store_true") 41 default=False, action="store_true")
42 result.add_option( 42 result.add_option(
43 "-v", "--verbose", 43 "-v", "--verbose",
44 help='Verbose output.', 44 help='Verbose output.',
45 default=False, action="store_true") 45 default=False, action="store_true")
46 return result 46 return result
47 47
48 48
49 def ProcessOptions(options): 49 def ProcessOptions(options):
50 global DEBUG 50 global DEBUG
51 DEBUG = options.debug 51 DEBUG = options.debug
52 global VERBOSE 52 global VERBOSE
53 VERBOSE = options.verbose 53 VERBOSE = options.verbose
54 if options.abi is None: 54 if options.abi is None:
55 sys.stderr.write('--abi not specified\n') 55 sys.stderr.write('--abi not specified.\n')
56 return False 56 return False
57 return True 57 return True
58 58
59 59
60 def ParseAndroidListSdkResult(text): 60 def ParseAndroidListSdkResult(text):
61 """ 61 """
62 Parse the output of an 'android list sdk' command. 62 Parse the output of an 'android list sdk' command.
63 63
64 Return list of (id-num, id-key, type, description) 64 Return list of (id-num, id-key, type, description).
65 """ 65 """
66 header_regex = re.compile( 66 header_regex = re.compile(
67 r'Packages available for installation or update: \d+\n') 67 r'Packages available for installation or update: \d+\n')
68 packages = re.split(header_regex, text) 68 packages = re.split(header_regex, text)
69 if len(packages) != 2: 69 if len(packages) != 2:
70 raise Exception("Could not get a list of packages to install") 70 raise utils.Error("Could not get a list of packages to install")
71 entry_regex = re.compile( 71 entry_regex = re.compile(
72 r'^id\: (\d+) or "([^"]*)"\n\s*Type\: ([^\n]*)\n\s*Desc\: (.*)') 72 r'^id\: (\d+) or "([^"]*)"\n\s*Type\: ([^\n]*)\n\s*Desc\: (.*)')
73 entries = [] 73 entries = []
74 for entry in packages[1].split('----------\n'): 74 for entry in packages[1].split('----------\n'):
75 match = entry_regex.match(entry) 75 match = entry_regex.match(entry)
76 if match == None: 76 if match == None:
77 continue 77 continue
78 entries.append((int(match.group(1)), match.group(2), match.group(3), 78 entries.append((int(match.group(1)), match.group(2), match.group(3),
79 match.group(4))) 79 match.group(4)))
80 return entries 80 return entries
81 81
82 82
83 def AndroidListSdk(): 83 def AndroidListSdk():
84 return ParseAndroidListSdkResult(utils.RunCommand( 84 return ParseAndroidListSdkResult(utils.RunCommand(
85 ["android", "list", "sdk", "-a", "-e"])) 85 ["android", "list", "sdk", "-a", "-e"]))
86 86
87 87
88 def AndroidSdkFindPackage(packages, key): 88 def AndroidSdkFindPackage(packages, key):
89 """key is (id-key, type, description-prefix)""" 89 """
90 Args:
91 packages: list of (id-num, id-key, type, description).
92 key: (id-key, type, description-prefix).
93 """
94 (key_id, key_type, key_description_prefix) = key
90 for package in packages: 95 for package in packages:
91 if (package[1] == key[0] and package[2] == key[1] 96 (package_num, package_id, package_type, package_description) = package
92 and package[3].find(key[2]) == 0): 97 if (package_id == key_id and package_type == key_type
98 and package_description.startswith(key_description_prefix)):
93 return package 99 return package
94 return None 100 return None
95 101
96 102
97 def EnsureSdkPackageInstalled(packages, key): 103 def EnsureSdkPackageInstalled(packages, key):
98 """ 104 """
99 Makes sure the package with a given key is installed. 105 Makes sure the package with a given key is installed.
100 106
101 key is (id-key, type, description-prefix) 107 key is (id-key, type, description-prefix)
102 108
103 Returns True if the package was not already installed. 109 Returns True if the package was not already installed.
104 """ 110 """
105 entry = AndroidSdkFindPackage(packages, key) 111 entry = AndroidSdkFindPackage(packages, key)
106 if entry is None: 112 if entry is None:
107 raise Exception("Could not find a package for key %s" % key) 113 raise utils.Error("Could not find a package for key %s" % key)
108 packageId = entry[0] 114 packageId = entry[0]
109 if VERBOSE: 115 if VERBOSE:
110 sys.stderr.write('Checking Android SDK package %s...\n' % str(entry)) 116 sys.stderr.write('Checking Android SDK package %s...\n' % str(entry))
111 out = utils.RunCommand( 117 out = utils.RunCommand(
112 ["android", "update", "sdk", "-a", "-u", "--filter", str(packageId)]) 118 ["android", "update", "sdk", "-a", "-u", "--filter", str(packageId)])
113 return out.find('\nInstalling Archives:\n') >= 0 119 return '\nInstalling Archives:\n' in out
114 120
115 121
116 def SdkPackagesForAbi(abi): 122 def SdkPackagesForAbi(abi):
117 packagesForAbi = { 123 packagesForAbi = {
118 'armeabi-v7a': [ 124 'armeabi-v7a': [
119 # The platform needed to install the armeabi ABI system image: 125 # The platform needed to install the armeabi ABI system image:
120 ('android-15', 'Platform', 'Android SDK Platform 4.0.3'), 126 ('android-15', 'Platform', 'Android SDK Platform 4.0.3'),
121 # The armeabi-v7a ABI system image: 127 # The armeabi-v7a ABI system image:
122 ('sysimg-15', 'SystemImage', 'Android SDK Platform 4.0.3') 128 ('sysimg-15', 'SystemImage', 'Android SDK Platform 4.0.3')
123 ], 129 ],
124 'x86': [ 130 'x86': [
125 # The platform needed to install the x86 ABI system image: 131 # The platform needed to install the x86 ABI system image:
126 ('android-15', 'Platform', 'Android SDK Platform 4.0.3'), 132 ('android-15', 'Platform', 'Android SDK Platform 4.0.3'),
127 # The x86 ABI system image: 133 # The x86 ABI system image:
128 ('sysimg-15', 'SystemImage', 'Android SDK Platform 4.0.4') 134 ('sysimg-15', 'SystemImage', 'Android SDK Platform 4.0.4')
129 ] 135 ]
130 } 136 }
131 137
132 if abi not in packagesForAbi: 138 if abi not in packagesForAbi:
133 raise Exception('Unsupported abi %s' % abi) 139 raise utils.Error('Unsupported abi %s' % abi)
134 return packagesForAbi[abi] 140 return packagesForAbi[abi]
135 141
136 142
137 def TargetForAbi(abi): 143 def TargetForAbi(abi):
138 for package in SdkPackagesForAbi(abi): 144 for package in SdkPackagesForAbi(abi):
139 if package[1] == 'Platform': 145 if package[1] == 'Platform':
140 return package[0] 146 return package[0]
141 147
148
142 def EnsureAndroidSdkPackagesInstalled(abi): 149 def EnsureAndroidSdkPackagesInstalled(abi):
143 """Return true if at least one package was not already installed.""" 150 """Return true if at least one package was not already installed."""
144 abiPackageList = SdkPackagesForAbi(abi) 151 abiPackageList = SdkPackagesForAbi(abi)
145 installedSomething = False 152 installedSomething = False
146 packages = AndroidListSdk() 153 packages = AndroidListSdk()
147 for package in abiPackageList: 154 for package in abiPackageList:
148 installedSomething |= EnsureSdkPackageInstalled(packages, package) 155 installedSomething |= EnsureSdkPackageInstalled(packages, package)
149 return installedSomething 156 return installedSomething
150 157
151 158
152 def ParseAndroidListAvdResult(text): 159 def ParseAndroidListAvdResult(text):
153 """ 160 """
154 Parse the output of an 'android list avd' command. 161 Parse the output of an 'android list avd' command.
155 Return List of {Name: Path: Target: ABI: Skin: Sdcard:} 162 Return List of {Name: Path: Target: ABI: Skin: Sdcard:}
156 """ 163 """
157 text = text.split('Available Android Virtual Devices:\n')[-1] 164 text = text.split('Available Android Virtual Devices:\n')[-1]
158 text = text.split( 165 text = text.split(
159 'The following Android Virtual Devices could not be loaded:\n')[0] 166 'The following Android Virtual Devices could not be loaded:\n')[0]
160 result = [] 167 result = []
161 line_re = re.compile(r'^\s*([^\:]+)\:\s*(.*)$') 168 line_re = re.compile(r'^\s*([^\:]+)\:\s*(.*)$')
162 for chunk in text.split('\n---------\n'): 169 for chunk in text.split('\n---------\n'):
163 entry = {} 170 entry = {}
164 for line in chunk.split('\n'): 171 for line in chunk.split('\n'):
165 line = line.strip() 172 line = line.strip()
166 if len(line) == 0: 173 if len(line) == 0:
167 continue 174 continue
168 match = line_re.match(line) 175 match = line_re.match(line)
169 if match is None: 176 if match is None:
170 raise Exception('Match failed') 177 raise utils.Error('Match failed')
171 entry[match.group(1)] = match.group(2) 178 entry[match.group(1)] = match.group(2)
172 if len(entry) > 0: 179 if len(entry) > 0:
173 result.append(entry) 180 result.append(entry)
174 return result 181 return result
175 182
176 183
177 def AndroidListAvd(): 184 def AndroidListAvd():
178 """Returns a list of available Android Virtual Devices.""" 185 """Returns a list of available Android Virtual Devices."""
179 return ParseAndroidListAvdResult(utils.RunCommand(["android", "list", "avd"])) 186 return ParseAndroidListAvdResult(utils.RunCommand(["android", "list", "avd"]))
180 187
181 188
182 def FindAvd(avds, key): 189 def FindAvd(avds, key):
183 for avd in avds: 190 for avd in avds:
184 if avd['Name'] == key: 191 if avd['Name'] == key:
185 return avd 192 return avd
186 return None 193 return None
187 194
188 195
189 def CreateAvd(avdName, abi): 196 def CreateAvd(avdName, abi):
190 out = utils.RunCommand(["android", "create", "avd", "--name", avdName, 197 out = utils.RunCommand(["android", "create", "avd", "--name", avdName,
191 "--target", TargetForAbi(abi), '--abi', abi], 198 "--target", TargetForAbi(abi), '--abi', abi],
192 input="no\n") 199 input="no\n")
193 if out.find('Created AVD ') < 0: 200 if out.find('Created AVD ') < 0:
194 if VERBOSE: 201 if VERBOSE:
195 sys.stderr.write('Could not create AVD:\n%s\n' % out) 202 sys.stderr.write('Could not create AVD:\n%s\n' % out)
196 raise Exception('Could not create AVD') 203 raise utils.Error('Could not create AVD')
197 204
198 205
199 def AvdExists(avdName): 206 def AvdExists(avdName):
200 avdList = AndroidListAvd() 207 avdList = AndroidListAvd()
201 return FindAvd(avdList, avdName) is not None 208 return FindAvd(avdList, avdName) is not None
202 209
203 210
204 def EnsureAvdExists(avdName, abi): 211 def EnsureAvdExists(avdName, abi):
205 if AvdExists(avdName): 212 if AvdExists(avdName):
206 return 213 return
207 if VERBOSE: 214 if VERBOSE:
208 sys.stderr.write('Checking SDK packages...\n') 215 sys.stderr.write('Checking SDK packages...\n')
209 if EnsureAndroidSdkPackagesInstalled(abi): 216 if EnsureAndroidSdkPackagesInstalled(abi):
210 # Installing a new package could have made a previously invalid AVD valid 217 # Installing a new package could have made a previously invalid AVD valid
211 if AvdExists(avdName): 218 if AvdExists(avdName):
212 return 219 return
213 CreateAvd(avdName, abi) 220 CreateAvd(avdName, abi)
214 221
215 def dumpenv(map):
216 e = map.keys()
217 e.sort()
218 for k in e:
219 sys.stderr.write("%s: %s\n" % (k, map[k]))
220
221 222
222 def StartEmulator(abi, avdName, pollFn): 223 def StartEmulator(abi, avdName, pollFn):
223 """ 224 """
224 Start an emulator for a given abi and svdName. 225 Start an emulator for a given abi and svdName.
225 226
226 Echo the emulator's stderr and stdout output to our stderr. 227 Echo the emulator's stderr and stdout output to our stderr.
227 228
228 Call pollFn repeatedly until it returns False. Leave the emulator running 229 Call pollFn repeatedly until it returns False. Leave the emulator running
229 when we return. 230 when we return.
230 231
231 Implementation note: Normally we would call the 'emulator' binary, which 232 Implementation note: Normally we would call the 'emulator' binary, which
232 is a wrapper that launches the appropriate abi-specific emulator. But there 233 is a wrapper that launches the appropriate abi-specific emulator. But there
233 is a bug that causes the emulator to exit immediately with a result code of 234 is a bug that causes the emulator to exit immediately with a result code of
234 -11 if run from a ssh shell or a NX Machine shell. (And only if called from 235 -11 if run from a ssh shell or a No Machine shell. (And only if called from
235 three levels of nested python scripts.) Calling the ABI-specific versions 236 three levels of nested python scripts.) Calling the ABI-specific versions
236 of the emulator directly works around this bug. 237 of the emulator directly works around this bug.
237 """ 238 """
238 emulatorName = {'x86' : 'emulator-x86', 'armeabi-v7a': 'emulator-arm'}[abi] 239 emulatorName = {'x86' : 'emulator-x86', 'armeabi-v7a': 'emulator-arm'}[abi]
239 command = [emulatorName, '-avd', avdName, '-no-boot-anim', '-no-window'] 240 command = [emulatorName, '-avd', avdName, '-no-boot-anim', '-no-window']
240 utils.RunCommand(command, pollFn=pollFn, killOnEarlyReturn=False, 241 utils.RunCommand(command, pollFn=pollFn, killOnEarlyReturn=False,
241 outStream=sys.stderr, errStream=sys.stderr) 242 outStream=sys.stderr, errStream=sys.stderr)
242 243
243 244
244 def ParseAndroidDevices(text): 245 def ParseAndroidDevices(text):
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 os.environ['PATH'] = ':'.join([ 303 os.environ['PATH'] = ':'.join([
303 os.environ['PATH'], android_sdk_tools, android_sdk_platform_tools]) 304 os.environ['PATH'], android_sdk_tools, android_sdk_platform_tools])
304 # Remove any environment variables that would affect our build. 305 # Remove any environment variables that would affect our build.
305 for i in ['ANDROID_NDK_ROOT', 'ANDROID_SDK_ROOT', 'ANDROID_TOOLCHAIN', 306 for i in ['ANDROID_NDK_ROOT', 'ANDROID_SDK_ROOT', 'ANDROID_TOOLCHAIN',
306 'AR', 'BUILDTYPE', 'CC', 'CXX', 'GYP_DEFINES', 307 'AR', 'BUILDTYPE', 'CC', 'CXX', 'GYP_DEFINES',
307 'LD_LIBRARY_PATH', 'LINK', 'MAKEFLAGS', 'MAKELEVEL', 308 'LD_LIBRARY_PATH', 'LINK', 'MAKEFLAGS', 'MAKELEVEL',
308 'MAKEOVERRIDES', 'MFLAGS', 'NM']: 309 'MAKEOVERRIDES', 'MFLAGS', 'NM']:
309 if i in os.environ: 310 if i in os.environ:
310 del os.environ[i] 311 del os.environ[i]
311 312
313
312 def FindAndroid(abi, bootstrap): 314 def FindAndroid(abi, bootstrap):
313 if VERBOSE: 315 if VERBOSE:
314 sys.stderr.write('Looking for an Android device running abi %s...\n' % abi) 316 sys.stderr.write('Looking for an Android device running abi %s...\n' % abi)
315 AddSdkToolsToPath() 317 AddSdkToolsToPath()
316 device = FindAndroidRunning(abi) 318 device = FindAndroidRunning(abi)
317 if device is None: 319 if not device:
318 if bootstrap: 320 if bootstrap:
319 if VERBOSE: 321 if VERBOSE:
320 sys.stderr.write("No emulator found, try to create one.\n") 322 sys.stderr.write("No emulator found, try to create one.\n")
321 avdName = 'dart-build-%s' % abi 323 avdName = 'dart-build-%s' % abi
322 EnsureAvdExists(avdName, abi) 324 EnsureAvdExists(avdName, abi)
323 325
324 # It takes a while to start up an emulator. 326 # It takes a while to start up an emulator.
325 # Provide feedback while we wait. 327 # Provide feedback while we wait.
326 pollResult = [None] 328 pollResult = [None]
327 def pollFunction(): 329 def pollFunction():
(...skipping 22 matching lines...) Expand all
350 352
351 try: 353 try:
352 device = FindAndroid(options.abi, options.bootstrap) 354 device = FindAndroid(options.abi, options.bootstrap)
353 if device != None: 355 if device != None:
354 sys.stdout.write("%s\n" % device) 356 sys.stdout.write("%s\n" % device)
355 return 0 357 return 0
356 else: 358 else:
357 if VERBOSE: 359 if VERBOSE:
358 sys.stderr.write('Could not find device\n') 360 sys.stderr.write('Could not find device\n')
359 return 2 361 return 2
360 except Exception as e: 362 except utils.Error as e:
361 sys.stderr.write("error: %s\n" % e) 363 sys.stderr.write("error: %s\n" % e)
362 if DEBUG: 364 if DEBUG:
363 traceback.print_exc(file=sys.stderr) 365 traceback.print_exc(file=sys.stderr)
364 return -1 366 return -1
365 367
366 368
367 if __name__ == '__main__': 369 if __name__ == '__main__':
368 sys.exit(Main()) 370 sys.exit(Main())
OLDNEW
« no previous file with comments | « no previous file | runtime/tools/utils.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698