Unverified Commit 108da013 authored by Danny Tuppeny's avatar Danny Tuppeny Committed by GitHub

Remove the 'app' domain from flutter daemon (#18873)

* Remove the 'app' domain from flutter daemon

By default the daemon won't register the "app" domain, you need to opt-in (which the 'run' command does, as well as the tests for the app functionality).

Fixes #6658.

* Tweak text

* Put restart/callServiceExtension/stop back into daemon mode

* Add a comment about removing discoverApps
parent 7e4038fe
......@@ -10,7 +10,7 @@ flutter daemon
It runs a persistent, JSON-RPC based server to communicate with devices. IDEs and other tools can start the flutter tool in this mode and get device addition and removal notifications, as well as being able to programmatically start and stop apps on those devices.
A subset of the `flutter daemon` commands/events are also exposed via `flutter run --machine` which allows IDEs and tools to launch flutter applications and interact to send commands like Hot Reload. Which commands/events are available in this mode is documented at the bottom of this document.
A set of `flutter daemon` commands/events are also exposed via `flutter run --machine` which allows IDEs and tools to launch flutter applications and interact to send commands like Hot Reload. The command and events that are available in this mode are documented at the bottom of this document.
## Protocol
......@@ -76,24 +76,6 @@ It is up to the client to decide how best to display the message; for some clien
### app domain
#### app.start
The `start()` command is used to start applications.
- `deviceId`: The device to launch the app on; this is required.
- `projectDirectory`: The project directory; this is required. It is used to determine the application to start.
- `startPaused`: Start the VM in a paused mode.
- `route`: A string; the route to use when restoring the application.
- `mode`: One of either `debug`, `profile`, or `release`.
- `target`: Optional; the target file to start.
- `hot`: Optional; whether to start the application using `--hot` mode
On success, returns a map with the fields:
- `appId`: this is is used when sending app events, and can be used by clients to stop the app (`app.stop`).
- `deviceId`
- `directory`
- `supportsRestart`
#### app.restart
The `restart()` restarts the given application. It returns a Map of `{ int code, String message, String hintMessage, String hintId }` to indicate success or failure in restarting the app. A `code` of `0` indicates success, and non-zero indicates a failure. If `hintId` is non-null and equal to `restartRecommended`, that indicates that the reload was successful, but not all reloaded elements were executed during view reassembly (i.e., the user might not see all the changes in the current UI, and a restart could be necessary).
......@@ -116,10 +98,6 @@ The `stop()` command takes one parameter, `appId`. It returns a `bool` to indica
- `appId`: the id of a previously started app; this is required.
#### app.discover
The `discover()` command takes one parameter, a `deviceId`. It returns a list of applications discovered on the device. Each application is represented by a map with two fields, an `id` - an Android or iOS application id - and an `observatoryDevicePort`. The `observatoryDevicePort` is the device port to connect to to debug the application. The port may first have to be made accessable via `device.forward`.
#### Events
#### app.start
......
......@@ -516,6 +516,9 @@ class AndroidDevice extends Device {
await runCheckedAsync(adbCommandForDevice(<String>['shell', 'rm', remotePath]));
}
// TODO(dantup): discoverApps is no longer used and can possibly be removed.
// Waiting for a response here:
// https://github.com/flutter/flutter/pull/18873#discussion_r198862179
@override
Future<List<DiscoveredApp>> discoverApps() async {
final RegExp discoverExp = new RegExp(r'DISCOVER: (.*)');
......
......@@ -83,7 +83,7 @@ class Daemon {
this.sendCommand, {
this.daemonCommand,
this.notifyingLogger,
this.logToStdout = false
this.logToStdout = false,
}) {
// Set up domains.
_registerDomain(daemonDomain = new DaemonDomain(this));
......@@ -300,11 +300,9 @@ class DaemonDomain extends Domain {
/// It fires events for application start, stop, and stdout and stderr.
class AppDomain extends Domain {
AppDomain(Daemon daemon) : super(daemon, 'app') {
registerHandler('start', start);
registerHandler('restart', restart);
registerHandler('callServiceExtension', callServiceExtension);
registerHandler('stop', stop);
registerHandler('discover', discover);
}
static final Uuid _uuidGenerator = new Uuid();
......@@ -313,58 +311,6 @@ class AppDomain extends Domain {
final List<AppInstance> _apps = <AppInstance>[];
Future<Map<String, dynamic>> start(Map<String, dynamic> args) async {
final String deviceId = _getStringArg(args, 'deviceId', required: true);
final String projectDirectory = _getStringArg(args, 'projectDirectory', required: true);
final bool startPaused = _getBoolArg(args, 'startPaused') ?? false;
final bool useTestFonts = _getBoolArg(args, 'useTestFonts') ?? false;
final String route = _getStringArg(args, 'route');
final String mode = _getStringArg(args, 'mode');
final String flavor = _getStringArg(args, 'flavor');
final String target = _getStringArg(args, 'target');
final bool enableHotReload = _getBoolArg(args, 'hot') ?? kHotReloadDefault;
final Device device = await daemon.deviceDomain._getOrLocateDevice(deviceId);
if (device == null)
throw "device '$deviceId' not found";
if (!fs.isDirectorySync(projectDirectory))
throw "'$projectDirectory' does not exist";
final BuildInfo buildInfo = new BuildInfo(
getBuildModeForName(mode) ?? BuildMode.debug,
flavor,
previewDart2: _getBoolArg(args, 'preview-dart-2'),
);
DebuggingOptions options;
if (buildInfo.isRelease) {
options = new DebuggingOptions.disabled(buildInfo);
} else {
options = new DebuggingOptions.enabled(
buildInfo,
startPaused: startPaused,
useTestFonts: useTestFonts,
);
}
final AppInstance app = await startApp(
device,
projectDirectory,
target,
route,
options,
enableHotReload,
trackWidgetCreation: _getBoolArg(args, 'track-widget-creation'),
);
return <String, dynamic>{
'appId': app.id,
'deviceId': device.id,
'directory': projectDirectory,
'supportsRestart': isRestartSupported(enableHotReload, device)
};
}
Future<AppInstance> startApp(
Device device, String projectDirectory, String target, String route,
DebuggingOptions options, bool enableHotReload, {
......@@ -537,22 +483,6 @@ class AppDomain extends Domain {
});
}
Future<List<Map<String, dynamic>>> discover(Map<String, dynamic> args) async {
final String deviceId = _getStringArg(args, 'deviceId', required: true);
final Device device = await daemon.deviceDomain._getDevice(deviceId);
if (device == null)
throw "device '$deviceId' not found";
final List<DiscoveredApp> apps = await device.discoverApps();
return apps.map((DiscoveredApp app) {
return <String, dynamic>{
'id': app.id,
'observatoryDevicePort': app.observatoryPort,
};
}).toList();
}
AppInstance _getApp(String id) {
return _apps.firstWhere((AppInstance app) => app.id == id, orElse: () => null);
}
......@@ -687,25 +617,6 @@ class DeviceDomain extends Domain {
}
return null;
}
/// Return a known matching device, or scan for devices if no known match is found.
Future<Device> _getOrLocateDevice(String deviceId) async {
// Look for an already known device.
final Device device = await _getDevice(deviceId);
if (device != null)
return device;
// Scan the different device providers for a match.
for (PollingDeviceDiscovery discoverer in _discoverers) {
final List<Device> devices = await discoverer.pollingGetDevices();
for (Device device in devices)
if (device.id == deviceId)
return device;
}
// No match found.
return null;
}
}
Stream<Map<String, dynamic>> get stdinCommandStream => stdin
......
......@@ -277,6 +277,9 @@ abstract class Device {
Future<void> takeScreenshot(File outputFile) => new Future<Null>.error('unimplemented');
// TODO(dantup): discoverApps is no longer used and can possibly be removed.
// Waiting for a response here:
// https://github.com/flutter/flutter/pull/18873#discussion_r198862179
/// Find the apps that are currently running on this device.
Future<List<DiscoveredApp>> discoverApps() =>
new Future<List<DiscoveredApp>>.value(<DiscoveredApp>[]);
......
......@@ -110,27 +110,6 @@ void main() {
});
});
testUsingContext('app.start without a deviceId should report an error', () async {
final DaemonCommand command = new DaemonCommand();
applyMocksToCommand(command);
final StreamController<Map<String, dynamic>> commands = new StreamController<Map<String, dynamic>>();
final StreamController<Map<String, dynamic>> responses = new StreamController<Map<String, dynamic>>();
daemon = new Daemon(
commands.stream,
responses.add,
daemonCommand: command,
notifyingLogger: notifyingLogger
);
commands.add(<String, dynamic>{ 'id': 0, 'method': 'app.start' });
final Map<String, dynamic> response = await responses.stream.firstWhere(_notEvent);
expect(response['id'], 0);
expect(response['error'], contains('deviceId is required'));
responses.close();
commands.close();
});
testUsingContext('app.restart without an appId should report an error', () async {
final DaemonCommand command = new DaemonCommand();
applyMocksToCommand(command);
......@@ -141,7 +120,7 @@ void main() {
commands.stream,
responses.add,
daemonCommand: command,
notifyingLogger: notifyingLogger
notifyingLogger: notifyingLogger,
);
commands.add(<String, dynamic>{ 'id': 0, 'method': 'app.restart' });
......@@ -162,7 +141,7 @@ void main() {
commands.stream,
responses.add,
daemonCommand: command,
notifyingLogger: notifyingLogger
notifyingLogger: notifyingLogger,
);
commands.add(<String, dynamic>{
......@@ -189,7 +168,7 @@ void main() {
commands.stream,
responses.add,
daemonCommand: command,
notifyingLogger: notifyingLogger
notifyingLogger: notifyingLogger,
);
commands.add(<String, dynamic>{ 'id': 0, 'method': 'app.stop' });
......
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