Commit 9a068c65 authored by Zachary Anderson's avatar Zachary Anderson Committed by GitHub

[fuchsia_reload] Find and attach to the first instance of the named app (#8830)

parent 41d99685
......@@ -9,12 +9,14 @@ import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/platform.dart';
import '../cache.dart';
import '../device.dart';
import '../flx.dart' as flx;
import '../fuchsia/fuchsia_device.dart';
import '../globals.dart';
import '../run_hot.dart';
import '../runner/flutter_command.dart';
import '../vmservice.dart';
// Usage:
// With e.g. flutter_gallery already running, a HotRunner can be attached to it
......@@ -62,6 +64,8 @@ class FuchsiaReloadCommand extends FlutterCommand {
@override
Future<Null> runCommand() async {
Cache.releaseLockEarly();
_validateArguments();
// Find the network ports used on the device by VM service instances.
......@@ -70,24 +74,57 @@ class FuchsiaReloadCommand extends FlutterCommand {
throwToolExit("Couldn't find any running Observatory instances.");
}
for (int port in servicePorts) {
printStatus("Fuchsia service port: $port");
printTrace("Fuchsia service port: $port");
}
// TODO(zra): Check that there are running VM services on the returned
// Check that there are running VM services on the returned
// ports, and find the Isolates that are running the target app.
final String isolateName = "$_projectName\$main";
final List<int> targetPorts = await _filterPorts(servicePorts, isolateName);
if (targetPorts.length == 0) {
throwToolExit("No VMs found running $_projectName");
}
for (int port in targetPorts) {
printTrace("Found $_projectName at $port");
}
// Set up a device and hot runner and attach the hot runner to the first
// vm service we found.
final int firstPort = servicePorts[0];
final FuchsiaDevice device = new FuchsiaDevice("$_address:$firstPort");
final int firstPort = targetPorts[0];
final String fullAddress = "$_address:$firstPort";
final FuchsiaDevice device = new FuchsiaDevice(fullAddress);
final HotRunner hotRunner = new HotRunner(
device,
debuggingOptions: new DebuggingOptions.enabled(getBuildMode()),
target: _target,
projectRootPath: _fuchsiaProjectPath,
packagesFilePath: _dotPackagesPath);
final Uri observatoryUri = Uri.parse("http://$_address:$firstPort");
await hotRunner.attach(observatoryUri);
final Uri observatoryUri = Uri.parse("http://$fullAddress");
printStatus("Connecting to $_projectName at $observatoryUri");
await hotRunner.attach(observatoryUri, isolateFilter: isolateName);
}
// Find ports where there is a view isolate with the given name
Future<List<int>> _filterPorts(List<int> ports, String isolateFilter) async {
final List<int> result = new List<int>();
for (int port in ports) {
final String addr = "http://$_address:$port";
final Uri uri = Uri.parse(addr);
final VMService vmService = VMService.connect(uri);
await vmService.getVM();
await vmService.waitForViews();
if (vmService.vm.firstView == null) {
printTrace("Found no views at $addr");
continue;
}
for (FlutterView v in vmService.vm.views) {
printTrace("At $addr, found view: ${v.uiIsolate.name}");
if (v.uiIsolate.name.indexOf(isolateFilter) == 0) {
result.add(port);
}
}
}
return result;
}
void _validateArguments() {
......
......@@ -209,7 +209,7 @@ abstract class ResidentRunner {
_loggingSubscription = null;
}
Future<Null> connectToServiceProtocol(Uri uri) async {
Future<Null> connectToServiceProtocol(Uri uri, {String isolateFilter}) async {
if (!debuggingOptions.debuggingEnabled) {
return new Future<Null>.error('Error the service protocol is not enabled.');
}
......@@ -217,15 +217,11 @@ abstract class ResidentRunner {
printTrace('Connected to service protocol: $uri');
await vmService.getVM();
// Refresh the view list.
await vmService.vm.refreshViews();
for (int i = 0; vmService.vm.mainView == null && i < 5; i++) {
// If the VM doesn't yet have a view, wait for one to show up.
printTrace('Waiting for Flutter view');
await new Future<Null>.delayed(const Duration(seconds: 1));
await vmService.vm.refreshViews();
}
currentView = vmService.vm.mainView;
// Refresh the view list, and wait a bit for the list to populate.
await vmService.waitForViews();
currentView = (isolateFilter == null)
? vmService.vm.firstView
: vmService.vm.firstViewWithName(isolateFilter);
if (currentView == null)
throwToolExit('No Flutter view is available');
......
......@@ -115,7 +115,7 @@ class ColdRunner extends ResidentRunner {
if (vmService != null) {
await vmService.vm.refreshViews();
printTrace('Connected to ${vmService.vm.mainView}\.');
printTrace('Connected to ${vmService.vm.firstView}\.');
}
if (vmService != null && traceStartup) {
......
......@@ -90,10 +90,12 @@ class HotRunner extends ResidentRunner {
Future<int> attach(Uri observatoryUri, {
Completer<DebugConnectionInfo> connectionInfoCompleter,
Completer<Null> appStartedCompleter,
String isolateFilter,
}) async {
_observatoryUri = observatoryUri;
try {
await connectToServiceProtocol(_observatoryUri);
await connectToServiceProtocol(
_observatoryUri, isolateFilter: isolateFilter);
} catch (error) {
printError('Error connecting to the service protocol: $error');
return 2;
......@@ -121,7 +123,7 @@ class HotRunner extends ResidentRunner {
}
await vmService.vm.refreshViews();
printTrace('Connected to ${vmService.vm.mainView}.');
printTrace('Connected to $currentView.');
if (stayResident) {
setupTerminal();
......@@ -302,7 +304,7 @@ class HotRunner extends ResidentRunner {
Future<Null> _launchInView(Uri entryUri,
Uri packagesUri,
Uri assetsDirectoryUri) async {
final FlutterView view = vmService.vm.mainView;
final FlutterView view = currentView;
return view.runFromSource(entryUri, packagesUri, assetsDirectoryUri);
}
......
......@@ -170,6 +170,16 @@ class VMService {
Future<VM> getVM() {
return _vm.reload();
}
Future<Null> waitForViews({int attempts = 5, int attemptSeconds = 1}) async {
await vm.refreshViews();
for (int i = 0; (vm.firstView == null) && (i < attempts); i++) {
// If the VM doesn't yet have a view, wait for one to show up.
printTrace('Waiting for Flutter view');
await new Future<Null>.delayed(new Duration(seconds: attemptSeconds));
await vm.refreshViews();
}
}
}
/// An error that is thrown when constructing/updating a service object.
......@@ -743,9 +753,20 @@ class VM extends ServiceObjectOwner {
await vmService.vm.invokeRpc('_flutter.listViews', timeout: kLongRequestTimeout);
}
FlutterView get mainView {
Iterable<FlutterView> get views => _viewCache.values;
FlutterView get firstView {
return _viewCache.values.isEmpty ? null : _viewCache.values.first;
}
FlutterView firstViewWithName(String isolateFilter) {
if (_viewCache.values.isEmpty) {
return null;
}
return _viewCache.values.firstWhere(
(FlutterView v) => v.uiIsolate.name.contains(isolateFilter),
orElse: () => null);
}
}
/// An isolate running inside the VM. Instances of the Isolate class are always
......
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