Commit 20e53552 authored by James Robinson's avatar James Robinson

Teach sky_tools mojo_run to run on Android (using mojo devtools)

This teaches sky_tools mojo_run --android to invoke mojo's devtool's mojo_run
script with the right flags for invoking sky_viewer on android. This tells the
devtools script to load sky_viewer.mojo from https://storage.googleapis.com/...
and to load app.flx (or whatever the developer specifies as --app) from the
filesystem using the devtools http server.
parent 542da8cc
...@@ -17,8 +17,8 @@ class _ArtifactStore { ...@@ -17,8 +17,8 @@ class _ArtifactStore {
_ArtifactStore._(); _ArtifactStore._();
// Keep in sync with https://github.com/flutter/engine/blob/master/sky/tools/big_red_button.py#L50 // 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) { String googleStorageUrl(String category, String platform, String engineRevision) {
return 'https://storage.googleapis.com/mojo/sky/${category}/linux-x64/${engineRevision}/${name}'; return 'https://storage.googleapis.com/mojo/sky/${category}/${platform}/${engineRevision}/';
} }
Future _downloadFile(String url, File file) async { Future _downloadFile(String url, File file) async {
...@@ -34,10 +34,6 @@ class _ArtifactStore { ...@@ -34,10 +34,6 @@ class _ArtifactStore {
_logging.fine('Wrote file'); _logging.fine('Wrote file');
} }
Future<String> _getEngineRevision(String packageRoot) {
return new File(packageRoot + '/sky_engine/REVISION').readAsString();
}
Future<Directory> _cacheDir(String engineRevision, String packageRoot) async { Future<Directory> _cacheDir(String engineRevision, String packageRoot) async {
String cacheDirPath = '${packageRoot}/sky_tools/cache/sky_engine/${engineRevision}/'; String cacheDirPath = '${packageRoot}/sky_tools/cache/sky_engine/${engineRevision}/';
Directory cacheDir = new Directory(cacheDirPath); Directory cacheDir = new Directory(cacheDirPath);
...@@ -52,8 +48,13 @@ class _ArtifactStore { ...@@ -52,8 +48,13 @@ class _ArtifactStore {
return artifact == Artifact.FlutterCompiler; return artifact == Artifact.FlutterCompiler;
} }
Future<String> getEngineRevision(String packageRoot) {
return new File(packageRoot + '/sky_engine/REVISION').readAsString();
}
Future<String> getPath(Artifact artifact, String packageRoot) async { Future<String> getPath(Artifact artifact, String packageRoot) async {
String engineRevision = await _getEngineRevision(packageRoot); String engineRevision = await getEngineRevision(packageRoot);
Directory cacheDir = await _cacheDir(engineRevision, packageRoot); Directory cacheDir = await _cacheDir(engineRevision, packageRoot);
String category, name; String category, name;
...@@ -72,8 +73,8 @@ class _ArtifactStore { ...@@ -72,8 +73,8 @@ class _ArtifactStore {
File cachedFile = new File(cacheDir.path + name); File cachedFile = new File(cacheDir.path + name);
if (!await cachedFile.exists()) { if (!await cachedFile.exists()) {
_logging.info('Downloading ${name} from the cloud, one moment please...'); _logging.info('Downloading ${name} from the cloud, one moment please...');
String googleStorageUrl = _googleStorageUrl(category, name, engineRevision); String url = googleStorageUrl(category, 'linux-x64', engineRevision) + name;
await _downloadFile(googleStorageUrl, cachedFile); await _downloadFile(url, cachedFile);
if (_needsToBeExecutable(artifact)) { if (_needsToBeExecutable(artifact)) {
ProcessResult result = await Process.run('chmod', ['u+x', cachedFile.path]); ProcessResult result = await Process.run('chmod', ['u+x', cachedFile.path]);
if (result.exitCode != 0) throw new Exception(result.stderr); if (result.exitCode != 0) throw new Exception(result.stderr);
......
// 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<int> runCommandAndStreamOutput(String command, List<String> 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;
}
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
library sky_tools.run_mojo; library sky_tools.run_mojo;
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:args/args.dart'; import 'package:args/args.dart';
...@@ -14,6 +13,7 @@ import 'package:path/path.dart' as path; ...@@ -14,6 +13,7 @@ import 'package:path/path.dart' as path;
import 'artifacts.dart'; import 'artifacts.dart';
import 'common.dart'; import 'common.dart';
import 'process.dart';
final Logger _logging = new Logger('sky_tools.run_mojo'); final Logger _logging = new Logger('sky_tools.run_mojo');
...@@ -22,10 +22,11 @@ class RunMojoCommandHandler extends CommandHandler { ...@@ -22,10 +22,11 @@ class RunMojoCommandHandler extends CommandHandler {
ArgParser get parser { ArgParser get parser {
ArgParser parser = new ArgParser(); ArgParser parser = new ArgParser();
parser.addFlag('android', negatable: false, help: 'Run on an Android device');
parser.addFlag('help', abbr: 'h', negatable: false); 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('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; return parser;
} }
...@@ -37,6 +38,36 @@ class RunMojoCommandHandler extends CommandHandler { ...@@ -37,6 +38,36 @@ class RunMojoCommandHandler extends CommandHandler {
return file.absolute.path; return file.absolute.path;
} }
Future<int> _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<String> 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<int> _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<String> mojoRunArgs = [
'mojo:window_manager file://${appPath}',
'--url-mappings=mojo:window_manager=mojo:kiosk_wm,mojo:sky_viewer=file://${viewerPath}'
];
return runCommandAndStreamOutput(mojoShellPath, mojoRunArgs);
}
@override @override
Future<int> processArgResults(ArgResults results) async { Future<int> processArgResults(ArgResults results) async {
if (results['help']) { if (results['help']) {
...@@ -48,23 +79,12 @@ class RunMojoCommandHandler extends CommandHandler { ...@@ -48,23 +79,12 @@ class RunMojoCommandHandler extends CommandHandler {
return 1; return 1;
} }
String packageRoot = results['package-root']; String packageRoot = results['package-root'];
String engineRevision = await artifactStore.getEngineRevision(packageRoot);
String appPath = await _makePathAbsolute(results['app']); String appPath = await _makePathAbsolute(results['app']);
String viewerPath = await _makePathAbsolute(await artifactStore.getPath(Artifact.SkyViewerMojo, packageRoot)); if (results['android']) {
String mojoShellPath = await _makePathAbsolute(path.join(results['mojo-path'], 'mojo_shell')); return _runAndroid(results, appPath, engineRevision);
List<String> mojoRunArgs = [ } else {
'mojo:window_manager file://${appPath}', return _runLinux(results, appPath, packageRoot, engineRevision);
'--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;
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment