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 datetime | 6 import datetime |
7 import email.utils | 7 import email.utils |
8 import hashlib | 8 import hashlib |
9 import itertools | 9 import itertools |
10 import json | 10 import json |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 class AndroidShell(object): | 184 class AndroidShell(object): |
185 """ Allows to set up and run a given mojo shell binary on an Android device. | 185 """ Allows to set up and run a given mojo shell binary on an Android device. |
186 | 186 |
187 Args: | 187 Args: |
188 shell_apk_path: path to the shell Android binary | 188 shell_apk_path: path to the shell Android binary |
189 local_dir: directory where locally build Mojo apps will be served, optional | 189 local_dir: directory where locally build Mojo apps will be served, optional |
190 adb_path: path to adb, optional if adb is in PATH | 190 adb_path: path to adb, optional if adb is in PATH |
191 target_device: device to run on, if multiple devices are connected | 191 target_device: device to run on, if multiple devices are connected |
192 """ | 192 """ |
193 def __init__( | 193 def __init__( |
194 self, shell_apk_path, local_dir=None, adb_path="adb", target_device=None): | 194 self, shell_apk_path, local_dir=None, adb_path="adb", target_device=None, |
| 195 target_package=MOJO_SHELL_PACKAGE_NAME): |
195 self.shell_apk_path = shell_apk_path | 196 self.shell_apk_path = shell_apk_path |
196 self.adb_path = adb_path | 197 self.adb_path = adb_path |
197 self.local_dir = local_dir | 198 self.local_dir = local_dir |
198 self.target_device = target_device | 199 self.target_device = target_device |
| 200 self.target_package = target_package |
199 | 201 |
200 def _CreateADBCommand(self, args): | 202 def _CreateADBCommand(self, args): |
201 adb_command = [self.adb_path] | 203 adb_command = [self.adb_path] |
202 if self.target_device: | 204 if self.target_device: |
203 adb_command.extend(['-s', self.target_device]) | 205 adb_command.extend(['-s', self.target_device]) |
204 adb_command.extend(args) | 206 adb_command.extend(args) |
205 return adb_command | 207 return adb_command |
206 | 208 |
207 def _ReadFifo(self, fifo_path, pipe, on_fifo_closed, max_attempts=5): | 209 def _ReadFifo(self, fifo_path, pipe, on_fifo_closed, max_attempts=5): |
208 """ | 210 """ |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 """ Prepares for StartShell: runs adb as root and installs the apk. If no | 320 """ Prepares for StartShell: runs adb as root and installs the apk. If no |
319 --origin is specified, local http server will be set up to serve files from | 321 --origin is specified, local http server will be set up to serve files from |
320 the build directory along with port forwarding. | 322 the build directory along with port forwarding. |
321 | 323 |
322 Returns arguments that should be appended to shell argument list.""" | 324 Returns arguments that should be appended to shell argument list.""" |
323 if 'cannot run as root' in subprocess.check_output( | 325 if 'cannot run as root' in subprocess.check_output( |
324 self._CreateADBCommand(['root'])): | 326 self._CreateADBCommand(['root'])): |
325 raise Exception("Unable to run adb as root.") | 327 raise Exception("Unable to run adb as root.") |
326 subprocess.check_call( | 328 subprocess.check_call( |
327 self._CreateADBCommand(['install', '-r', self.shell_apk_path, '-i', | 329 self._CreateADBCommand(['install', '-r', self.shell_apk_path, '-i', |
328 MOJO_SHELL_PACKAGE_NAME])) | 330 self.target_package])) |
329 atexit.register(self.StopShell) | 331 atexit.register(self.StopShell) |
330 | 332 |
331 extra_shell_args = [] | 333 extra_shell_args = [] |
332 origin_url = origin if origin else self._StartHttpServerForDirectory( | 334 if origin: |
333 self.local_dir, DEFAULT_BASE_PORT if fixed_port else 0) | 335 origin_url = origin if origin else self._StartHttpServerForDirectory( |
334 extra_shell_args.append("--origin=" + origin_url) | 336 self.local_dir, DEFAULT_BASE_PORT if fixed_port else 0) |
| 337 extra_shell_args.append("--origin=" + origin_url) |
335 | 338 |
336 return extra_shell_args | 339 return extra_shell_args |
337 | 340 |
338 def StartShell(self, | 341 def StartShell(self, |
339 arguments, | 342 arguments, |
340 stdout=None, | 343 stdout=None, |
341 on_application_stop=None, | 344 on_application_stop=None, |
342 fixed_port=True): | 345 fixed_port=True): |
343 """ | 346 """ |
344 Starts the mojo shell, passing it the given arguments. | 347 Starts the mojo shell, passing it the given arguments. |
345 | 348 |
346 The |arguments| list must contain the "--origin=" arg from PrepareShellRun. | 349 The |arguments| list must contain the "--origin=" arg from PrepareShellRun. |
347 If |stdout| is not None, it should be a valid argument for subprocess.Popen. | 350 If |stdout| is not None, it should be a valid argument for subprocess.Popen. |
348 """ | 351 """ |
349 STDOUT_PIPE = "/data/data/%s/stdout.fifo" % MOJO_SHELL_PACKAGE_NAME | 352 STDOUT_PIPE = "/data/data/%s/stdout.fifo" % self.target_package |
350 | 353 |
351 cmd = self._CreateADBCommand([ | 354 cmd = self._CreateADBCommand([ |
352 'shell', | 355 'shell', |
353 'am', | 356 'am', |
354 'start', | 357 'start', |
355 '-S', | 358 '-S', |
356 '-a', 'android.intent.action.VIEW', | 359 '-a', 'android.intent.action.VIEW', |
357 '-n', '%s/.MojoShellActivity' % MOJO_SHELL_PACKAGE_NAME]) | 360 '-n', '%s/%s.MojoShellActivity' % (self.target_package, |
| 361 MOJO_SHELL_PACKAGE_NAME)]) |
358 | 362 |
359 parameters = [] | 363 parameters = [] |
360 if stdout or on_application_stop: | 364 if stdout or on_application_stop: |
361 subprocess.check_call(self._CreateADBCommand( | 365 subprocess.check_call(self._CreateADBCommand( |
362 ['shell', 'rm', STDOUT_PIPE])) | 366 ['shell', 'rm', '-f', STDOUT_PIPE])) |
363 parameters.append('--fifo-path=%s' % STDOUT_PIPE) | 367 parameters.append('--fifo-path=%s' % STDOUT_PIPE) |
364 self._ReadFifo(STDOUT_PIPE, stdout, on_application_stop) | 368 self._ReadFifo(STDOUT_PIPE, stdout, on_application_stop) |
365 # The origin has to be specified whether it's local or external. | |
366 assert any("--origin=" in arg for arg in arguments) | |
367 | 369 |
368 # Extract map-origin arguments. | 370 # Extract map-origin arguments. |
369 map_parameters, other_parameters = _Split(arguments, _IsMapOrigin) | 371 map_parameters, other_parameters = _Split(arguments, _IsMapOrigin) |
370 parameters += other_parameters | 372 parameters += other_parameters |
371 parameters += self._StartHttpServerForOriginMappings(map_parameters, | 373 parameters += self._StartHttpServerForOriginMappings(map_parameters, |
372 fixed_port) | 374 fixed_port) |
373 | 375 |
374 if parameters: | 376 if parameters: |
375 encodedParameters = json.dumps(parameters) | 377 encodedParameters = json.dumps(parameters) |
376 cmd += ['--es', 'encodedParameters', encodedParameters] | 378 cmd += ['--es', 'encodedParameters', encodedParameters] |
377 | 379 |
378 with open(os.devnull, 'w') as devnull: | 380 with open(os.devnull, 'w') as devnull: |
379 subprocess.Popen(cmd, stdout=devnull).wait() | 381 subprocess.Popen(cmd, stdout=devnull).wait() |
380 | 382 |
381 def StopShell(self): | 383 def StopShell(self): |
382 """ | 384 """ |
383 Stops the mojo shell. | 385 Stops the mojo shell. |
384 """ | 386 """ |
385 subprocess.check_call(self._CreateADBCommand(['shell', | 387 subprocess.check_call(self._CreateADBCommand(['shell', |
386 'am', | 388 'am', |
387 'force-stop', | 389 'force-stop', |
388 MOJO_SHELL_PACKAGE_NAME])) | 390 self.target_package])) |
389 | 391 |
390 def CleanLogs(self): | 392 def CleanLogs(self): |
391 """ | 393 """ |
392 Cleans the logs on the device. | 394 Cleans the logs on the device. |
393 """ | 395 """ |
394 subprocess.check_call(self._CreateADBCommand(['logcat', '-c'])) | 396 subprocess.check_call(self._CreateADBCommand(['logcat', '-c'])) |
395 | 397 |
396 def ShowLogs(self): | 398 def ShowLogs(self): |
397 """ | 399 """ |
398 Displays the log for the mojo shell. | 400 Displays the log for the mojo shell. |
399 | 401 |
400 Returns the process responsible for reading the logs. | 402 Returns the process responsible for reading the logs. |
401 """ | 403 """ |
402 logcat = subprocess.Popen(self._CreateADBCommand([ | 404 logcat = subprocess.Popen(self._CreateADBCommand([ |
403 'logcat', | 405 'logcat', |
404 '-s', | 406 '-s', |
405 ' '.join(LOGCAT_TAGS)]), | 407 ' '.join(LOGCAT_TAGS)]), |
406 stdout=sys.stdout) | 408 stdout=sys.stdout) |
407 atexit.register(_ExitIfNeeded, logcat) | 409 atexit.register(_ExitIfNeeded, logcat) |
408 return logcat | 410 return logcat |
OLD | NEW |