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

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

Issue 10823209: Add support for building the Dart VM for Android OS. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Removed unused script tools/android/envsetup.sh 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
OLDNEW
(Empty)
1 #!/usr/bin/env python
2
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
5 # BSD-style license that can be found in the LICENSE file.
6
7 """
8 Find an Android device with a given ABI
9
10 The name of the Android device is printed to stdout
11
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.
14 """
15
16 import optparse
17 import os
18 import re
19 import sys
20 import traceback
21 import utils
22
23
24 DEBUG = False
25 VERBOSE = False
26
27
28 def BuildOptions():
29 result = optparse.OptionParser()
30 result.add_option(
31 "-a", "--abi",
32 action="store", type="string",
33 help="Desired ABI.",
34 default='armeabi-v7a')
35 result.add_option(
36 "-b", "--bootstrap",
37 help='Bootstrap - create an emulator, installing SDK packages if needed.',
38 default=False, action="store_true")
39 result.add_option(
40 "-d", "--debug",
41 help='Turn on debugging diagnostics.',
42 default=False, action="store_true")
43 result.add_option(
44 "-v", "--verbose",
45 help='Verbose output.',
46 default=False, action="store_true")
47 return result
48
49
50 def ProcessOptions(options):
51 global DEBUG
52 DEBUG = options.debug
53 global VERBOSE
54 VERBOSE = options.verbose
55 return True
56
57
58 def ParseAndroidListSdkResult(text):
59 """
60 Parse the output of an 'android list sdk' command.
61
62 Return list of (id-num, id-key, type, description)
63 """
64 header_regex = re.compile(
65 r'Packages available for installation or update: \d+\n')
66 packages = re.split(header_regex, text)
67 if len(packages) != 2:
68 raise Exception("Could not get a list of packages to install")
69 entry_regex = re.compile(
70 r'^id\: (\d+) or "([^"]*)"\n\s*Type\: ([^\n]*)\n\s*Desc\: (.*)')
71 entries = []
72 for entry in packages[1].split('----------\n'):
73 match = entry_regex.match(entry)
74 if match == None:
75 continue
76 entries.append((int(match.group(1)), match.group(2), match.group(3),
77 match.group(4)))
78 return entries
79
80
81 def AndroidListSdk():
82 return ParseAndroidListSdkResult(utils.RunCommand(
83 ["android", "list", "sdk", "-a", "-e"]))
84
85
86 def AndroidSdkFindPackage(packages, key):
87 """key is (id-key, type, description-prefix)"""
88 for package in packages:
89 if (package[1] == key[0] and package[2] == key[1]
90 and package[3].find(key[2]) == 0):
91 return package
92 return None
93
94
95 def EnsureSdkPackageInstalled(packages, key):
96 """
97 Makes sure the package with a given key is installed.
98
99 key is (id-key, type, description-prefix)
100
101 Returns True if the package was not already installed.
102 """
103 entry = AndroidSdkFindPackage(packages, key)
104 if entry is None:
105 raise Exception("Could not find a package for key %s" % key)
106 packageId = entry[0]
107 if VERBOSE:
108 sys.stderr.write('Checking Android SDK package %s...\n' % str(entry))
109 out = utils.RunCommand(
110 ["android", "update", "sdk", "-a", "-u", "--filter", str(packageId)])
111 return out.find('\nInstalling Archives:\n') >= 0
112
113
114 def SdkPackagesForAbi(abi):
115 packagesForAbi = {
116 'armeabi-v7a': [
117 # The platform needed to install the armeabi ABI system image:
118 ('android-15', 'Platform', 'Android SDK Platform 4.0.3'),
119 # The armeabi-v7a ABI system image:
120 ('sysimg-15', 'SystemImage', 'Android SDK Platform 4.0.3')
121 ],
122 'x86': [
123 # The platform needed to install the x86 ABI system image:
124 ('android-15', 'Platform', 'Android SDK Platform 4.0.3'),
125 # The x86 ABI system image:
126 ('sysimg-15', 'SystemImage', 'Android SDK Platform 4.0.4')
127 ]
128 }
129
130 if abi not in packagesForAbi:
131 raise Exception('Unsupported abi %s' % abi)
132 return packagesForAbi[abi]
133
134
135 def TargetForAbi(abi):
136 for package in SdkPackagesForAbi(abi):
137 if package[1] == 'Platform':
138 return package[0]
139
140 def EnsureAndroidSdkPackagesInstalled(abi):
141 """Return true if at least one package was not already installed."""
142 abiPackageList = SdkPackagesForAbi(abi)
143 installedSomething = False
144 packages = AndroidListSdk()
145 for package in abiPackageList:
146 installedSomething |= EnsureSdkPackageInstalled(packages, package)
147 return installedSomething
148
149
150 def ParseAndroidListAvdResult(text):
151 """
152 Parse the output of an 'android list avd' command.
153 Return List of {Name: Path: Target: ABI: Skin: Sdcard:}
154 """
155 text = text.split('Available Android Virtual Devices:\n')[-1]
156 text = text.split(
157 'The following Android Virtual Devices could not be loaded:\n')[0]
158 result = []
159 line_re = re.compile(r'^\s*([^\:]+)\:\s*(.*)$')
160 for chunk in text.split('\n---------\n'):
161 entry = {}
162 for line in chunk.split('\n'):
163 line = line.strip()
164 if len(line) == 0:
165 continue
166 match = line_re.match(line)
167 if match is None:
168 raise Exception('Match failed')
169 entry[match.group(1)] = match.group(2)
170 if len(entry) > 0:
171 result.append(entry)
172 return result
173
174
175 def AndroidListAvd():
176 """Returns a list of available Android Virtual Devices."""
177 return ParseAndroidListAvdResult(utils.RunCommand(["android", "list", "avd"]))
178
179
180 def FindAvd(avds, key):
181 for avd in avds:
182 if avd['Name'] == key:
183 return avd
184 return None
185
186
187 def CreateAvd(avdName, abi):
188 out = utils.RunCommand(["android", "create", "avd", "--name", avdName,
189 "--target", TargetForAbi(abi), '--abi', abi],
190 input="no\n")
191 if out.find('Created AVD ') < 0:
192 if VERBOSE:
193 sys.stderr.write('Could not create AVD:\n%s\n' % out)
194 raise Exception('Could not create AVD')
195
196
197 def AvdExists(avdName):
198 avdList = AndroidListAvd()
199 return FindAvd(avdList, avdName) is not None
200
201
202 def EnsureAvdExists(avdName, abi):
203 if AvdExists(avdName):
204 return
205 if VERBOSE:
206 sys.stderr.write('Checking SDK packages...\n')
207 if EnsureAndroidSdkPackagesInstalled(abi):
208 # Installing a new package could have made a previously invalid AVD valid
209 if AvdExists(avdName):
210 return
211 CreateAvd(avdName, abi)
212
213 def dumpenv(map):
214 e = map.keys()
215 e.sort()
216 for k in e:
217 sys.stderr.write("%s: %s\n" % (k, map[k]))
218
219
220 def StartEmulator(abi, avdName, pollFn):
221 """
222 Start an emulator for a given abi and svdName.
223
224 Echo the emulator's stderr and stdout output to our stderr.
225
226 Call pollFn repeatedly until it returns False. Leave the emulator running
227 when we return.
228
229 Implementation note: Normally we would call the 'emulator' binary, which
230 is a wrapper that launches the appropriate abi-specific emulator. But there
231 is a bug that causes the emulator to exit immediately with a result code of
232 -11 if run from a ssh shell or a NX Machine shell. (And only if called from
233 three levels of nested python scripts.) Calling the ABI-specific versions
234 of the emulator directly works around this bug.
235 """
236 emulatorName = {'x86' : 'emulator-x86', 'armeabi-v7a': 'emulator-arm'}[abi]
237 command = [emulatorName, '-avd', avdName, '-no-boot-anim', '-no-window']
238 utils.RunCommand(command, pollFn=pollFn, killOnEarlyReturn=False,
239 outStream=sys.stderr, errStream=sys.stderr)
240
241
242 def ParseAndroidDevices(text):
243 """Return Dictionary [name] -> status"""
244 text = text.split('List of devices attached')[-1]
245 lines = [line.strip() for line in text.split('\n')]
246 lines = [line for line in lines if len(line) > 0]
247 devices = {}
248 for line in lines:
249 lineItems = line.split('\t')
250 devices[lineItems[0]] = lineItems[1]
251 return devices
252
253
254 def GetAndroidDevices():
255 return ParseAndroidDevices(utils.RunCommand(["adb", "devices"]))
256
257
258 def FilterOfflineDevices(devices):
259 online = {}
260 for device in devices.keys():
261 status = devices[device]
262 if status != 'offline':
263 online[device] = status
264 return online
265
266
267 def GetOnlineAndroidDevices():
268 return FilterOfflineDevices(GetAndroidDevices())
269
270
271 def GetAndroidDeviceProperty(device, property):
272 return utils.RunCommand(
273 ["adb", "-s", device, "shell", "getprop", property]).strip()
274
275
276 def GetAndroidDeviceAbis(device):
277 abis = []
278 for property in ['ro.product.cpu.abi', 'ro.product.cpu.abi2']:
279 out = GetAndroidDeviceProperty(device, property)
280 if len(out) > 0:
281 abis.append(out)
282 return abis
283
284
285 def FindAndroidRunning(abi):
286 for device in GetOnlineAndroidDevices().keys():
287 if abi in GetAndroidDeviceAbis(device):
288 return device
289 return None
290
291
292 def AddSdkToolsToPath():
293 script_dir = os.path.dirname(sys.argv[0])
294 dart_root = os.path.realpath(os.path.join(script_dir, '..', '..'))
295 third_party_root = os.path.join(dart_root, 'third_party')
296 android_tools = os.path.join(third_party_root, 'android_tools')
297 android_sdk_root = os.path.join(android_tools, 'sdk')
298 android_sdk_tools = os.path.join(android_sdk_root, 'tools')
299 android_sdk_platform_tools = os.path.join(android_sdk_root, 'platform-tools')
300 os.environ['PATH'] = ':'.join([os.environ['PATH'], android_sdk_tools, android_ sdk_platform_tools])
Emily Fortuna 2012/08/28 16:49:14 80 char
jackpal 2012/08/28 20:15:20 Done.
301 for i in ['ANDROID_NDK_ROOT', 'ANDROID_SDK_ROOT', 'ANDROID_TOOLCHAIN', 'AR', ' BUILDTYPE', 'CC', 'CXX', 'GYP_DEFINES',
302 'LD_LIBRARY_PATH', 'LINK', 'MAKEFLAGS', 'MAKELEVEL', 'MAKEOVERRIDES' , 'MFLAGS', 'NM']:
303 if i in os.environ:
304 del os.environ[i]
305 os.environ['PATH'] = '/usr/local/google/home/jackpal/bin:/usr/local/google/hom e/jackpal/code/depot_tools:/usr/local/symlinks:/usr/local/sbin:/usr/local/bin:/u sr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin:/usr/local/google/home/jackpal/cod e/dart-repo/dart/third_party/android_tools/sdk/tools:/usr/local/google/home/jack pal/code/dart-repo/dart/third_party/android_tools/sdk/platform-tools'
Emily Fortuna 2012/08/28 16:49:14 methinks this is debugging code
jackpal 2012/08/28 20:15:20 Done.
306 os.chdir(dart_root)
307 os.environ['PWD'] = dart_root
308
309 def FindAndroid(abi, bootstrap):
310 if VERBOSE:
311 sys.stderr.write('Looking for an Android device running abi %s\n' % abi)
312 AddSdkToolsToPath()
313 device = FindAndroidRunning(abi)
314 if device is None:
315 if bootstrap:
316 if VERBOSE:
317 sys.stderr.write("No emulator found, try to create one.\n")
318 avdName = 'dart-build-%s' % abi
319 EnsureAvdExists(avdName, abi)
320
321 # It takes a while to start up an emulator. Provide feedback while we wait .
Emily Fortuna 2012/08/28 16:49:14 80 char
jackpal 2012/08/28 20:15:20 Done.
322 pollResult = [None]
323 def pollFunction():
324 if VERBOSE:
325 sys.stderr.write('.')
326 pollResult[0] = FindAndroidRunning(abi)
327 # Stop polling once we have our result.
328 return pollResult[0] != None
329 StartEmulator(abi, avdName, pollFunction)
330 device = pollResult[0]
331 return device
332
333
334 def Main():
335 # Parse options.
336 parser = BuildOptions()
337 (options, args) = parser.parse_args()
338 if not ProcessOptions(options):
339 parser.print_help()
340 return 1
341
342 # If there are additional arguments, report error and exit.
343 if args:
344 parser.print_help()
345 return 1
346
347 try:
348 device = FindAndroid(options.abi, options.bootstrap)
349 if device != None:
350 sys.stdout.write("%s\n" % device)
351 return 0
352 else:
353 if VERBOSE:
354 sys.stderr.write('Could not find device\n')
355 return 2
356 except Exception as e:
357 sys.stderr.write("error: %s\n" % e)
358 if DEBUG:
359 traceback.print_exc(file=sys.stderr)
360 return -1
361
362
363 if __name__ == '__main__':
364 sys.exit(Main())
OLDNEW
« no previous file with comments | « no previous file | runtime/tools/create_snapshot_bin.py » ('j') | runtime/tools/create_snapshot_bin.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698