diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart index 29420f679ef..9d0b1895d88 100644 --- a/packages/flutter_tools/lib/src/artifacts.dart +++ b/packages/flutter_tools/lib/src/artifacts.dart @@ -17,8 +17,8 @@ class _ArtifactStore { _ArtifactStore._(); // Keep in sync with https://github.com/flutter/engine/blob/master/sky/tools/big_red_button.py#L50 - String _googleStorageUrl(String category, String name, String engineRevision) { - return 'https://storage.googleapis.com/mojo/sky/${category}/linux-x64/${engineRevision}/${name}'; + String googleStorageUrl(String category, String platform, String engineRevision) { + return 'https://storage.googleapis.com/mojo/sky/${category}/${platform}/${engineRevision}/'; } Future _downloadFile(String url, File file) async { @@ -34,10 +34,6 @@ class _ArtifactStore { _logging.fine('Wrote file'); } - Future _getEngineRevision(String packageRoot) { - return new File(packageRoot + '/sky_engine/REVISION').readAsString(); - } - Future _cacheDir(String engineRevision, String packageRoot) async { String cacheDirPath = '${packageRoot}/sky_tools/cache/sky_engine/${engineRevision}/'; Directory cacheDir = new Directory(cacheDirPath); @@ -52,8 +48,13 @@ class _ArtifactStore { return artifact == Artifact.FlutterCompiler; } + + Future getEngineRevision(String packageRoot) { + return new File(packageRoot + '/sky_engine/REVISION').readAsString(); + } + Future getPath(Artifact artifact, String packageRoot) async { - String engineRevision = await _getEngineRevision(packageRoot); + String engineRevision = await getEngineRevision(packageRoot); Directory cacheDir = await _cacheDir(engineRevision, packageRoot); String category, name; @@ -72,8 +73,8 @@ class _ArtifactStore { File cachedFile = new File(cacheDir.path + name); if (!await cachedFile.exists()) { _logging.info('Downloading ${name} from the cloud, one moment please...'); - String googleStorageUrl = _googleStorageUrl(category, name, engineRevision); - await _downloadFile(googleStorageUrl, cachedFile); + String url = googleStorageUrl(category, 'linux-x64', engineRevision) + name; + await _downloadFile(url, cachedFile); if (_needsToBeExecutable(artifact)) { ProcessResult result = await Process.run('chmod', ['u+x', cachedFile.path]); if (result.exitCode != 0) throw new Exception(result.stderr); diff --git a/packages/flutter_tools/lib/src/process.dart b/packages/flutter_tools/lib/src/process.dart new file mode 100644 index 00000000000..898ab861970 --- /dev/null +++ b/packages/flutter_tools/lib/src/process.dart @@ -0,0 +1,26 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +library sky_tools.process; + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:logging/logging.dart'; + +final Logger _logging = new Logger('sky_tools.process'); + +// This runs the command and streams stdout/stderr from the child process to this process' stdout/stderr. +Future runCommandAndStreamOutput(String command, List args) async { + _logging.fine("Starting ${command} with args: ${args}"); + Process proc = await Process.start(command, args); + proc.stdout.transform(UTF8.decoder).listen((data) { + stdout.write(data); + }); + proc.stderr.transform(UTF8.decoder).listen((data) { + stderr.write(data); + }); + return proc.exitCode; +} diff --git a/packages/flutter_tools/lib/src/run_mojo.dart b/packages/flutter_tools/lib/src/run_mojo.dart index d396c714763..5330ea701da 100644 --- a/packages/flutter_tools/lib/src/run_mojo.dart +++ b/packages/flutter_tools/lib/src/run_mojo.dart @@ -5,7 +5,6 @@ library sky_tools.run_mojo; import 'dart:async'; -import 'dart:convert'; import 'dart:io'; import 'package:args/args.dart'; @@ -14,6 +13,7 @@ import 'package:path/path.dart' as path; import 'artifacts.dart'; import 'common.dart'; +import 'process.dart'; final Logger _logging = new Logger('sky_tools.run_mojo'); @@ -22,10 +22,11 @@ class RunMojoCommandHandler extends CommandHandler { ArgParser get parser { ArgParser parser = new ArgParser(); + parser.addFlag('android', negatable: false, help: 'Run on an Android device'); parser.addFlag('help', abbr: 'h', negatable: false); - parser.addOption('package-root', defaultsTo: 'packages'); - parser.addOption('mojo-path', help: 'Path to directory containing mojo_shell and services'); parser.addOption('app', defaultsTo: 'app.flx'); + parser.addOption('mojo-path', help: 'Path to directory containing mojo_shell and services'); + parser.addOption('package-root', defaultsTo: 'packages'); return parser; } @@ -37,6 +38,36 @@ class RunMojoCommandHandler extends CommandHandler { return file.absolute.path; } + Future _runAndroid(ArgResults results, String appPath, String engineRevision) async { + String skyViewerUrl = artifactStore.googleStorageUrl('viewer', 'android-arm', engineRevision); + String command = await _makePathAbsolute(path.join(results['mojo-path'], 'mojo', 'devtools', 'common', 'mojo_run')); + String appName = path.basename(appPath); + String appDir = path.dirname(appPath); + List args = [ + '--android', '--release', '--embed', 'http://app/$appName', + '--map-origin=http://app/=$appDir', + '--map-origin=http://sky_viewer/=$skyViewerUrl', + '--url-mappings=mojo:sky_viewer=http://sky_viewer/sky_viewer.mojo', + ]; + if (_logging.level <= Level.INFO) { + args.add('--verbose'); + if (_logging.level <= Level.FINE) { + args.add('--verbose'); + } + } + return runCommandAndStreamOutput(command, args); + } + + Future _runLinux(ArgResults results, String appPath, String packageRoot, String engineRevision) async { + String viewerPath = await _makePathAbsolute(await artifactStore.getPath(Artifact.SkyViewerMojo, packageRoot)); + String mojoShellPath = await _makePathAbsolute(path.join(results['mojo-path'], 'out', 'Release', 'mojo_shell')); + List mojoRunArgs = [ + 'mojo:window_manager file://${appPath}', + '--url-mappings=mojo:window_manager=mojo:kiosk_wm,mojo:sky_viewer=file://${viewerPath}' + ]; + return runCommandAndStreamOutput(mojoShellPath, mojoRunArgs); + } + @override Future processArgResults(ArgResults results) async { if (results['help']) { @@ -48,23 +79,12 @@ class RunMojoCommandHandler extends CommandHandler { return 1; } String packageRoot = results['package-root']; + String engineRevision = await artifactStore.getEngineRevision(packageRoot); String appPath = await _makePathAbsolute(results['app']); - String viewerPath = await _makePathAbsolute(await artifactStore.getPath(Artifact.SkyViewerMojo, packageRoot)); - String mojoShellPath = await _makePathAbsolute(path.join(results['mojo-path'], 'mojo_shell')); - List mojoRunArgs = [ - 'mojo:window_manager file://${appPath}', - '--url-mappings=mojo:window_manager=mojo:kiosk_wm,mojo:sky_viewer=file://${viewerPath}' - ]; - _logging.fine("Starting ${mojoShellPath} with args: ${mojoRunArgs}"); - Process proc = await Process.start(mojoShellPath, mojoRunArgs); - proc.stdout.transform(UTF8.decoder).listen((data) { - stdout.write(data); - }); - proc.stderr.transform(UTF8.decoder).listen((data) { - stderr.write(data); - }); - int exitCode = await proc.exitCode; - if (exitCode != 0) throw new Exception(exitCode); - return 0; + if (results['android']) { + return _runAndroid(results, appPath, engineRevision); + } else { + return _runLinux(results, appPath, packageRoot, engineRevision); + } } }