| OLD | NEW |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 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 import atexit | 5 import atexit |
| 6 import hashlib | 6 import hashlib |
| 7 import logging | 7 import logging |
| 8 import os | 8 import os |
| 9 import os.path | 9 import os.path |
| 10 import random | 10 import random |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 | 119 |
| 120 def _run(): | 120 def _run(): |
| 121 def _wait_for_fifo(): | 121 def _wait_for_fifo(): |
| 122 for _ in xrange(max_attempts): | 122 for _ in xrange(max_attempts): |
| 123 output = subprocess.check_output(fifo_command).strip() | 123 output = subprocess.check_output(fifo_command).strip() |
| 124 if output == fifo_path: | 124 if output == fifo_path: |
| 125 return | 125 return |
| 126 time.sleep(1) | 126 time.sleep(1) |
| 127 if on_fifo_closed: | 127 if on_fifo_closed: |
| 128 on_fifo_closed() | 128 on_fifo_closed() |
| 129 raise Exception("Unable to find fifo.") | 129 raise Exception('Unable to find fifo.') |
| 130 _wait_for_fifo() | 130 _wait_for_fifo() |
| 131 stdout_cat = subprocess.Popen( | 131 stdout_cat = subprocess.Popen( |
| 132 self._adb_command(['shell', 'run-as', _MOJO_SHELL_PACKAGE_NAME, | 132 self._adb_command(['shell', 'run-as', _MOJO_SHELL_PACKAGE_NAME, |
| 133 'cat', fifo_path]), stdout=pipe) | 133 'cat', fifo_path]), stdout=pipe) |
| 134 atexit.register(_exit_if_needed, stdout_cat) | 134 atexit.register(_exit_if_needed, stdout_cat) |
| 135 stdout_cat.wait() | 135 stdout_cat.wait() |
| 136 if on_fifo_closed: | 136 if on_fifo_closed: |
| 137 on_fifo_closed() | 137 on_fifo_closed() |
| 138 | 138 |
| 139 thread = threading.Thread(target=_run, name="StdoutRedirector") | 139 thread = threading.Thread(target=_run, name='StdoutRedirector') |
| 140 thread.start() | 140 thread.start() |
| 141 | 141 |
| 142 def _find_available_device_port(self): | 142 def _find_available_device_port(self): |
| 143 netstat_output = subprocess.check_output( | 143 netstat_output = subprocess.check_output( |
| 144 self._adb_command(['shell', 'netstat'])) | 144 self._adb_command(['shell', 'netstat'])) |
| 145 return _find_available_port(netstat_output) | 145 return _find_available_port(netstat_output) |
| 146 | 146 |
| 147 def _forward_device_port_to_host(self, device_port, host_port): | 147 def _forward_device_port_to_host(self, device_port, host_port): |
| 148 """Maps the device port to the host port. If |device_port| is 0, a random | 148 """Maps the device port to the host port. If |device_port| is 0, a random |
| 149 available port is chosen. | 149 available port is chosen. |
| 150 | 150 |
| 151 Returns: | 151 Returns: |
| 152 The device port. | 152 The device port. |
| 153 """ | 153 """ |
| 154 assert host_port | 154 assert host_port |
| 155 | 155 |
| 156 if device_port == 0: | 156 if device_port == 0: |
| 157 # TODO(ppi): Should we have a retry loop to handle the unlikely races? | 157 # TODO(ppi): Should we have a retry loop to handle the unlikely races? |
| 158 device_port = self._find_available_device_port() | 158 device_port = self._find_available_device_port() |
| 159 subprocess.check_call(self._adb_command([ | 159 subprocess.check_call(self._adb_command([ |
| 160 "reverse", "tcp:%d" % device_port, "tcp:%d" % host_port])) | 160 'reverse', 'tcp:%d' % device_port, 'tcp:%d' % host_port])) |
| 161 | 161 |
| 162 def _unmap_port(): | 162 def _unmap_port(): |
| 163 unmap_command = self._adb_command([ | 163 unmap_command = self._adb_command([ |
| 164 "reverse", "--remove", "tcp:%d" % device_port]) | 164 'reverse', '--remove', 'tcp:%d' % device_port]) |
| 165 subprocess.Popen(unmap_command) | 165 subprocess.Popen(unmap_command) |
| 166 atexit.register(_unmap_port) | 166 atexit.register(_unmap_port) |
| 167 return device_port | 167 return device_port |
| 168 | 168 |
| 169 def _forward_host_port_to_device(self, host_port, device_port): | 169 def _forward_host_port_to_device(self, host_port, device_port): |
| 170 """Maps the host port to the device port. If |host_port| is 0, a random | 170 """Maps the host port to the device port. If |host_port| is 0, a random |
| 171 available port is chosen. | 171 available port is chosen. |
| 172 | 172 |
| 173 Returns: | 173 Returns: |
| 174 The host port. | 174 The host port. |
| 175 """ | 175 """ |
| 176 assert device_port | 176 assert device_port |
| 177 | 177 |
| 178 if host_port == 0: | 178 if host_port == 0: |
| 179 # TODO(ppi): Should we have a retry loop to handle the unlikely races? | 179 # TODO(ppi): Should we have a retry loop to handle the unlikely races? |
| 180 host_port = _find_available_host_port() | 180 host_port = _find_available_host_port() |
| 181 subprocess.check_call(self._adb_command([ | 181 subprocess.check_call(self._adb_command([ |
| 182 "forward", 'tcp:%d' % host_port, 'tcp:%d' % device_port])) | 182 'forward', 'tcp:%d' % host_port, 'tcp:%d' % device_port])) |
| 183 | 183 |
| 184 def _unmap_port(): | 184 def _unmap_port(): |
| 185 unmap_command = self._adb_command([ | 185 unmap_command = self._adb_command([ |
| 186 "forward", "--remove", "tcp:%d" % device_port]) | 186 'forward', '--remove', 'tcp:%d' % device_port]) |
| 187 subprocess.Popen(unmap_command) | 187 subprocess.Popen(unmap_command) |
| 188 atexit.register(_unmap_port) | 188 atexit.register(_unmap_port) |
| 189 return host_port | 189 return host_port |
| 190 | 190 |
| 191 def _is_shell_package_installed(self): | 191 def _is_shell_package_installed(self): |
| 192 # Adb should print one line if the package is installed and return empty | 192 # Adb should print one line if the package is installed and return empty |
| 193 # string otherwise. | 193 # string otherwise. |
| 194 return len(subprocess.check_output(self._adb_command([ | 194 return len(subprocess.check_output(self._adb_command([ |
| 195 'shell', 'pm', 'list', 'packages', _MOJO_SHELL_PACKAGE_NAME]))) > 0 | 195 'shell', 'pm', 'list', 'packages', _MOJO_SHELL_PACKAGE_NAME]))) > 0 |
| 196 | 196 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 """Starts the mojo shell, passing it the given arguments. | 289 """Starts the mojo shell, passing it the given arguments. |
| 290 | 290 |
| 291 Args: | 291 Args: |
| 292 arguments: List of arguments for the shell. | 292 arguments: List of arguments for the shell. |
| 293 stdout: Valid argument for subprocess.Popen() or None. | 293 stdout: Valid argument for subprocess.Popen() or None. |
| 294 """ | 294 """ |
| 295 if not self.stop_shell_registered: | 295 if not self.stop_shell_registered: |
| 296 atexit.register(self.stop_shell) | 296 atexit.register(self.stop_shell) |
| 297 self.stop_shell_registered = True | 297 self.stop_shell_registered = True |
| 298 | 298 |
| 299 STDOUT_PIPE = "/data/data/%s/stdout.fifo" % _MOJO_SHELL_PACKAGE_NAME | 299 STDOUT_PIPE = '/data/data/%s/stdout.fifo' % _MOJO_SHELL_PACKAGE_NAME |
| 300 | 300 |
| 301 cmd = self._adb_command(['shell', 'am', 'start', | 301 cmd = self._adb_command(['shell', 'am', 'start', |
| 302 '-S', | 302 '-S', |
| 303 '-a', 'android.intent.action.VIEW', | 303 '-a', 'android.intent.action.VIEW', |
| 304 '-n', '%s/.MojoShellActivity' % | 304 '-n', '%s/.MojoShellActivity' % |
| 305 _MOJO_SHELL_PACKAGE_NAME]) | 305 _MOJO_SHELL_PACKAGE_NAME]) |
| 306 | 306 |
| 307 parameters = [] | 307 parameters = [] |
| 308 if stdout or on_application_stop: | 308 if stdout or on_application_stop: |
| 309 # Remove any leftover fifo file after the previous run. | 309 # Remove any leftover fifo file after the previous run. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 def _forward_observatories_as_needed(): | 371 def _forward_observatories_as_needed(): |
| 372 while True: | 372 while True: |
| 373 line = logcat.stdout.readline() | 373 line = logcat.stdout.readline() |
| 374 if not line: | 374 if not line: |
| 375 break | 375 break |
| 376 match = re.search(r'Observatory listening on http://127.0.0.1:(\d+)', | 376 match = re.search(r'Observatory listening on http://127.0.0.1:(\d+)', |
| 377 line) | 377 line) |
| 378 if match: | 378 if match: |
| 379 device_port = int(match.group(1)) | 379 device_port = int(match.group(1)) |
| 380 host_port = self._forward_host_port_to_device(0, device_port) | 380 host_port = self._forward_host_port_to_device(0, device_port) |
| 381 print ("Dart observatory available at the host at http://127.0.0.1:%d" | 381 print ('Dart observatory available at the host at http://127.0.0.1:%d' |
| 382 % host_port) | 382 % host_port) |
| 383 | 383 |
| 384 logcat_watch_thread = threading.Thread( | 384 logcat_watch_thread = threading.Thread( |
| 385 target=_forward_observatories_as_needed) | 385 target=_forward_observatories_as_needed) |
| 386 logcat_watch_thread.daemon = True | 386 logcat_watch_thread.daemon = True |
| 387 logcat_watch_thread.start() | 387 logcat_watch_thread.start() |
| 388 | 388 |
| 389 @overrides(Shell) | 389 @overrides(Shell) |
| 390 def serve_local_directories(self, mappings, port, reuse_servers=False): | 390 def serve_local_directories(self, mappings, port, reuse_servers=False): |
| 391 assert mappings | 391 assert mappings |
| 392 if reuse_servers: | 392 if reuse_servers: |
| 393 assert port, 'Cannot reuse the server when |port| is 0.' | 393 assert port, 'Cannot reuse the server when |port| is 0.' |
| 394 server_address = ('127.0.0.1', port) | 394 server_address = ('127.0.0.1', port) |
| 395 else: | 395 else: |
| 396 server_address = http_server.start_http_server(mappings, port) | 396 server_address = http_server.start_http_server(mappings, port) |
| 397 | 397 |
| 398 return 'http://127.0.0.1:%d/' % self._forward_device_port_to_host( | 398 return 'http://127.0.0.1:%d/' % self._forward_device_port_to_host( |
| 399 port, server_address[1]) | 399 port, server_address[1]) |
| 400 | 400 |
| 401 @overrides(Shell) | 401 @overrides(Shell) |
| 402 def forward_host_port_to_shell(self, host_port): | 402 def forward_host_port_to_shell(self, host_port): |
| 403 self._forward_host_port_to_device(host_port, host_port) | 403 self._forward_host_port_to_device(host_port, host_port) |
| 404 | 404 |
| 405 @overrides(Shell) | 405 @overrides(Shell) |
| 406 def run(self, arguments): | 406 def run(self, arguments): |
| 407 self.clean_logs() | 407 self.clean_logs() |
| 408 self.forward_observatory_ports() | 408 self.forward_observatory_ports() |
| 409 | 409 |
| 410 p = self.show_logs(); | 410 p = self.show_logs() |
| 411 self.start_shell(arguments, sys.stdout, p.terminate) | 411 self.start_shell(arguments, sys.stdout, p.terminate) |
| 412 p.wait() | 412 p.wait() |
| 413 return None | 413 return None |
| 414 | 414 |
| 415 @overrides(Shell) | 415 @overrides(Shell) |
| 416 def run_and_get_output(self, arguments, timeout=None): | 416 def run_and_get_output(self, arguments, timeout=None): |
| 417 class Results: | 417 class Results: |
| 418 """Workaround for Python scoping rules that prevent assigning to variables | 418 """Workaround for Python scoping rules that prevent assigning to variables |
| 419 from the outer scope. | 419 from the outer scope. |
| 420 """ | 420 """ |
| 421 output = None | 421 output = None |
| 422 | 422 |
| 423 def do_run(): | 423 def do_run(): |
| 424 (r, w) = os.pipe() | 424 (r, w) = os.pipe() |
| 425 with os.fdopen(r, "r") as rf: | 425 with os.fdopen(r, 'r') as rf: |
| 426 with os.fdopen(w, "w") as wf: | 426 with os.fdopen(w, 'w') as wf: |
| 427 self.start_shell(arguments, wf, wf.close) | 427 self.start_shell(arguments, wf, wf.close) |
| 428 Results.output = rf.read() | 428 Results.output = rf.read() |
| 429 | 429 |
| 430 run_thread = threading.Thread(target=do_run) | 430 run_thread = threading.Thread(target=do_run) |
| 431 run_thread.start() | 431 run_thread.start() |
| 432 run_thread.join(timeout) | 432 run_thread.join(timeout) |
| 433 | 433 |
| 434 if run_thread.is_alive(): | 434 if run_thread.is_alive(): |
| 435 self.stop_shell() | 435 self.stop_shell() |
| 436 return None, Results.output, True | 436 return None, Results.output, True |
| 437 return None, Results.output, False | 437 return None, Results.output, False |
| OLD | NEW |