Add device category, ephemeral, platformType for daemon (#33990)
diff --git a/packages/flutter_tools/doc/daemon.md b/packages/flutter_tools/doc/daemon.md index a910b00..ac9d9c4 100644 --- a/packages/flutter_tools/doc/daemon.md +++ b/packages/flutter_tools/doc/daemon.md
@@ -45,7 +45,7 @@ Events that come from the server will have an `event` field containing the type of event, along with a `params` field. ``` -[{"event":"device.added","params":{"id":"1DD6786B-37D4-4355-AA15-B818A87A18B4","name":"iPhone XS Max","platform":"ios","emulator":true}}] +[{"event":"device.added","params":{"id":"1DD6786B-37D4-4355-AA15-B818A87A18B4","name":"iPhone XS Max","platform":"ios","emulator":true,"ephemeral":false,"platformType":"ios","category":"mobile"}}] ``` ## Domains and Commands @@ -157,7 +157,15 @@ #### device.getDevices -Return a list of all connected devices. The `params` field will be a List; each item is a map with the fields `id`, `name`, `platform`, and `emulator` (a boolean). +Return a list of all connected devices. The `params` field will be a List; each item is a map with the fields `id`, `name`, `platform`, `category`, `platformType`, `ephemeral`, and `emulator` (a boolean). + +`category` is string description of the kind of workflow the device supports. The current categories are "mobile", "web" and "desktop", or null if none. + +`platformType` is a string description of the platform sub-folder the device +supports. The current catgetories are "android", "ios", "linux", "macos", +"fuchsia", "windows", and "web". These are kept in sync with the response from `daemon.getSupportedPlatforms`. + +`ephemeral` is a boolean which indicates where the device needs to be manually connected to a development machine. For example, a physical Android device is ephemeral, but the "web" device (that is always present) is not. #### device.enable @@ -181,11 +189,11 @@ #### device.added -This is sent when a device is connected (and polling has been enabled via `enable()`). The `params` field will be a map with the fields `id`, `name`, `platform`, and `emulator`. +This is sent when a device is connected (and polling has been enabled via `enable()`). The `params` field will be a map with the fields `id`, `name`, `platform`, `category`, `platformType`, `ephemeral`, and `emulator`. For more information on `platform`, `category`, `platformType`, and `ephemeral` see `device.getDevices`. #### device.removed -This is sent when a device is disconnected (and polling has been enabled via `enable()`). The `params` field will be a map with the fields `id`, `name`, `platform`, and `emulator`. +This is sent when a device is disconnected (and polling has been enabled via `enable()`). The `params` field will be a map with the fields `id`, `name`, `platform`, `category`, `platformType`, `ephemeral`, and `emulator`. For more information on `platform`, `category`, `platformType`, and `ephemeral` see `device.getDevices`. ### emulator domain @@ -250,6 +258,7 @@ ## Changelog +- 0.5.1: Added `platformType`, `ephemeral`, and `category` field to device. - 0.5.0: Added `daemon.getSupportedPlatforms` command - 0.4.2: Added `app.detach` command - 0.4.1: Added `flutter attach --machine`
diff --git a/packages/flutter_tools/lib/src/android/android_device.dart b/packages/flutter_tools/lib/src/android/android_device.dart index f8003c3..2bba099 100644 --- a/packages/flutter_tools/lib/src/android/android_device.dart +++ b/packages/flutter_tools/lib/src/android/android_device.dart
@@ -72,7 +72,12 @@ this.productID, this.modelID, this.deviceCodeName, - }) : super(id); + }) : super( + id, + category: Category.mobile, + platformType: PlatformType.android, + ephemeral: true, + ); final String productID; final String modelID;
diff --git a/packages/flutter_tools/lib/src/commands/daemon.dart b/packages/flutter_tools/lib/src/commands/daemon.dart index 78f582c..708bddf 100644 --- a/packages/flutter_tools/lib/src/commands/daemon.dart +++ b/packages/flutter_tools/lib/src/commands/daemon.dart
@@ -26,7 +26,7 @@ import '../runner/flutter_command.dart'; import '../vmservice.dart'; -const String protocolVersion = '0.5.0'; +const String protocolVersion = '0.5.1'; /// A server process command. This command will start up a long-lived server. /// It reads JSON-RPC based commands from stdin, executes them, and returns @@ -659,7 +659,12 @@ _DeviceEventHandler _onDeviceEvent(String eventName) { return (Device device) { _serializeDeviceEvents = _serializeDeviceEvents.then<void>((_) async { - sendEvent(eventName, await _deviceToMap(device)); + try { + final Map<String, Object> response = await _deviceToMap(device); + sendEvent(eventName, response); + } catch (err) { + printError(err); + } }); }; } @@ -768,6 +773,9 @@ 'name': device.name, 'platform': getNameForTargetPlatform(await device.targetPlatform), 'emulator': await device.isLocalEmulator, + 'category': device.category?.toString(), + 'platformType': device.platformType?.toString(), + 'ephemeral': device.ephemeral, }; }
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index 3947ce3..14dd869 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart
@@ -5,6 +5,8 @@ import 'dart:async'; import 'dart:math' as math; +import 'package:meta/meta.dart'; + import 'android/android_device.dart'; import 'application_package.dart'; import 'artifacts.dart'; @@ -28,6 +30,38 @@ DeviceManager get deviceManager => context.get<DeviceManager>(); +/// A description of the kind of workflow the device supports. +class Category { + const Category._(this.value); + + static const Category web = Category._('web'); + static const Category desktop = Category._('desktop'); + static const Category mobile = Category._('mobile'); + + final String value; + + @override + String toString() => value; +} + +/// The platform sub-folder that a device type supports. +class PlatformType { + const PlatformType._(this.value); + + static const PlatformType web = PlatformType._('web'); + static const PlatformType android = PlatformType._('android'); + static const PlatformType ios = PlatformType._('ios'); + static const PlatformType linux = PlatformType._('linux'); + static const PlatformType macos = PlatformType._('macos'); + static const PlatformType windows = PlatformType._('windows'); + static const PlatformType fuchsia = PlatformType._('fuchsia'); + + final String value; + + @override + String toString() => value; +} + /// A class to get all available devices. class DeviceManager { @@ -208,10 +242,19 @@ abstract class Device { - Device(this.id); + Device(this.id, {@required this.category, @required this.platformType, @required this.ephemeral}); final String id; + /// The [Category] for this device type. + final Category category; + + /// The [PlatformType] for this device. + final PlatformType platformType; + + /// Whether this is an ephemeral device. + final bool ephemeral; + String get name; bool get supportsStartPaused => true;
diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart index df1840e..8576789 100644 --- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart +++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
@@ -175,7 +175,12 @@ } class FuchsiaDevice extends Device { - FuchsiaDevice(String id, {this.name}) : super(id); + FuchsiaDevice(String id, {this.name}) : super( + id, + platformType: PlatformType.fuchsia, + category: null, + ephemeral: false, + ); @override bool get supportsHotReload => true;
diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart index 15f2a2e..6c8d297 100644 --- a/packages/flutter_tools/lib/src/ios/devices.dart +++ b/packages/flutter_tools/lib/src/ios/devices.dart
@@ -114,7 +114,12 @@ class IOSDevice extends Device { IOSDevice(String id, { this.name, String sdkVersion }) : _sdkVersion = sdkVersion, - super(id) { + super( + id, + category: Category.mobile, + platformType: PlatformType.ios, + ephemeral: true, + ) { _installerPath = _checkForCommand('ideviceinstaller'); _iproxyPath = _checkForCommand('iproxy'); }
diff --git a/packages/flutter_tools/lib/src/ios/simulators.dart b/packages/flutter_tools/lib/src/ios/simulators.dart index b22e32d..06116b5 100644 --- a/packages/flutter_tools/lib/src/ios/simulators.dart +++ b/packages/flutter_tools/lib/src/ios/simulators.dart
@@ -50,7 +50,7 @@ return <IOSSimulator>[]; return SimControl.instance.getConnectedDevices().map<IOSSimulator>((SimDevice device) { - return IOSSimulator(device.udid, name: device.name, category: device.category); + return IOSSimulator(device.udid, name: device.name, simulatorCategory: device.category); }).toList(); } } @@ -215,12 +215,17 @@ } class IOSSimulator extends Device { - IOSSimulator(String id, { this.name, this.category }) : super(id); + IOSSimulator(String id, { this.name, this.simulatorCategory }) : super( + id, + category: Category.mobile, + platformType: PlatformType.ios, + ephemeral: true, + ); @override final String name; - final String category; + final String simulatorCategory; @override Future<bool> get isLocalEmulator async => true; @@ -435,7 +440,7 @@ Future<TargetPlatform> get targetPlatform async => TargetPlatform.ios; @override - Future<String> get sdkNameAndVersion async => category; + Future<String> get sdkNameAndVersion async => simulatorCategory; final RegExp _iosSdkRegExp = RegExp(r'iOS( |-)(\d+)');
diff --git a/packages/flutter_tools/lib/src/linux/linux_device.dart b/packages/flutter_tools/lib/src/linux/linux_device.dart index 7519737..6f4c49b 100644 --- a/packages/flutter_tools/lib/src/linux/linux_device.dart +++ b/packages/flutter_tools/lib/src/linux/linux_device.dart
@@ -19,7 +19,12 @@ /// A device that represents a desktop Linux target. class LinuxDevice extends Device { - LinuxDevice() : super('Linux'); + LinuxDevice() : super( + 'Linux', + category: Category.desktop, + platformType: PlatformType.linux, + ephemeral: false, + ); @override void clearLogs() { }
diff --git a/packages/flutter_tools/lib/src/macos/macos_device.dart b/packages/flutter_tools/lib/src/macos/macos_device.dart index bf9a307..a082bf0 100644 --- a/packages/flutter_tools/lib/src/macos/macos_device.dart +++ b/packages/flutter_tools/lib/src/macos/macos_device.dart
@@ -20,7 +20,12 @@ /// A device that represents a desktop MacOS target. class MacOSDevice extends Device { - MacOSDevice() : super('macOS'); + MacOSDevice() : super( + 'macOS', + category: Category.desktop, + platformType: PlatformType.macos, + ephemeral: false, + ); @override void clearLogs() { }
diff --git a/packages/flutter_tools/lib/src/tester/flutter_tester.dart b/packages/flutter_tools/lib/src/tester/flutter_tester.dart index 3705057..a7abcf1 100644 --- a/packages/flutter_tools/lib/src/tester/flutter_tester.dart +++ b/packages/flutter_tools/lib/src/tester/flutter_tester.dart
@@ -42,7 +42,12 @@ // TODO(scheglov): This device does not currently work with full restarts. class FlutterTesterDevice extends Device { - FlutterTesterDevice(String deviceId) : super(deviceId); + FlutterTesterDevice(String deviceId) : super( + deviceId, + platformType: null, + category: null, + ephemeral: false, + ); Process _process; final DevicePortForwarder _portForwarder = _NoopPortForwarder();
diff --git a/packages/flutter_tools/lib/src/web/web_device.dart b/packages/flutter_tools/lib/src/web/web_device.dart index 8238690f..a98e91f 100644 --- a/packages/flutter_tools/lib/src/web/web_device.dart +++ b/packages/flutter_tools/lib/src/web/web_device.dart
@@ -28,7 +28,12 @@ } class WebDevice extends Device { - WebDevice() : super('web'); + WebDevice() : super( + 'web', + category: Category.web, + platformType: PlatformType.web, + ephemeral: false, + ); @override bool get supportsHotReload => true;
diff --git a/packages/flutter_tools/lib/src/windows/windows_device.dart b/packages/flutter_tools/lib/src/windows/windows_device.dart index 103a731..86d80ee 100644 --- a/packages/flutter_tools/lib/src/windows/windows_device.dart +++ b/packages/flutter_tools/lib/src/windows/windows_device.dart
@@ -21,7 +21,12 @@ /// A device that represents a desktop Windows target. class WindowsDevice extends Device { - WindowsDevice() : super('Windows'); + WindowsDevice() : super( + 'Windows', + category: Category.desktop, + platformType: PlatformType.windows, + ephemeral: false, + ); @override void clearLogs() { }
diff --git a/packages/flutter_tools/test/android/android_device_test.dart b/packages/flutter_tools/test/android/android_device_test.dart index 2046891..c605876 100644 --- a/packages/flutter_tools/test/android/android_device_test.dart +++ b/packages/flutter_tools/test/android/android_device_test.dart
@@ -58,6 +58,7 @@ ''', devices: devices); expect(devices, hasLength(1)); expect(devices.first.name, 'Nexus 7'); + expect(devices.first.category, Category.mobile); }); testUsingContext('emulators and short listings', () {
diff --git a/packages/flutter_tools/test/device_test.dart b/packages/flutter_tools/test/device_test.dart index 4b199c7..308ef0c 100644 --- a/packages/flutter_tools/test/device_test.dart +++ b/packages/flutter_tools/test/device_test.dart
@@ -50,7 +50,12 @@ } class _MockDevice extends Device { - _MockDevice(this.name, String id) : super(id); + _MockDevice(this.name, String id) : super( + id, + platformType: PlatformType.web, + category: Category.mobile, + ephemeral: true, + ); @override final String name;
diff --git a/packages/flutter_tools/test/ios/devices_test.dart b/packages/flutter_tools/test/ios/devices_test.dart index 8b1d2da..9b5f30f 100644 --- a/packages/flutter_tools/test/ios/devices_test.dart +++ b/packages/flutter_tools/test/ios/devices_test.dart
@@ -182,6 +182,7 @@ 'This is a multi-line message,', ' with a non-Flutter log message following it.', ]); + expect(device.category, Category.mobile); }, overrides: <Type, Generator>{ IMobileDevice: () => mockIMobileDevice, });
diff --git a/packages/flutter_tools/test/ios/simulators_test.dart b/packages/flutter_tools/test/ios/simulators_test.dart index c244adf..8cff8c6 100644 --- a/packages/flutter_tools/test/ios/simulators_test.dart +++ b/packages/flutter_tools/test/ios/simulators_test.dart
@@ -109,16 +109,22 @@ group('sdkMajorVersion', () { // This new version string appears in SimulatorApp-850 CoreSimulator-518.16 beta. test('can be parsed from iOS-11-3', () async { - final IOSSimulator device = IOSSimulator('x', name: 'iPhone SE', category: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3'); + final IOSSimulator device = IOSSimulator('x', name: 'iPhone SE', simulatorCategory: 'com.apple.CoreSimulator.SimRuntime.iOS-11-3'); expect(await device.sdkMajorVersion, 11); }); test('can be parsed from iOS 11.2', () async { - final IOSSimulator device = IOSSimulator('x', name: 'iPhone SE', category: 'iOS 11.2'); + final IOSSimulator device = IOSSimulator('x', name: 'iPhone SE', simulatorCategory: 'iOS 11.2'); expect(await device.sdkMajorVersion, 11); }); + + test('Has a simulator category', () async { + final IOSSimulator device = IOSSimulator('x', name: 'iPhone SE', simulatorCategory: 'iOS 11.2'); + + expect(device.category, Category.mobile); + }); }); group('IOSSimulator.isSupported', () { @@ -246,7 +252,7 @@ }); testUsingContext('uses tail on iOS versions prior to iOS 11', () async { - final IOSSimulator device = IOSSimulator('x', name: 'iPhone SE', category: 'iOS 9.3'); + final IOSSimulator device = IOSSimulator('x', name: 'iPhone SE', simulatorCategory: 'iOS 9.3'); await launchDeviceLogTool(device); expect( verify(mockProcessManager.start(captureAny, environment: null, workingDirectory: null)).captured.single, @@ -258,7 +264,7 @@ }); testUsingContext('uses /usr/bin/log on iOS 11 and above', () async { - final IOSSimulator device = IOSSimulator('x', name: 'iPhone SE', category: 'iOS 11.0'); + final IOSSimulator device = IOSSimulator('x', name: 'iPhone SE', simulatorCategory: 'iOS 11.0'); await launchDeviceLogTool(device); expect( verify(mockProcessManager.start(captureAny, environment: null, workingDirectory: null)).captured.single, @@ -280,7 +286,7 @@ }); testUsingContext('uses tail on iOS versions prior to iOS 11', () async { - final IOSSimulator device = IOSSimulator('x', name: 'iPhone SE', category: 'iOS 9.3'); + final IOSSimulator device = IOSSimulator('x', name: 'iPhone SE', simulatorCategory: 'iOS 9.3'); await launchSystemLogTool(device); expect( verify(mockProcessManager.start(captureAny, environment: null, workingDirectory: null)).captured.single, @@ -292,7 +298,7 @@ }); testUsingContext('uses /usr/bin/log on iOS 11 and above', () async { - final IOSSimulator device = IOSSimulator('x', name: 'iPhone SE', category: 'iOS 11.0'); + final IOSSimulator device = IOSSimulator('x', name: 'iPhone SE', simulatorCategory: 'iOS 11.0'); await launchSystemLogTool(device); verifyNever(mockProcessManager.start(any, environment: null, workingDirectory: null)); }, @@ -330,7 +336,7 @@ return Future<Process>.value(mockProcess); }); - final IOSSimulator device = IOSSimulator('123456', category: 'iOS 11.0'); + final IOSSimulator device = IOSSimulator('123456', simulatorCategory: 'iOS 11.0'); final DeviceLogReader logReader = device.getLogReader( app: BuildableIOSApp(mockIosProject), ); @@ -430,7 +436,7 @@ }); testUsingContext("startApp uses compiled app's Info.plist to find CFBundleIdentifier", () async { - final IOSSimulator device = IOSSimulator('x', name: 'iPhone SE', category: 'iOS 11.2'); + final IOSSimulator device = IOSSimulator('x', name: 'iPhone SE', simulatorCategory: 'iOS 11.2'); when(iosWorkflow.getPlistValueFromFile(any, any)).thenReturn('correct'); final Directory mockDir = fs.currentDirectory;
diff --git a/packages/flutter_tools/test/linux/linux_device_test.dart b/packages/flutter_tools/test/linux/linux_device_test.dart index 1c49f80..97e7425 100644 --- a/packages/flutter_tools/test/linux/linux_device_test.dart +++ b/packages/flutter_tools/test/linux/linux_device_test.dart
@@ -43,6 +43,7 @@ expect(await device.isLatestBuildInstalled(linuxApp), true); expect(await device.isAppInstalled(linuxApp), true); expect(await device.stopApp(linuxApp), true); + expect(device.category, Category.desktop); }, overrides: <Type, Generator>{ ProcessManager: () => mockProcessManager, });
diff --git a/packages/flutter_tools/test/macos/macos_device_test.dart b/packages/flutter_tools/test/macos/macos_device_test.dart index 4dd84e3..6a1b651 100644 --- a/packages/flutter_tools/test/macos/macos_device_test.dart +++ b/packages/flutter_tools/test/macos/macos_device_test.dart
@@ -44,6 +44,7 @@ expect(await device.isLatestBuildInstalled(mockMacOSApp), true); expect(await device.isAppInstalled(mockMacOSApp), true); expect(await device.stopApp(mockMacOSApp), false); + expect(device.category, Category.desktop); }, overrides: <Type, Generator>{ ProcessManager: () => mockProcessManager, });
diff --git a/packages/flutter_tools/test/windows/windows_device_test.dart b/packages/flutter_tools/test/windows/windows_device_test.dart index 979a9e3..e1dc10b 100644 --- a/packages/flutter_tools/test/windows/windows_device_test.dart +++ b/packages/flutter_tools/test/windows/windows_device_test.dart
@@ -43,6 +43,7 @@ expect(await device.isLatestBuildInstalled(windowsApp), true); expect(await device.isAppInstalled(windowsApp), true); expect(await device.stopApp(windowsApp), false); + expect(device.category, Category.desktop); }, overrides: <Type, Generator>{ ProcessManager: () => mockProcessManager, });