diff --git a/packages/flutter_tools/lib/src/commands/attach.dart b/packages/flutter_tools/lib/src/commands/attach.dart index bf42f805699..0cba1583819 100644 --- a/packages/flutter_tools/lib/src/commands/attach.dart +++ b/packages/flutter_tools/lib/src/commands/attach.dart @@ -16,6 +16,7 @@ import '../fuchsia/fuchsia_device.dart'; import '../globals.dart'; import '../protocol_discovery.dart'; import '../resident_runner.dart'; +import '../run_cold.dart'; import '../run_hot.dart'; import '../runner/flutter_command.dart'; @@ -176,6 +177,7 @@ class AttachCommand extends FlutterCommand { : Uri.parse('http://$ipv4Loopback:$localPort/'); } try { + final bool useHot = getBuildInfo().isDebug; final FlutterDevice flutterDevice = FlutterDevice( device, trackWidgetCreation: false, @@ -186,24 +188,32 @@ class AttachCommand extends FlutterCommand { targetModel: TargetModel(argResults['target-model']), ); flutterDevice.observatoryUris = [ observatoryUri ]; - final HotRunner hotRunner = hotRunnerFactory.build( - [flutterDevice], - target: targetFile, - debuggingOptions: DebuggingOptions.enabled(getBuildInfo()), - packagesFilePath: globalResults['packages'], - usesTerminalUI: daemon == null, - projectRootPath: argResults['project-root'], - dillOutputPath: argResults['output-dill'], - ipv6: usesIpv6, - ); + final List flutterDevices = [flutterDevice]; + final DebuggingOptions debuggingOptions = DebuggingOptions.enabled(getBuildInfo()); + final ResidentRunner runner = useHot ? + hotRunnerFactory.build( + flutterDevices, + target: targetFile, + debuggingOptions: debuggingOptions, + packagesFilePath: globalResults['packages'], + usesTerminalUI: daemon == null, + projectRootPath: argResults['project-root'], + dillOutputPath: argResults['output-dill'], + ipv6: usesIpv6, + ) + : ColdRunner( + flutterDevices, + target: targetFile, + debuggingOptions: debuggingOptions, + ipv6: usesIpv6, + ); if (attachLogger) { flutterDevice.startEchoingDeviceLog(); } - if (daemon != null) { AppInstance app; try { - app = await daemon.appDomain.launch(hotRunner, hotRunner.attach, + app = await daemon.appDomain.launch(runner, runner.attach, device, null, true, fs.currentDirectory); } catch (error) { throwToolExit(error.toString()); @@ -212,7 +222,7 @@ class AttachCommand extends FlutterCommand { if (result != 0) throwToolExit(null, exitCode: result); } else { - await hotRunner.attach(); + await runner.attach(); } } finally { final List ports = device.portForwarder.forwardedPorts.toList(); diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart index d5928e325a9..6cc1db335c4 100644 --- a/packages/flutter_tools/lib/src/resident_runner.dart +++ b/packages/flutter_tools/lib/src/resident_runner.dart @@ -489,6 +489,11 @@ abstract class ResidentRunner { bool shouldBuild = true }); + Future attach({ + Completer connectionInfoCompleter, + Completer appStartedCompleter, + }); + bool get supportsRestart => false; Future restart({ bool fullRestart = false, bool pauseAfterRestart = false, String reason }) { diff --git a/packages/flutter_tools/lib/src/run_cold.dart b/packages/flutter_tools/lib/src/run_cold.dart index f963a4006c0..7fc18dba4c0 100644 --- a/packages/flutter_tools/lib/src/run_cold.dart +++ b/packages/flutter_tools/lib/src/run_cold.dart @@ -11,6 +11,7 @@ import 'device.dart'; import 'globals.dart'; import 'resident_runner.dart'; import 'tracing.dart'; +import 'vmservice.dart'; // TODO(mklim): Test this, flutter/flutter#23031. class ColdRunner extends ResidentRunner { @@ -34,6 +35,7 @@ class ColdRunner extends ResidentRunner { final bool traceStartup; final File applicationBinary; + bool _didAttach = false; @override Future run({ @@ -111,12 +113,50 @@ class ColdRunner extends ResidentRunner { return 0; } + @override + Future attach({ + Completer connectionInfoCompleter, + Completer appStartedCompleter, + }) async { + _didAttach = true; + try { + await connectToServiceProtocol(); + } catch (error) { + printError('Error connecting to the service protocol: $error'); + return 2; + } + for (FlutterDevice device in flutterDevices) { + device.initLogReader(); + } + await refreshViews(); + for (FlutterDevice device in flutterDevices) { + for (FlutterView view in device.views) { + printTrace('Connected to $view.'); + } + } + if (stayResident) { + setupTerminal(); + registerSignalHandlers(); + } + appStartedCompleter?.complete(); + if (stayResident) { + return waitForAppToFinish(); + } + await cleanupAtFinish(); + return 0; + } + @override Future handleTerminalCommand(String code) async { } @override Future cleanupAfterSignal() async { await stopEchoingDeviceLog(); + if (_didAttach) { + appFinished(); + } else { + await stopApp(); + } await stopApp(); } @@ -145,15 +185,18 @@ class ColdRunner extends ResidentRunner { haveAnything = true; } } + final String quitMessage = _didAttach + ? 'To detach, press "d"; to quit, press "q".' + : 'To quit, press "q".'; if (haveDetails && !details) { if (saveCompilationTrace) { printStatus('Compilation training data will be saved when flutter run quits...'); } - printStatus('For a more detailed help message, press "h". To quit, press "q".'); + printStatus('For a more detailed help message, press "h". $quitMessage'); } else if (haveAnything) { - printStatus('To repeat this help message, press "h". To quit, press "q".'); + printStatus('To repeat this help message, press "h". $quitMessage'); } else { - printStatus('To quit, press "q".'); + printStatus(quitMessage); } } diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart index b24839cb385..103790de61d 100644 --- a/packages/flutter_tools/lib/src/run_hot.dart +++ b/packages/flutter_tools/lib/src/run_hot.dart @@ -176,6 +176,7 @@ class HotRunner extends ResidentRunner { throw 'Failed to compile $expression'; } + @override Future attach({ Completer connectionInfoCompleter, Completer appStartedCompleter, diff --git a/packages/flutter_tools/test/resident_runner_test.dart b/packages/flutter_tools/test/resident_runner_test.dart index a818d4789b6..815de9309b9 100644 --- a/packages/flutter_tools/test/resident_runner_test.dart +++ b/packages/flutter_tools/test/resident_runner_test.dart @@ -40,6 +40,12 @@ class TestRunner extends ResidentRunner { String route, bool shouldBuild = true, }) async => null; + + @override + Future attach({ + Completer connectionInfoCompleter, + Completer appStartedCompleter, + }) async => null; } void main() {