Unverified Commit 1bea512a authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] flutter logs no longer requires supported device (#66696)

Flutter logs should not attempt to filter the device list based on the current project, because it does not require a current project. Also fix disabled polling test

Fixes #47996
Fixes #63550
parent 33fb35e9
...@@ -826,21 +826,17 @@ class DeviceDomain extends Domain { ...@@ -826,21 +826,17 @@ class DeviceDomain extends Domain {
} }
/// Enable device events. /// Enable device events.
Future<void> enable(Map<String, dynamic> args) { Future<void> enable(Map<String, dynamic> args) async {
final List<Future<void>> calls = <Future<void>>[];
for (final PollingDeviceDiscovery discoverer in _discoverers) { for (final PollingDeviceDiscovery discoverer in _discoverers) {
calls.add(discoverer.startPolling()); discoverer.startPolling();
} }
return Future.wait<void>(calls);
} }
/// Disable device events. /// Disable device events.
Future<void> disable(Map<String, dynamic> args) async { Future<void> disable(Map<String, dynamic> args) async {
final List<Future<void>> calls = <Future<void>>[];
for (final PollingDeviceDiscovery discoverer in _discoverers) { for (final PollingDeviceDiscovery discoverer in _discoverers) {
calls.add(discoverer.stopPolling()); discoverer.stopPolling();
} }
return Future.wait<void>(calls);
} }
/// Forward a host port to a device port. /// Forward a host port to a device port.
...@@ -874,10 +870,11 @@ class DeviceDomain extends Domain { ...@@ -874,10 +870,11 @@ class DeviceDomain extends Domain {
} }
@override @override
Future<void> dispose() async { Future<void> dispose() {
for (final PollingDeviceDiscovery discoverer in _discoverers) { for (final PollingDeviceDiscovery discoverer in _discoverers) {
await discoverer.dispose(); discoverer.dispose();
} }
return Future<void>.value();
} }
/// Return the device matching the deviceId field in the args. /// Return the device matching the deviceId field in the args.
......
...@@ -34,7 +34,7 @@ class LogsCommand extends FlutterCommand { ...@@ -34,7 +34,7 @@ class LogsCommand extends FlutterCommand {
@override @override
Future<FlutterCommandResult> verifyThenRunCommand(String commandPath) async { Future<FlutterCommandResult> verifyThenRunCommand(String commandPath) async {
device = await findTargetDevice(); device = await findTargetDevice(includeUnsupportedDevices: true);
if (device == null) { if (device == null) {
throwToolExit(null); throwToolExit(null);
} }
......
...@@ -77,7 +77,7 @@ class PlatformType { ...@@ -77,7 +77,7 @@ class PlatformType {
String toString() => value; String toString() => value;
} }
/// A class to get all available devices. /// A disovery mechanism for flutter-supported development devices.
abstract class DeviceManager { abstract class DeviceManager {
/// Constructing DeviceManagers is cheap; they only do expensive work if some /// Constructing DeviceManagers is cheap; they only do expensive work if some
...@@ -210,6 +210,9 @@ abstract class DeviceManager { ...@@ -210,6 +210,9 @@ abstract class DeviceManager {
/// * If the user did not specify a device id and there is more than one /// * If the user did not specify a device id and there is more than one
/// device connected, then filter out unsupported devices and prioritize /// device connected, then filter out unsupported devices and prioritize
/// ephemeral devices. /// ephemeral devices.
///
/// * If [flutterProject] is null, then assume the project supports all
/// device types.
Future<List<Device>> findTargetDevices(FlutterProject flutterProject, { Duration timeout }) async { Future<List<Device>> findTargetDevices(FlutterProject flutterProject, { Duration timeout }) async {
if (timeout != null) { if (timeout != null) {
// Reset the cache with the specified timeout. // Reset the cache with the specified timeout.
...@@ -310,8 +313,12 @@ abstract class DeviceManager { ...@@ -310,8 +313,12 @@ abstract class DeviceManager {
/// Returns whether the device is supported for the project. /// Returns whether the device is supported for the project.
/// ///
/// This exists to allow the check to be overridden for google3 clients. /// This exists to allow the check to be overridden for google3 clients. If
/// [flutterProject] is null then return true.
bool isDeviceSupportedForProject(Device device, FlutterProject flutterProject) { bool isDeviceSupportedForProject(Device device, FlutterProject flutterProject) {
if (flutterProject == null) {
return true;
}
return device.isSupportedForProject(flutterProject); return device.isSupportedForProject(flutterProject);
} }
} }
...@@ -428,7 +435,7 @@ abstract class PollingDeviceDiscovery extends DeviceDiscovery { ...@@ -428,7 +435,7 @@ abstract class PollingDeviceDiscovery extends DeviceDiscovery {
Future<List<Device>> pollingGetDevices({ Duration timeout }); Future<List<Device>> pollingGetDevices({ Duration timeout });
Future<void> startPolling() async { void startPolling() {
if (_timer == null) { if (_timer == null) {
deviceNotifier ??= ItemListNotifier<Device>(); deviceNotifier ??= ItemListNotifier<Device>();
// Make initial population the default, fast polling timeout. // Make initial population the default, fast polling timeout.
...@@ -449,18 +456,18 @@ abstract class PollingDeviceDiscovery extends DeviceDiscovery { ...@@ -449,18 +456,18 @@ abstract class PollingDeviceDiscovery extends DeviceDiscovery {
}); });
} }
Future<void> stopPolling() async { void stopPolling() {
_timer?.cancel(); _timer?.cancel();
_timer = null; _timer = null;
} }
@override @override
Future<List<Device>> get devices async { Future<List<Device>> get devices {
return _populateDevices(); return _populateDevices();
} }
@override @override
Future<List<Device>> discoverDevices({ Duration timeout }) async { Future<List<Device>> discoverDevices({ Duration timeout }) {
deviceNotifier = null; deviceNotifier = null;
return _populateDevices(timeout: timeout); return _populateDevices(timeout: timeout);
} }
...@@ -480,7 +487,7 @@ abstract class PollingDeviceDiscovery extends DeviceDiscovery { ...@@ -480,7 +487,7 @@ abstract class PollingDeviceDiscovery extends DeviceDiscovery {
return deviceNotifier.onRemoved; return deviceNotifier.onRemoved;
} }
Future<void> dispose() async => await stopPolling(); void dispose() => stopPolling();
@override @override
String toString() => '$name device discovery'; String toString() => '$name device discovery';
......
...@@ -1005,13 +1005,18 @@ abstract class FlutterCommand extends Command<void> { ...@@ -1005,13 +1005,18 @@ abstract class FlutterCommand extends Command<void> {
/// devices and criteria entered by the user on the command line. /// devices and criteria entered by the user on the command line.
/// If no device can be found that meets specified criteria, /// If no device can be found that meets specified criteria,
/// then print an error message and return null. /// then print an error message and return null.
Future<List<Device>> findAllTargetDevices() async { Future<List<Device>> findAllTargetDevices({
bool includeUnsupportedDevices = false,
}) async {
if (!globals.doctor.canLaunchAnything) { if (!globals.doctor.canLaunchAnything) {
globals.printError(userMessages.flutterNoDevelopmentDevice); globals.printError(userMessages.flutterNoDevelopmentDevice);
return null; return null;
} }
final DeviceManager deviceManager = globals.deviceManager; final DeviceManager deviceManager = globals.deviceManager;
List<Device> devices = await deviceManager.findTargetDevices(FlutterProject.current(), timeout: deviceDiscoveryTimeout); List<Device> devices = await deviceManager.findTargetDevices(
includeUnsupportedDevices ? null : FlutterProject.current(),
timeout: deviceDiscoveryTimeout,
);
if (devices.isEmpty && deviceManager.hasSpecifiedDeviceId) { if (devices.isEmpty && deviceManager.hasSpecifiedDeviceId) {
globals.printStatus(userMessages.flutterNoMatchingDevice(deviceManager.specifiedDeviceId)); globals.printStatus(userMessages.flutterNoMatchingDevice(deviceManager.specifiedDeviceId));
...@@ -1057,8 +1062,13 @@ abstract class FlutterCommand extends Command<void> { ...@@ -1057,8 +1062,13 @@ abstract class FlutterCommand extends Command<void> {
/// devices and criteria entered by the user on the command line. /// devices and criteria entered by the user on the command line.
/// If a device cannot be found that meets specified criteria, /// If a device cannot be found that meets specified criteria,
/// then print an error message and return null. /// then print an error message and return null.
Future<Device> findTargetDevice() async { ///
List<Device> deviceList = await findAllTargetDevices(); /// If [includeUnsupportedDevices] is true, the tool does not filter
/// the list by the current project support list.
Future<Device> findTargetDevice({
bool includeUnsupportedDevices = false,
}) async {
List<Device> deviceList = await findAllTargetDevices(includeUnsupportedDevices: includeUnsupportedDevices);
if (deviceList == null) { if (deviceList == null) {
return null; return null;
} }
......
...@@ -79,6 +79,4 @@ void main() { ...@@ -79,6 +79,4 @@ void main() {
}); });
} }
class MockDeviceManager extends Mock implements DeviceManager { class MockDeviceManager extends Mock implements DeviceManager {}
}
...@@ -137,26 +137,26 @@ void main() { ...@@ -137,26 +137,26 @@ void main() {
}); });
group('PollingDeviceDiscovery', () { group('PollingDeviceDiscovery', () {
testUsingContext('startPolling', () async { testUsingContext('startPolling', () {
await FakeAsync().run((FakeAsync time) async { FakeAsync().run((FakeAsync time) {
final FakePollingDeviceDiscovery pollingDeviceDiscovery = FakePollingDeviceDiscovery(); final FakePollingDeviceDiscovery pollingDeviceDiscovery = FakePollingDeviceDiscovery();
await pollingDeviceDiscovery.startPolling(); pollingDeviceDiscovery.startPolling();
time.elapse(const Duration(milliseconds: 4001)); time.elapse(const Duration(milliseconds: 4001));
time.flushMicrotasks();
// First check should use the default polling timeout // First check should use the default polling timeout
// to quickly populate the list. // to quickly populate the list.
expect(pollingDeviceDiscovery.lastPollingTimeout, isNull); expect(pollingDeviceDiscovery.lastPollingTimeout, isNull);
time.elapse(const Duration(milliseconds: 4001)); time.elapse(const Duration(milliseconds: 4001));
time.flushMicrotasks();
// Subsequent polling should be much longer. // Subsequent polling should be much longer.
expect(pollingDeviceDiscovery.lastPollingTimeout, const Duration(seconds: 30)); expect(pollingDeviceDiscovery.lastPollingTimeout, const Duration(seconds: 30));
await pollingDeviceDiscovery.stopPolling(); pollingDeviceDiscovery.stopPolling();
}); });
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Artifacts: () => Artifacts.test(), Artifacts: () => Artifacts.test(),
Cache: () => cache, Cache: () => cache,
}, skip: true); // TODO(jonahwilliams): clean up with https://github.com/flutter/flutter/issues/60675 });
}); });
group('Filter devices', () { group('Filter devices', () {
...@@ -369,6 +369,20 @@ void main() { ...@@ -369,6 +369,20 @@ void main() {
Cache: () => cache, Cache: () => cache,
}); });
testUsingContext('Does not remove an unsupported device if FlutterProject is null', () async {
final List<Device> devices = <Device>[
unsupported,
];
final DeviceManager deviceManager = TestDeviceManager(devices);
final List<Device> filtered = await deviceManager.findTargetDevices(null);
expect(filtered, <Device>[unsupported]);
}, overrides: <Type, Generator>{
Artifacts: () => Artifacts.test(),
Cache: () => cache,
});
testUsingContext('Removes web and fuchsia from --all', () async { testUsingContext('Removes web and fuchsia from --all', () async {
final List<Device> devices = <Device>[ final List<Device> devices = <Device>[
webDevice, webDevice,
...@@ -428,9 +442,7 @@ void main() { ...@@ -428,9 +442,7 @@ void main() {
]; ];
final MockDeviceDiscovery mockDeviceDiscovery = MockDeviceDiscovery(); final MockDeviceDiscovery mockDeviceDiscovery = MockDeviceDiscovery();
when(mockDeviceDiscovery.supportsPlatform).thenReturn(true); when(mockDeviceDiscovery.supportsPlatform).thenReturn(true);
// when(mockDeviceDiscovery.discoverDevices(timeout: timeout)).thenAnswer((_) async => devices);
when(mockDeviceDiscovery.devices).thenAnswer((_) async => devices); when(mockDeviceDiscovery.devices).thenAnswer((_) async => devices);
// when(mockDeviceDiscovery.discoverDevices(timeout: timeout)).thenAnswer((_) async => devices);
final DeviceManager deviceManager = TestDeviceManager(<Device>[], deviceDiscoveryOverrides: <DeviceDiscovery>[ final DeviceManager deviceManager = TestDeviceManager(<Device>[], deviceDiscoveryOverrides: <DeviceDiscovery>[
mockDeviceDiscovery mockDeviceDiscovery
...@@ -457,7 +469,6 @@ void main() { ...@@ -457,7 +469,6 @@ void main() {
when(mockDeviceDiscovery.supportsPlatform).thenReturn(true); when(mockDeviceDiscovery.supportsPlatform).thenReturn(true);
when(mockDeviceDiscovery.discoverDevices(timeout: timeout)).thenAnswer((_) async => devices); when(mockDeviceDiscovery.discoverDevices(timeout: timeout)).thenAnswer((_) async => devices);
when(mockDeviceDiscovery.devices).thenAnswer((_) async => devices); when(mockDeviceDiscovery.devices).thenAnswer((_) async => devices);
// when(mockDeviceDiscovery.discoverDevices(timeout: timeout)).thenAnswer((_) async => devices);
final DeviceManager deviceManager = TestDeviceManager(<Device>[], deviceDiscoveryOverrides: <DeviceDiscovery>[ final DeviceManager deviceManager = TestDeviceManager(<Device>[], deviceDiscoveryOverrides: <DeviceDiscovery>[
mockDeviceDiscovery mockDeviceDiscovery
......
...@@ -515,7 +515,7 @@ void main() { ...@@ -515,7 +515,7 @@ void main() {
expect(iosDevices.deviceNotifier.items, isEmpty); expect(iosDevices.deviceNotifier.items, isEmpty);
expect(eventStream.hasListener, isTrue); expect(eventStream.hasListener, isTrue);
await iosDevices.dispose(); iosDevices.dispose();
expect(eventStream.hasListener, isFalse); expect(eventStream.hasListener, isFalse);
}); });
......
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