OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 from skypy.skyserver import SkyServer | 6 from skypy.skyserver import SkyServer |
7 import argparse | 7 import argparse |
8 import json | 8 import json |
9 import logging | 9 import logging |
10 import os | 10 import os |
11 import pipes | 11 import pipes |
12 import re | 12 import re |
13 import requests | 13 import requests |
14 import signal | 14 import signal |
15 import skypy.paths | 15 import skypy.paths |
16 import StringIO | 16 import StringIO |
17 import subprocess | 17 import subprocess |
18 import sys | 18 import sys |
19 import time | 19 import time |
20 import urlparse | 20 import urlparse |
21 | 21 |
22 SRC_ROOT = skypy.paths.Paths('ignored').src_root | |
23 sys.path.insert(0, os.path.join(SRC_ROOT, 'build', 'android')) | |
24 from pylib import android_commands | |
25 from pylib import constants | |
26 from pylib import forwarder | |
27 | |
28 | |
29 SUPPORTED_MIME_TYPES = [ | 22 SUPPORTED_MIME_TYPES = [ |
30 'text/html', | 23 'text/html', |
31 'text/sky', | 24 'text/sky', |
32 'text/plain', | 25 'text/plain', |
33 ] | 26 ] |
34 | 27 |
35 DEFAULT_SKY_COMMAND_PORT = 7777 | 28 DEFAULT_SKY_COMMAND_PORT = 7777 |
36 GDB_PORT = 8888 | 29 GDB_PORT = 8888 |
37 SKY_SERVER_PORT = 9999 | 30 SKY_SERVER_PORT = 9999 |
38 PID_FILE_PATH = "/tmp/skydb.pids" | |
39 DEFAULT_URL = "https://raw.githubusercontent.com/domokit/mojo/master/sky/example
s/home.sky" | 31 DEFAULT_URL = "https://raw.githubusercontent.com/domokit/mojo/master/sky/example
s/home.sky" |
40 | 32 |
41 ANDROID_PACKAGE = "org.chromium.mojo.shell" | 33 ANDROID_PACKAGE = "org.chromium.mojo.shell" |
42 ANDROID_ACTIVITY = "%s/.MojoShellActivity" % ANDROID_PACKAGE | 34 ANDROID_ACTIVITY = "%s/.MojoShellActivity" % ANDROID_PACKAGE |
43 ANDROID_APK_NAME = 'MojoShell.apk' | 35 ANDROID_APK_NAME = 'MojoShell.apk' |
| 36 |
| 37 PID_FILE_PATH = "/tmp/skydb.pids" |
44 CACHE_LINKS_PATH = '/tmp/mojo_cache_links' | 38 CACHE_LINKS_PATH = '/tmp/mojo_cache_links' |
45 SYSTEM_LIBS_ROOT_PATH = '/tmp/device_libs' | 39 SYSTEM_LIBS_ROOT_PATH = '/tmp/device_libs' |
46 | 40 |
| 41 SRC_ROOT = skypy.paths.Paths('ignored').src_root |
| 42 ADB_PATH = os.path.join(SRC_ROOT, |
| 43 'third_party/android_tools/sdk/platform-tools/adb') |
| 44 |
47 | 45 |
48 # FIXME: Move this into mopy.config | 46 # FIXME: Move this into mopy.config |
49 def gn_args_from_build_dir(build_dir): | 47 def gn_args_from_build_dir(build_dir): |
50 gn_cmd = [ | 48 gn_cmd = [ |
51 'gn', 'args', | 49 'gn', 'args', |
52 build_dir, | 50 build_dir, |
53 '--list', '--short' | 51 '--list', '--short' |
54 ] | 52 ] |
55 config = {} | 53 config = {} |
56 for line in subprocess.check_output(gn_cmd).strip().split('\n'): | 54 for line in subprocess.check_output(gn_cmd).strip().split('\n'): |
(...skipping 21 matching lines...) Expand all Loading... |
78 | 76 |
79 def _in_chromoting(self): | 77 def _in_chromoting(self): |
80 return os.environ.get('CHROME_REMOTE_DESKTOP_SESSION', False) | 78 return os.environ.get('CHROME_REMOTE_DESKTOP_SESSION', False) |
81 | 79 |
82 def _wrap_for_android(self, shell_args): | 80 def _wrap_for_android(self, shell_args): |
83 # am shell --esa: (someone shoot me now) | 81 # am shell --esa: (someone shoot me now) |
84 # [--esa <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]] | 82 # [--esa <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]] |
85 # (to embed a comma into a string escape it using "\,") | 83 # (to embed a comma into a string escape it using "\,") |
86 escaped_args = map(lambda arg: arg.replace(',', '\\,'), shell_args) | 84 escaped_args = map(lambda arg: arg.replace(',', '\\,'), shell_args) |
87 return [ | 85 return [ |
88 'adb', 'shell', | 86 ADB_PATH, 'shell', |
89 'am', 'start', | 87 'am', 'start', |
90 '-W', | 88 '-W', |
91 '-S', | 89 '-S', |
92 '-a', 'android.intent.action.VIEW', | 90 '-a', 'android.intent.action.VIEW', |
93 '-n', ANDROID_ACTIVITY, | 91 '-n', ANDROID_ACTIVITY, |
94 # FIXME: This quoting is very error-prone. Perhaps we should read | 92 # FIXME: This quoting is very error-prone. Perhaps we should read |
95 # our args from a file instead? | 93 # our args from a file instead? |
96 '--esa', 'parameters', ','.join(escaped_args), | 94 '--esa', 'parameters', ','.join(escaped_args), |
97 ] | 95 ] |
98 | 96 |
99 def _build_mojo_shell_command(self, args, is_android): | 97 def _build_mojo_shell_command(self, args, is_android): |
100 content_handlers = ['%s,%s' % (mime_type, 'mojo:sky_viewer') | 98 content_handlers = ['%s,%s' % (mime_type, 'mojo:sky_viewer') |
101 for mime_type in SUPPORTED_MIME_TYPES] | 99 for mime_type in SUPPORTED_MIME_TYPES] |
102 | 100 |
103 remote_command_port = self.pids.get('remote_sky_command_port', self.pids
['sky_command_port']) | 101 remote_command_port = self.pids.get('remote_sky_command_port', self.pids
['sky_command_port']) |
104 remote_server_port = self.pids.get('remote_sky_server_port', self.pids['
sky_server_port']) | 102 remote_server_port = self.pids.get('remote_sky_server_port', self.pids['
sky_server_port']) |
105 | 103 |
106 shell_args = [ | 104 shell_args = [ |
107 '--v=1', | 105 '--v=1', |
108 '--content-handlers=%s' % ','.join(content_handlers), | 106 '--content-handlers=%s' % ','.join(content_handlers), |
109 '--url-mappings=mojo:window_manager=mojo:sky_debugger', | 107 '--url-mappings=mojo:window_manager=mojo:sky_debugger', |
110 '--args-for=mojo:sky_debugger_prompt %d' % remote_command_port, | 108 '--args-for=mojo:sky_debugger_prompt %d' % remote_command_port, |
111 'mojo:window_manager', | 109 'mojo:window_manager', |
112 ] | 110 ] |
113 | 111 |
| 112 if args.url_or_path: |
| 113 shell_args.append( |
| 114 '--args-for=mojo:window_manager %s' % self._url_from_args(args)) |
| 115 |
114 # Map all mojo: urls to http: urls using the --origin command. | 116 # Map all mojo: urls to http: urls using the --origin command. |
115 build_dir_url = SkyServer.url_for_path( | 117 build_dir_url = SkyServer.url_for_path( |
116 remote_server_port, | 118 remote_server_port, |
117 self.pids['sky_server_root'], | 119 self.pids['sky_server_root'], |
118 self.pids['build_dir']) | 120 self.pids['build_dir']) |
119 shell_args += ['--origin=%s' % build_dir_url] | 121 shell_args += ['--origin=%s' % build_dir_url] |
120 | 122 |
121 # Desktop-only work-around for mojo crashing under chromoting. | 123 # Desktop-only work-around for mojo crashing under chromoting. |
122 if not is_android and args.use_osmesa: | 124 if not is_android and args.use_osmesa: |
123 shell_args.append( | 125 shell_args.append( |
124 '--args-for=mojo:native_viewport_service --use-osmesa') | 126 '--args-for=mojo:native_viewport_service --use-osmesa') |
125 | 127 |
126 if is_android and args.gdb: | 128 if is_android and args.gdb: |
127 shell_args.append('--wait_for_debugger') | 129 shell_args.append('--wait_for_debugger') |
128 | 130 |
129 if 'remote_sky_server_port' in self.pids: | 131 if 'remote_sky_server_port' in self.pids: |
130 shell_command = self._wrap_for_android(shell_args) | 132 shell_command = self._wrap_for_android(shell_args) |
131 else: | 133 else: |
132 shell_command = [self.paths.mojo_shell_path] + shell_args | 134 shell_command = [self.paths.mojo_shell_path] + shell_args |
133 | 135 |
134 return shell_command | 136 return shell_command |
135 | 137 |
136 def _connect_to_device(self): | |
137 device = android_commands.AndroidCommands( | |
138 android_commands.GetAttachedDevices()[0]) | |
139 device.EnableAdbRoot() | |
140 return device | |
141 | |
142 def sky_server_for_args(self, args): | 138 def sky_server_for_args(self, args): |
143 # FIXME: This is a hack. sky_server should just take a build_dir | 139 # FIXME: This is a hack. sky_server should just take a build_dir |
144 # not a magical "configuration" name. | 140 # not a magical "configuration" name. |
145 configuration = os.path.basename(os.path.normpath(self.paths.build_dir)) | 141 configuration = os.path.basename(os.path.normpath(self.paths.build_dir)) |
146 server_root = self._server_root_for_url(args.url_or_path) | 142 server_root = self._server_root_for_url(args.url_or_path) |
147 sky_server = SkyServer(self.paths, SKY_SERVER_PORT, | 143 sky_server = SkyServer(self.paths, SKY_SERVER_PORT, |
148 configuration, server_root) | 144 configuration, server_root) |
149 return sky_server | 145 return sky_server |
150 | 146 |
151 def _create_paths_for_build_dir(self, build_dir): | 147 def _create_paths_for_build_dir(self, build_dir): |
152 # skypy.paths.Paths takes a root-relative build_dir argument. :( | 148 # skypy.paths.Paths takes a root-relative build_dir argument. :( |
153 abs_build_dir = os.path.abspath(build_dir) | 149 abs_build_dir = os.path.abspath(build_dir) |
154 root_relative_build_dir = os.path.relpath(abs_build_dir, SRC_ROOT) | 150 root_relative_build_dir = os.path.relpath(abs_build_dir, SRC_ROOT) |
155 return skypy.paths.Paths(root_relative_build_dir) | 151 return skypy.paths.Paths(root_relative_build_dir) |
156 | 152 |
157 def _find_remote_pid_for_package(self, package): | 153 def _find_remote_pid_for_package(self, package): |
158 ps_output = subprocess.check_output(['adb', 'shell', 'ps']) | 154 ps_output = subprocess.check_output([ADB_PATH, 'shell', 'ps']) |
159 for line in ps_output.split('\n'): | 155 for line in ps_output.split('\n'): |
160 fields = line.split() | 156 fields = line.split() |
161 if fields and fields[-1] == package: | 157 if fields and fields[-1] == package: |
162 return fields[1] | 158 return fields[1] |
163 return None | 159 return None |
164 | 160 |
165 def _find_install_location_for_package(self, package): | 161 def _find_install_location_for_package(self, package): |
166 pm_command = ['adb', 'shell', 'pm', 'path', package] | 162 pm_command = [ADB_PATH, 'shell', 'pm', 'path', package] |
167 pm_output = subprocess.check_output(pm_command) | 163 pm_output = subprocess.check_output(pm_command) |
168 # e.g. package:/data/app/org.chromium.mojo.shell-1/base.apk | 164 # e.g. package:/data/app/org.chromium.mojo.shell-1/base.apk |
169 return pm_output.split(':')[-1] | 165 return pm_output.split(':')[-1] |
170 | 166 |
171 def start_command(self, args): | 167 def start_command(self, args): |
172 # FIXME: Lame that we use self for a command-specific variable. | 168 # FIXME: Lame that we use self for a command-specific variable. |
173 self.paths = self._create_paths_for_build_dir(args.build_dir) | 169 self.paths = self._create_paths_for_build_dir(args.build_dir) |
174 self.stop_command(None) # Quit any existing process. | 170 self.stop_command(None) # Quit any existing process. |
175 | 171 |
176 if not os.path.exists(self.paths.mojo_shell_path): | 172 if not os.path.exists(self.paths.mojo_shell_path): |
177 print "mojo_shell not found in build_dir '%s'" % args.build_dir | 173 print "mojo_shell not found in build_dir '%s'" % args.build_dir |
178 print "Are you sure you sure that's a valid build_dir location?" | 174 print "Are you sure you sure that's a valid build_dir location?" |
179 print "See skydb start --help for more info" | 175 print "See skydb start --help for more info" |
180 sys.exit(2) | 176 sys.exit(2) |
181 | 177 |
182 # FIXME: This is probably not the right way to compute is_android | 178 # FIXME: This is probably not the right way to compute is_android |
183 # from the build directory? | 179 # from the build directory? |
184 gn_args = gn_args_from_build_dir(self.paths.build_dir) | 180 gn_args = gn_args_from_build_dir(self.paths.build_dir) |
185 is_android = 'android_sdk_version' in gn_args | 181 is_android = 'android_sdk_version' in gn_args |
186 | 182 |
187 sky_server = self.sky_server_for_args(args) | 183 sky_server = self.sky_server_for_args(args) |
188 self.pids['sky_server_pid'] = sky_server.start() | 184 self.pids['sky_server_pid'] = sky_server.start() |
189 self.pids['sky_server_port'] = sky_server.port | 185 self.pids['sky_server_port'] = sky_server.port |
190 self.pids['sky_server_root'] = sky_server.root | 186 self.pids['sky_server_root'] = sky_server.root |
191 | 187 |
192 self.pids['build_dir'] = self.paths.build_dir | 188 self.pids['build_dir'] = self.paths.build_dir |
193 self.pids['sky_command_port'] = args.command_port | 189 self.pids['sky_command_port'] = args.command_port |
194 | 190 |
195 if is_android: | 191 if is_android: |
196 # Pray to the build/android gods in their misspelled tongue. | |
197 constants.SetOutputDirectort(self.paths.build_dir) | |
198 | |
199 # We could make installing conditional on an argument. | 192 # We could make installing conditional on an argument. |
200 apk_path = os.path.join(self.paths.build_dir, 'apks', | 193 apk_path = os.path.join(self.paths.build_dir, 'apks', |
201 ANDROID_APK_NAME) | 194 ANDROID_APK_NAME) |
202 subprocess.check_call(['adb', 'install', '-r', apk_path]) | 195 subprocess.check_call([ADB_PATH, 'install', '-r', apk_path]) |
203 | 196 |
204 device = self._connect_to_device() | 197 port_string = 'tcp:%s' % sky_server.port |
205 self.pids['device_serial'] = device.GetDevice() | 198 subprocess.check_call([ |
206 | 199 ADB_PATH, 'reverse', port_string, port_string |
207 forwarder.Forwarder.Map([(0, sky_server.port)], device) | 200 ]) |
208 device_http_port = forwarder.Forwarder.DevicePortForHostPort( | 201 self.pids['remote_sky_server_port'] = sky_server.port |
209 sky_server.port) | |
210 self.pids['remote_sky_server_port'] = device_http_port | |
211 | 202 |
212 port_string = 'tcp:%s' % args.command_port | 203 port_string = 'tcp:%s' % args.command_port |
213 subprocess.check_call([ | 204 subprocess.check_call([ |
214 'adb', 'forward', port_string, port_string | 205 ADB_PATH, 'forward', port_string, port_string |
215 ]) | 206 ]) |
216 self.pids['remote_sky_command_port'] = args.command_port | 207 self.pids['remote_sky_command_port'] = args.command_port |
217 | 208 |
218 shell_command = self._build_mojo_shell_command(args, is_android) | 209 shell_command = self._build_mojo_shell_command(args, is_android) |
219 | 210 |
220 # On android we can't launch inside gdb, but rather have to attach. | 211 # On android we can't launch inside gdb, but rather have to attach. |
221 if not is_android and args.gdb: | 212 if not is_android and args.gdb: |
222 shell_command = ['gdbserver', ':%d' % GDB_PORT] + shell_command | 213 shell_command = ['gdbserver', ':%d' % GDB_PORT] + shell_command |
223 | 214 |
224 print ' '.join(map(pipes.quote, shell_command)) | 215 print ' '.join(map(pipes.quote, shell_command)) |
(...skipping 19 matching lines...) Expand all Loading... |
244 self.pids['mojo_shell_pid'] = start_command_pid | 235 self.pids['mojo_shell_pid'] = start_command_pid |
245 | 236 |
246 if args.gdb and is_android: | 237 if args.gdb and is_android: |
247 # We push our own copy of gdbserver with the package since | 238 # We push our own copy of gdbserver with the package since |
248 # the default gdbserver is a different version from our gdb. | 239 # the default gdbserver is a different version from our gdb. |
249 package_path = \ | 240 package_path = \ |
250 self._find_install_location_for_package(ANDROID_PACKAGE) | 241 self._find_install_location_for_package(ANDROID_PACKAGE) |
251 gdb_server_path = os.path.join( | 242 gdb_server_path = os.path.join( |
252 os.path.dirname(package_path), 'lib/arm/gdbserver') | 243 os.path.dirname(package_path), 'lib/arm/gdbserver') |
253 gdbserver_cmd = [ | 244 gdbserver_cmd = [ |
254 'adb', 'shell', | 245 ADB_PATH, 'shell', |
255 gdb_server_path, '--attach', | 246 gdb_server_path, '--attach', |
256 ':%d' % GDB_PORT, | 247 ':%d' % GDB_PORT, |
257 str(self.pids['mojo_shell_pid']) | 248 str(self.pids['mojo_shell_pid']) |
258 ] | 249 ] |
259 print ' '.join(map(pipes.quote, gdbserver_cmd)) | 250 print ' '.join(map(pipes.quote, gdbserver_cmd)) |
260 self.pids['adb_shell_gdbserver_pid'] = \ | 251 self.pids['adb_shell_gdbserver_pid'] = \ |
261 subprocess.Popen(gdbserver_cmd).pid | 252 subprocess.Popen(gdbserver_cmd).pid |
262 | 253 |
263 port_string = 'tcp:%d' % GDB_PORT | 254 port_string = 'tcp:%d' % GDB_PORT |
264 subprocess.check_call([ | 255 subprocess.check_call([ |
265 'adb', 'forward', port_string, port_string | 256 ADB_PATH, 'forward', port_string, port_string |
266 ]) | 257 ]) |
267 self.pids['remote_gdbserver_port'] = GDB_PORT | 258 self.pids['remote_gdbserver_port'] = GDB_PORT |
268 | 259 |
269 if not args.gdb: | 260 if not args.gdb: |
270 if not self._wait_for_sky_command_port(): | 261 if not self._wait_for_sky_command_port(): |
271 logging.error('Failed to start sky') | 262 logging.error('Failed to start sky') |
272 self.stop_command(None) | 263 self.stop_command(None) |
273 else: | |
274 self.load_command(args) | |
275 else: | 264 else: |
276 print 'No load issued, connect with gdb first and then run load.' | 265 # We could just run gdb_attach_command here, but when I do that |
| 266 # it auto-suspends in my zsh. Unclear why. |
| 267 # self.gdb_attach_command(args) |
| 268 print "Run skydb gdb_attach to attach." |
277 | 269 |
278 def _kill_if_exists(self, key, name): | 270 def _kill_if_exists(self, key, name): |
279 pid = self.pids.pop(key, None) | 271 pid = self.pids.pop(key, None) |
280 if not pid: | 272 if not pid: |
281 logging.info('No pid for %s, nothing to do.' % name) | 273 logging.info('No pid for %s, nothing to do.' % name) |
282 return | 274 return |
283 logging.info('Killing %s (%d).' % (name, pid)) | 275 logging.info('Killing %s (%d).' % (name, pid)) |
284 try: | 276 try: |
285 os.kill(pid, signal.SIGTERM) | 277 os.kill(pid, signal.SIGTERM) |
286 except OSError: | 278 except OSError: |
287 logging.info('%s (%d) already gone.' % (name, pid)) | 279 logging.info('%s (%d) already gone.' % (name, pid)) |
288 | 280 |
289 def stop_command(self, args): | 281 def stop_command(self, args): |
290 # TODO(eseidel): mojo_shell crashes when attempting graceful shutdown. | 282 # TODO(eseidel): mojo_shell crashes when attempting graceful shutdown. |
291 # self._run_basic_command('/quit') | 283 # self._run_basic_command('/quit') |
292 | 284 |
293 self._kill_if_exists('sky_server_pid', 'sky_server') | 285 self._kill_if_exists('sky_server_pid', 'sky_server') |
294 | 286 |
295 # We could be much more surgical here: | |
296 if 'remote_sky_server_port' in self.pids: | 287 if 'remote_sky_server_port' in self.pids: |
297 device = android_commands.AndroidCommands( | 288 port_string = 'tcp:%s' % self.pids['remote_sky_server_port'] |
298 self.pids['device_serial']) | 289 subprocess.call([ADB_PATH, 'reverse', '--remove', port_string]) |
299 forwarder.Forwarder.UnmapAllDevicePorts(device) | |
300 | 290 |
301 if 'remote_sky_command_port' in self.pids: | 291 if 'remote_sky_command_port' in self.pids: |
302 # adb forward --remove takes the *host* port, not the remote port. | 292 # adb forward --remove takes the *host* port, not the remote port. |
303 port_string = 'tcp:%s' % self.pids['sky_command_port'] | 293 port_string = 'tcp:%s' % self.pids['sky_command_port'] |
304 subprocess.call(['adb', 'forward', '--remove', port_string]) | 294 subprocess.call([ADB_PATH, 'forward', '--remove', port_string]) |
305 | 295 |
306 subprocess.call([ | 296 subprocess.call([ |
307 'adb', 'shell', 'am', 'force-stop', ANDROID_PACKAGE]) | 297 ADB_PATH, 'shell', 'am', 'force-stop', ANDROID_PACKAGE]) |
308 else: | 298 else: |
309 # Only try to kill mojo_shell if it's running locally. | 299 # Only try to kill mojo_shell if it's running locally. |
310 self._kill_if_exists('mojo_shell_pid', 'mojo_shell') | 300 self._kill_if_exists('mojo_shell_pid', 'mojo_shell') |
311 | 301 |
312 if 'remote_gdbserver_port' in self.pids: | 302 if 'remote_gdbserver_port' in self.pids: |
313 self._kill_if_exists('adb_shell_gdbserver_pid', | 303 self._kill_if_exists('adb_shell_gdbserver_pid', |
314 'adb shell gdbserver') | 304 'adb shell gdbserver') |
315 | 305 |
316 port_string = 'tcp:%s' % self.pids['remote_gdbserver_port'] | 306 port_string = 'tcp:%s' % self.pids['remote_gdbserver_port'] |
317 subprocess.call(['adb', 'forward', '--remove', port_string]) | 307 subprocess.call([ADB_PATH, 'forward', '--remove', port_string]) |
318 self.pids = {} # Clear out our pid file. | 308 self.pids = {} # Clear out our pid file. |
319 | 309 |
| 310 def _url_from_args(self, args): |
| 311 if urlparse.urlparse(args.url_or_path).scheme: |
| 312 return args.url_or_path |
| 313 # The load happens on the remote device, use the remote port. |
| 314 remote_sky_server_port = self.pids.get('remote_sky_server_port', |
| 315 self.pids['sky_server_port']) |
| 316 return SkyServer.url_for_path(remote_sky_server_port, |
| 317 self.pids['sky_server_root'], args.url_or_path) |
| 318 |
320 def load_command(self, args): | 319 def load_command(self, args): |
321 if not urlparse.urlparse(args.url_or_path).scheme: | 320 self._run_basic_command('/load', self._url_from_args(args)) |
322 # The load happens on the remote device, use the remote port. | |
323 remote_sky_server_port = self.pids.get('remote_sky_server_port', | |
324 self.pids['sky_server_port']) | |
325 url = SkyServer.url_for_path(remote_sky_server_port, | |
326 self.pids['sky_server_root'], args.url_or_path) | |
327 else: | |
328 url = args.url_or_path | |
329 self._run_basic_command('/load', url) | |
330 | 321 |
331 def _read_mojo_map(self): | 322 def _read_mojo_map(self): |
332 # TODO(eseidel): Does not work for android. | 323 # TODO(eseidel): Does not work for android. |
333 mojo_map_path = "/tmp/mojo_shell.%d.maps" % self.pids['mojo_shell_pid'] | 324 mojo_map_path = "/tmp/mojo_shell.%d.maps" % self.pids['mojo_shell_pid'] |
334 with open(mojo_map_path, 'r') as maps_file: | 325 with open(mojo_map_path, 'r') as maps_file: |
335 lines = maps_file.read().strip().split('\n') | 326 lines = maps_file.read().strip().split('\n') |
336 return dict(map(lambda line: line.split(' '), lines)) | 327 return dict(map(lambda line: line.split(' '), lines)) |
337 | 328 |
338 def stop_tracing_command(self, args): | 329 def stop_tracing_command(self, args): |
339 file_name = args.file_name | 330 file_name = args.file_name |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 time.sleep(1) | 421 time.sleep(1) |
431 | 422 |
432 def logcat_command(self, args): | 423 def logcat_command(self, args): |
433 TAGS = [ | 424 TAGS = [ |
434 'AndroidHandler', | 425 'AndroidHandler', |
435 'MojoMain', | 426 'MojoMain', |
436 'MojoShellActivity', | 427 'MojoShellActivity', |
437 'MojoShellApplication', | 428 'MojoShellApplication', |
438 'chromium', | 429 'chromium', |
439 ] | 430 ] |
440 subprocess.call(['adb', 'logcat', '-d', '-s'] + TAGS) | 431 subprocess.call([ADB_PATH, 'logcat', '-d', '-s'] + TAGS) |
441 | 432 |
442 def _pull_system_libraries(self, system_libs_root): | 433 def _pull_system_libraries(self, system_libs_root): |
443 # Pull down the system libraries this pid has already mapped in. | 434 # Pull down the system libraries this pid has already mapped in. |
444 # TODO(eseidel): This does not handle dynamic loads. | 435 # TODO(eseidel): This does not handle dynamic loads. |
445 library_cacher_path = os.path.join( | 436 library_cacher_path = os.path.join( |
446 self.paths.sky_tools_directory, 'android_library_cacher.py') | 437 self.paths.sky_tools_directory, 'android_library_cacher.py') |
447 subprocess.call([ | 438 subprocess.call([ |
448 library_cacher_path, system_libs_root, self.pids['mojo_shell_pid'] | 439 library_cacher_path, system_libs_root, self.pids['mojo_shell_pid'] |
449 ]) | 440 ]) |
450 | 441 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 | 490 |
500 # TODO(eseidel): We need to look up the toolchain somehow? | 491 # TODO(eseidel): We need to look up the toolchain somehow? |
501 gdb_path = os.path.join(SRC_ROOT, 'third_party/android_tools/ndk/' | 492 gdb_path = os.path.join(SRC_ROOT, 'third_party/android_tools/ndk/' |
502 'toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/' | 493 'toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/' |
503 'bin/arm-linux-androideabi-gdb') | 494 'bin/arm-linux-androideabi-gdb') |
504 | 495 |
505 # Set solib-search-path after letting android modify symbol_search_paths | 496 # Set solib-search-path after letting android modify symbol_search_paths |
506 eval_commands.append( | 497 eval_commands.append( |
507 'set solib-search-path %s' % ':'.join(symbol_search_paths)) | 498 'set solib-search-path %s' % ':'.join(symbol_search_paths)) |
508 | 499 |
509 exec_command = ['/usr/bin/strace', '-o', 'trace.txt', gdb_path] | 500 exec_command = [gdb_path] |
510 for command in eval_commands: | 501 for command in eval_commands: |
511 exec_command += ['--eval-command', command] | 502 exec_command += ['--eval-command', command] |
512 | 503 |
513 print " ".join(exec_command) | 504 print " ".join(exec_command) |
514 | 505 |
515 # Write out our pid file before we exec ourselves. | 506 # Write out our pid file before we exec ourselves. |
516 self._write_pid_file(PID_FILE_PATH, self.pids) | 507 self._write_pid_file(PID_FILE_PATH, self.pids) |
517 | 508 |
518 # Exec gdb directly to avoid python intercepting symbols, etc. | 509 # Exec gdb directly to avoid python intercepting symbols, etc. |
519 os.execv(exec_command[0], exec_command) | 510 os.execv(exec_command[0], exec_command) |
520 | 511 |
521 def print_crash_command(self, args): | 512 def print_crash_command(self, args): |
522 logcat_cmd = ['adb', 'logcat', '-d'] | 513 logcat_cmd = [ADB_PATH, 'logcat', '-d'] |
523 logcat = subprocess.Popen(logcat_cmd, stdout=subprocess.PIPE) | 514 logcat = subprocess.Popen(logcat_cmd, stdout=subprocess.PIPE) |
524 | 515 |
525 stack_path = os.path.join(SRC_ROOT, | 516 stack_path = os.path.join(SRC_ROOT, |
526 'tools', 'android_stack_parser', 'stack') | 517 'tools', 'android_stack_parser', 'stack') |
527 stack = subprocess.Popen([stack_path, '-'], stdin=logcat.stdout) | 518 stack = subprocess.Popen([stack_path, '-'], stdin=logcat.stdout) |
528 logcat.wait() | 519 logcat.wait() |
529 stack.wait() | 520 stack.wait() |
530 | 521 |
531 def pids_command(self, args): | 522 def pids_command(self, args): |
532 print json.dumps(self.pids, indent=1) | 523 print json.dumps(self.pids, indent=1) |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 load_parser.set_defaults(func=self.load_command) | 589 load_parser.set_defaults(func=self.load_command) |
599 | 590 |
600 args = parser.parse_args() | 591 args = parser.parse_args() |
601 args.func(args) | 592 args.func(args) |
602 | 593 |
603 self._write_pid_file(PID_FILE_PATH, self.pids) | 594 self._write_pid_file(PID_FILE_PATH, self.pids) |
604 | 595 |
605 | 596 |
606 if __name__ == '__main__': | 597 if __name__ == '__main__': |
607 SkyDebugger().main() | 598 SkyDebugger().main() |
OLD | NEW |