Unverified Commit 598f2ab0 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

Cleanups to resident runner and flutter device classes (#45673)

parent b39949ff
...@@ -645,7 +645,7 @@ abstract class DeviceLogReader { ...@@ -645,7 +645,7 @@ abstract class DeviceLogReader {
/// Some logs can be obtained from a VM service stream. /// Some logs can be obtained from a VM service stream.
/// Set this after the VM services are connected. /// Set this after the VM services are connected.
List<VMService> connectedVMServices; VMService connectedVMService;
@override @override
String toString() => name; String toString() => name;
...@@ -675,7 +675,7 @@ class NoOpDeviceLogReader implements DeviceLogReader { ...@@ -675,7 +675,7 @@ class NoOpDeviceLogReader implements DeviceLogReader {
int appPid; int appPid;
@override @override
List<VMService> connectedVMServices; VMService connectedVMService;
@override @override
Stream<String> get logLines => const Stream<String>.empty(); Stream<String> get logLines => const Stream<String>.empty();
......
...@@ -578,33 +578,30 @@ class IOSDeviceLogReader extends DeviceLogReader { ...@@ -578,33 +578,30 @@ class IOSDeviceLogReader extends DeviceLogReader {
String get name => device.name; String get name => device.name;
@override @override
List<VMService> get connectedVMServices => _connectedVMServices; VMService get connectedVMService => _connectedVMService;
List<VMService> _connectedVMServices; VMService _connectedVMService;
@override @override
set connectedVMServices(List<VMService> connectedVMServices) { set connectedVMService(VMService connectedVmService) {
_listenToUnifiedLoggingEvents(connectedVMServices); _listenToUnifiedLoggingEvents(connectedVmService);
_connectedVMServices = connectedVMServices; _connectedVMService = connectedVmService;
} }
static const int _minimumUniversalLoggingSdkVersion = 13; static const int _minimumUniversalLoggingSdkVersion = 13;
Future<void> _listenToUnifiedLoggingEvents(List<VMService> vmServices) async { Future<void> _listenToUnifiedLoggingEvents(VMService connectedVmService) async {
if (device.majorSdkVersion < _minimumUniversalLoggingSdkVersion) { if (device.majorSdkVersion < _minimumUniversalLoggingSdkVersion) {
return; return;
} }
for (VMService vmService in vmServices) { // The VM service will not publish logging events unless the debug stream is being listened to.
// The VM service will not publish logging events unless the debug stream is being listened to. // onDebugEvent listens to this stream as a side effect.
// onDebugEvent listens to this stream as a side effect. unawaited(connectedVmService.onDebugEvent);
unawaited(vmService.onDebugEvent); _loggingSubscriptions.add((await connectedVmService.onStdoutEvent).listen((ServiceEvent event) {
_loggingSubscriptions.add((await vmService.onStdoutEvent).listen((ServiceEvent event) { final String logMessage = event.message;
final String logMessage = event.message; if (logMessage.isNotEmpty) {
if (logMessage.isNotEmpty) { _linesController.add(logMessage);
_linesController.add(logMessage); }
} }));
}));
}
_connectedVMServices = connectedVMServices;
} }
void _listenToSysLog () { void _listenToSysLog () {
......
...@@ -134,7 +134,7 @@ class FlutterDevice { ...@@ -134,7 +134,7 @@ class FlutterDevice {
final Device device; final Device device;
final ResidentCompiler generator; final ResidentCompiler generator;
Stream<Uri> observatoryUris; Stream<Uri> observatoryUris;
List<VMService> vmServices; VMService vmService;
DevFS devFS; DevFS devFS;
ApplicationPackage package; ApplicationPackage package;
List<String> fileSystemRoots; List<String> fileSystemRoots;
...@@ -191,8 +191,8 @@ class FlutterDevice { ...@@ -191,8 +191,8 @@ class FlutterDevice {
} }
printTrace('Successfully connected to service protocol: $observatoryUri'); printTrace('Successfully connected to service protocol: $observatoryUri');
vmServices = <VMService>[service]; vmService = service;
device.getLogReader(app: package).connectedVMServices = vmServices; device.getLogReader(app: package).connectedVMService = vmService;
completer.complete(); completer.complete();
await subscription.cancel(); await subscription.cancel();
}, onError: (dynamic error) { }, onError: (dynamic error) {
...@@ -208,37 +208,23 @@ class FlutterDevice { ...@@ -208,37 +208,23 @@ class FlutterDevice {
} }
Future<void> refreshViews() async { Future<void> refreshViews() async {
if (vmServices == null || vmServices.isEmpty) { if (vmService == null) {
return Future<void>.value(null); return;
} }
final List<Future<void>> futures = <Future<void>>[ await vmService.vm.refreshViews(waitForViews: true);
for (VMService service in vmServices) service.vm.refreshViews(waitForViews: true),
];
await Future.wait(futures);
} }
List<FlutterView> get views { List<FlutterView> get views {
if (vmServices == null) { if (vmService == null || vmService.isClosed) {
return <FlutterView>[]; return <FlutterView>[];
} }
return vmServices return (viewFilter != null
.where((VMService service) => !service.isClosed) ? vmService.vm.allViewsWithName(viewFilter)
.expand<FlutterView>( : vmService.vm.views).toList();
(VMService service) {
return viewFilter != null
? service.vm.allViewsWithName(viewFilter)
: service.vm.views;
},
)
.toList();
} }
Future<void> getVMs() async { Future<void> getVMs() => vmService.getVM();
for (VMService service in vmServices) {
await service.getVM();
}
}
Future<void> exitApps() async { Future<void> exitApps() async {
if (!device.supportsFlutterExit) { if (!device.supportsFlutterExit) {
...@@ -249,7 +235,6 @@ class FlutterDevice { ...@@ -249,7 +235,6 @@ class FlutterDevice {
if (flutterViews == null || flutterViews.isEmpty) { if (flutterViews == null || flutterViews.isEmpty) {
return; return;
} }
final List<Future<void>> futures = <Future<void>>[];
// If any of the flutter views are paused, we might not be able to // If any of the flutter views are paused, we might not be able to
// cleanly exit since the service extension may not have been registered. // cleanly exit since the service extension may not have been registered.
if (flutterViews.any((FlutterView view) { if (flutterViews.any((FlutterView view) {
...@@ -262,6 +247,7 @@ class FlutterDevice { ...@@ -262,6 +247,7 @@ class FlutterDevice {
await device.stopApp(package); await device.stopApp(package);
return; return;
} }
final List<Future<void>> futures = <Future<void>>[];
for (FlutterView view in flutterViews) { for (FlutterView view in flutterViews) {
if (view != null && view.uiIsolate != null) { if (view != null && view.uiIsolate != null) {
assert(!view.uiIsolate.pauseEvent.isPauseEvent); assert(!view.uiIsolate.pauseEvent.isPauseEvent);
...@@ -281,7 +267,7 @@ class FlutterDevice { ...@@ -281,7 +267,7 @@ class FlutterDevice {
}) { }) {
// One devFS per device. Shared by all running instances. // One devFS per device. Shared by all running instances.
devFS = DevFS( devFS = DevFS(
vmServices[0], vmService,
fsName, fsName,
rootDirectory, rootDirectory,
packagesFilePath: packagesFilePath, packagesFilePath: packagesFilePath,
...@@ -416,7 +402,7 @@ class FlutterDevice { ...@@ -416,7 +402,7 @@ class FlutterDevice {
} }
void initLogReader() { void initLogReader() {
device.getLogReader(app: package).appPid = vmServices.first.vm.pid; device.getLogReader(app: package).appPid = vmService.vm.pid;
} }
Future<int> runHot({ Future<int> runHot({
...@@ -736,7 +722,7 @@ abstract class ResidentRunner { ...@@ -736,7 +722,7 @@ abstract class ResidentRunner {
void writeVmserviceFile() { void writeVmserviceFile() {
if (debuggingOptions.vmserviceOutFile != null) { if (debuggingOptions.vmserviceOutFile != null) {
try { try {
final String address = flutterDevices.first.vmServices.first.wsAddress.toString(); final String address = flutterDevices.first.vmService.wsAddress.toString();
final File vmserviceOutFile = fs.file(debuggingOptions.vmserviceOutFile); final File vmserviceOutFile = fs.file(debuggingOptions.vmserviceOutFile);
vmserviceOutFile.createSync(recursive: true); vmserviceOutFile.createSync(recursive: true);
vmserviceOutFile.writeAsStringSync(address); vmserviceOutFile.writeAsStringSync(address);
...@@ -940,15 +926,13 @@ abstract class ResidentRunner { ...@@ -940,15 +926,13 @@ abstract class ResidentRunner {
// Listen for service protocol connection to close. // Listen for service protocol connection to close.
for (FlutterDevice device in flutterDevices) { for (FlutterDevice device in flutterDevices) {
for (VMService service in device.vmServices) { // This hooks up callbacks for when the connection stops in the future.
// This hooks up callbacks for when the connection stops in the future. // We don't want to wait for them. We don't handle errors in those callbacks'
// We don't want to wait for them. We don't handle errors in those callbacks' // futures either because they just print to logger and is not critical.
// futures either because they just print to logger and is not critical. unawaited(device.vmService.done.then<void>(
unawaited(service.done.then<void>( _serviceProtocolDone,
_serviceProtocolDone, onError: _serviceProtocolError,
onError: _serviceProtocolError, ).whenComplete(_serviceDisconnected));
).whenComplete(_serviceDisconnected));
}
} }
} }
......
...@@ -83,15 +83,15 @@ class ColdRunner extends ResidentRunner { ...@@ -83,15 +83,15 @@ class ColdRunner extends ResidentRunner {
if (flutterDevices.first.observatoryUris != null) { if (flutterDevices.first.observatoryUris != null) {
// For now, only support one debugger connection. // For now, only support one debugger connection.
connectionInfoCompleter?.complete(DebugConnectionInfo( connectionInfoCompleter?.complete(DebugConnectionInfo(
httpUri: flutterDevices.first.vmServices.first.httpAddress, httpUri: flutterDevices.first.vmService.httpAddress,
wsUri: flutterDevices.first.vmServices.first.wsAddress, wsUri: flutterDevices.first.vmService.wsAddress,
)); ));
} }
printTrace('Application running.'); printTrace('Application running.');
for (FlutterDevice device in flutterDevices) { for (FlutterDevice device in flutterDevices) {
if (device.vmServices == null) { if (device.vmService == null) {
continue; continue;
} }
device.initLogReader(); device.initLogReader();
...@@ -102,10 +102,10 @@ class ColdRunner extends ResidentRunner { ...@@ -102,10 +102,10 @@ class ColdRunner extends ResidentRunner {
if (traceStartup) { if (traceStartup) {
// Only trace startup for the first device. // Only trace startup for the first device.
final FlutterDevice device = flutterDevices.first; final FlutterDevice device = flutterDevices.first;
if (device.vmServices != null && device.vmServices.isNotEmpty) { if (device.vmService != null) {
printStatus('Tracing startup on ${device.device.name}.'); printStatus('Tracing startup on ${device.device.name}.');
await downloadStartupTrace( await downloadStartupTrace(
device.vmServices.first, device.vmService,
awaitFirstFrame: awaitFirstFrameWhenTracing, awaitFirstFrame: awaitFirstFrameWhenTracing,
); );
} }
...@@ -183,10 +183,9 @@ class ColdRunner extends ResidentRunner { ...@@ -183,10 +183,9 @@ class ColdRunner extends ResidentRunner {
bool haveAnything = false; bool haveAnything = false;
for (FlutterDevice device in flutterDevices) { for (FlutterDevice device in flutterDevices) {
final String dname = device.device.name; final String dname = device.device.name;
if (device.vmServices != null) { if (device.vmService != null) {
for (VMService vm in device.vmServices) { printStatus('An Observatory debugger and profiler on $dname is '
printStatus('An Observatory debugger and profiler on $dname is available at: ${vm.httpAddress}'); 'available at: ${device.vmService .httpAddress}');
}
} }
} }
if (supportsServiceProtocol) { if (supportsServiceProtocol) {
...@@ -212,7 +211,7 @@ class ColdRunner extends ResidentRunner { ...@@ -212,7 +211,7 @@ class ColdRunner extends ResidentRunner {
Future<void> preExit() async { Future<void> preExit() async {
for (FlutterDevice device in flutterDevices) { for (FlutterDevice device in flutterDevices) {
// If we're running in release mode, stop the app using the device logic. // If we're running in release mode, stop the app using the device logic.
if (device.vmServices == null || device.vmServices.isEmpty) { if (device.vmService == null) {
await device.device.stopApp(device.package); await device.device.stopApp(device.package);
} }
} }
......
...@@ -10,7 +10,6 @@ import 'package:meta/meta.dart'; ...@@ -10,7 +10,6 @@ import 'package:meta/meta.dart';
import 'package:pool/pool.dart'; import 'package:pool/pool.dart';
import 'base/async_guard.dart'; import 'base/async_guard.dart';
import 'base/common.dart';
import 'base/context.dart'; import 'base/context.dart';
import 'base/file_system.dart'; import 'base/file_system.dart';
import 'base/logger.dart'; import 'base/logger.dart';
...@@ -180,8 +179,8 @@ class HotRunner extends ResidentRunner { ...@@ -180,8 +179,8 @@ class HotRunner extends ResidentRunner {
// Only handle one debugger connection. // Only handle one debugger connection.
connectionInfoCompleter.complete( connectionInfoCompleter.complete(
DebugConnectionInfo( DebugConnectionInfo(
httpUri: flutterDevices.first.vmServices.first.httpAddress, httpUri: flutterDevices.first.vmService.httpAddress,
wsUri: flutterDevices.first.vmServices.first.wsAddress, wsUri: flutterDevices.first.vmService.wsAddress,
baseUri: baseUris.first.toString(), baseUri: baseUris.first.toString(),
), ),
); );
...@@ -428,23 +427,18 @@ class HotRunner extends ResidentRunner { ...@@ -428,23 +427,18 @@ class HotRunner extends ResidentRunner {
continue; continue;
} }
// Reload the isolate. // Reload the isolate.
final Completer<void> completer = Completer<void>(); futures.add(view.uiIsolate.reload().then((ServiceObject _) {
futures.add(completer.future); final ServiceEvent pauseEvent = view.uiIsolate.pauseEvent;
unawaited(view.uiIsolate.reload().then( if ((pauseEvent != null) && pauseEvent.isPauseEvent) {
(ServiceObject _) { // Resume the isolate so that it can be killed by the embedder.
final ServiceEvent pauseEvent = view.uiIsolate.pauseEvent; return view.uiIsolate.resume();
if ((pauseEvent != null) && pauseEvent.isPauseEvent) { }
// Resume the isolate so that it can be killed by the embedder. return null;
return view.uiIsolate.resume(); }));
}
return null;
},
).whenComplete(
() { completer.complete(null); },
));
} }
} }
await Future.wait(futures); await Future.wait(futures);
// We are now running from source. // We are now running from source.
_runningFromSnapshot = false; _runningFromSnapshot = false;
await _launchFromDevFS(mainPath + '.dill'); await _launchFromDevFS(mainPath + '.dill');
...@@ -718,12 +712,10 @@ class HotRunner extends ResidentRunner { ...@@ -718,12 +712,10 @@ class HotRunner extends ResidentRunner {
// running from snapshot to running from uploaded files. // running from snapshot to running from uploaded files.
await device.resetAssetDirectory(); await device.resetAssetDirectory();
} }
final Completer<DeviceReloadReport> completer = Completer<DeviceReloadReport>();
allReportsFutures.add(completer.future);
final List<Future<Map<String, dynamic>>> reportFutures = device.reloadSources( final List<Future<Map<String, dynamic>>> reportFutures = device.reloadSources(
entryPath, pause: pause, entryPath, pause: pause,
); );
unawaited(Future.wait(reportFutures).then( allReportsFutures.add(Future.wait(reportFutures).then(
(List<Map<String, dynamic>> reports) async { (List<Map<String, dynamic>> reports) async {
// TODO(aam): Investigate why we are validating only first reload report, // TODO(aam): Investigate why we are validating only first reload report,
// which seems to be current behavior // which seems to be current behavior
...@@ -733,7 +725,7 @@ class HotRunner extends ResidentRunner { ...@@ -733,7 +725,7 @@ class HotRunner extends ResidentRunner {
await device.updateReloadStatus( await device.updateReloadStatus(
validateReloadReport(firstReport, printErrors: false), validateReloadReport(firstReport, printErrors: false),
); );
completer.complete(DeviceReloadReport(device, reports)); return DeviceReloadReport(device, reports);
}, },
)); ));
} }
...@@ -795,13 +787,12 @@ class HotRunner extends ResidentRunner { ...@@ -795,13 +787,12 @@ class HotRunner extends ResidentRunner {
printTrace('Sending reload event to "${view.uiIsolate.name}"'); printTrace('Sending reload event to "${view.uiIsolate.name}"');
futuresViews.add(view.uiIsolate.reload()); futuresViews.add(view.uiIsolate.reload());
} }
final Completer<void> deviceCompleter = Completer<void>(); allDevices.add(Future.wait(futuresViews).whenComplete(() {
unawaited(Future.wait(futuresViews).whenComplete(() { return device.refreshViews();
deviceCompleter.complete(device.refreshViews());
})); }));
allDevices.add(deviceCompleter.future);
} }
await Future.wait(allDevices); await Future.wait(allDevices);
// We are now running from source. // We are now running from source.
_runningFromSnapshot = false; _runningFromSnapshot = false;
// Check if any isolates are paused. // Check if any isolates are paused.
...@@ -851,7 +842,7 @@ class HotRunner extends ResidentRunner { ...@@ -851,7 +842,7 @@ class HotRunner extends ResidentRunner {
} }
}(), }(),
]; ];
final Future<void> reassembleFuture = Future.wait<void>(futures).then<void>((List<void> values) { }); final Future<void> reassembleFuture = Future.wait<void>(futures);
await reassembleFuture.timeout( await reassembleFuture.timeout(
const Duration(seconds: 2), const Duration(seconds: 2),
onTimeout: () async { onTimeout: () async {
...@@ -987,9 +978,8 @@ class HotRunner extends ResidentRunner { ...@@ -987,9 +978,8 @@ class HotRunner extends ResidentRunner {
printStatus(message); printStatus(message);
for (FlutterDevice device in flutterDevices) { for (FlutterDevice device in flutterDevices) {
final String dname = device.device.name; final String dname = device.device.name;
for (VMService vm in device.vmServices) { printStatus('An Observatory debugger and profiler on $dname is '
printStatus('An Observatory debugger and profiler on $dname is available at: ${vm.httpAddress}'); 'available at: ${device.vmService.httpAddress}');
}
} }
final String quitMessage = _didAttach final String quitMessage = _didAttach
? 'To detach, press "d"; to quit, press "q".' ? 'To detach, press "d"; to quit, press "q".'
......
...@@ -104,7 +104,7 @@ void main() { ...@@ -104,7 +104,7 @@ void main() {
.thenAnswer((Invocation invocation) async { .thenAnswer((Invocation invocation) async {
return testUri; return testUri;
}); });
when(mockFlutterDevice.vmServices).thenReturn(<VMService>[mockVMService]); when(mockFlutterDevice.vmService).thenReturn(mockVMService);
when(mockFlutterDevice.refreshViews()).thenAnswer((Invocation invocation) async { }); when(mockFlutterDevice.refreshViews()).thenAnswer((Invocation invocation) async { });
when(mockFlutterDevice.reloadSources(any, pause: anyNamed('pause'))).thenReturn(<Future<Map<String, dynamic>>>[ when(mockFlutterDevice.reloadSources(any, pause: anyNamed('pause'))).thenReturn(<Future<Map<String, dynamic>>>[
Future<Map<String, dynamic>>.value(<String, dynamic>{ Future<Map<String, dynamic>>.value(<String, dynamic>{
...@@ -631,7 +631,7 @@ void main() { ...@@ -631,7 +631,7 @@ void main() {
); );
await flutterDevice.connect(); await flutterDevice.connect();
verify(mockLogReader.connectedVMServices = <VMService>[ mockVMService ]); verify(mockLogReader.connectedVMService = mockVMService);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
VMServiceConnector: () => (Uri httpUri, { VMServiceConnector: () => (Uri httpUri, {
ReloadSources reloadSources, ReloadSources reloadSources,
......
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