Skip to content

Commit

Permalink
Separate attached and wireless devices (flutter#122615)
Browse files Browse the repository at this point in the history
Separate attached and wireless devices
  • Loading branch information
vashworth authored Mar 15, 2023
1 parent 5d10cc2 commit 27248d4
Show file tree
Hide file tree
Showing 34 changed files with 1,597 additions and 621 deletions.
8 changes: 8 additions & 0 deletions packages/flutter_tools/lib/src/android/android_device.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ class AndroidDevice extends Device {
final String modelID;
final String? deviceCodeName;

@override
// Wirelessly paired Android devices should have `adb-tls-connect` in the id.
// Source: https://android.googlesource.com/platform/packages/modules/adb/+/f4ba8d73079b99532069dbe888a58167b8723d6c/adb_mdns.h#30
DeviceConnectionInterface get connectionInterface =>
id.contains('adb-tls-connect')
? DeviceConnectionInterface.wireless
: DeviceConnectionInterface.attached;

late final Future<Map<String, String>> _properties = () async {
Map<String, String> properties = <String, String>{};

Expand Down
2 changes: 1 addition & 1 deletion packages/flutter_tools/lib/src/base/user_messages.dart
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ class UserMessages {
'for information about installing additional components.';
String flutterNoMatchingDevice(String deviceId) => 'No supported devices found with name or id '
"matching '$deviceId'.";
String get flutterNoDevicesFound => 'No devices found';
String get flutterNoDevicesFound => 'No devices found.';
String get flutterNoSupportedDevices => 'No supported devices connected.';
String flutterMissPlatformProjects(List<String> unsupportedDevicesType) =>
'If you would like your app to run on ${unsupportedDevicesType.join(' or ')}, consider running `flutter create .` to generate projects for these platforms.';
Expand Down
3 changes: 1 addition & 2 deletions packages/flutter_tools/lib/src/commands/attach.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import '../device.dart';
import '../device_port_forwarder.dart';
import '../fuchsia/fuchsia_device.dart';
import '../ios/devices.dart';
import '../ios/iproxy.dart';
import '../ios/simulators.dart';
import '../macos/macos_ipad_device.dart';
import '../mdns_discovery.dart';
Expand Down Expand Up @@ -287,7 +286,7 @@ known, it can be explicitly provided to attach via the command-line, e.g.
final String ipv6Loopback = InternetAddress.loopbackIPv6.address;
final String ipv4Loopback = InternetAddress.loopbackIPv4.address;
final String hostname = usesIpv6 ? ipv6Loopback : ipv4Loopback;
final bool isNetworkDevice = (device is IOSDevice) && device.interfaceType == IOSDeviceConnectionInterface.network;
final bool isNetworkDevice = (device is IOSDevice) && device.isWirelesslyConnected;

if ((debugPort == null && debugUri == null) || isNetworkDevice) {
if (device is FuchsiaDevice) {
Expand Down
76 changes: 58 additions & 18 deletions packages/flutter_tools/lib/src/commands/devices.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,31 +79,71 @@ class DevicesCommandOutput {

final Duration? deviceDiscoveryTimeout;

Future<List<Device>> _getAttachedDevices(DeviceManager deviceManager) async {
return deviceManager.getAllDevices(
filter: DeviceDiscoveryFilter(
deviceConnectionInterface: DeviceConnectionInterface.attached,
),
);
}

Future<List<Device>> _getWirelessDevices(DeviceManager deviceManager) async {
return deviceManager.getAllDevices(
filter: DeviceDiscoveryFilter(
deviceConnectionInterface: DeviceConnectionInterface.wireless,
),
);
}

Future<void> findAndOutputAllTargetDevices({required bool machine}) async {
final List<Device> devices = await globals.deviceManager?.refreshAllDevices(timeout: deviceDiscoveryTimeout) ?? <Device>[];
List<Device> attachedDevices = <Device>[];
List<Device> wirelessDevices = <Device>[];
final DeviceManager? deviceManager = globals.deviceManager;
if (deviceManager != null) {
// Refresh the cache and then get the attached and wireless devices from
// the cache.
await deviceManager.refreshAllDevices(timeout: deviceDiscoveryTimeout);
attachedDevices = await _getAttachedDevices(deviceManager);
wirelessDevices = await _getWirelessDevices(deviceManager);
}
final List<Device> allDevices = attachedDevices + wirelessDevices;

if (machine) {
await printDevicesAsJson(devices);
await printDevicesAsJson(allDevices);
return;
}

if (allDevices.isEmpty) {
_printNoDevicesDetected();
} else {
if (devices.isEmpty) {
final StringBuffer status = StringBuffer('No devices detected.');
status.writeln();
status.writeln();
status.writeln('Run "flutter emulators" to list and start any available device emulators.');
status.writeln();
status.write('If you expected your device to be detected, please run "flutter doctor" to diagnose potential issues. ');
if (deviceDiscoveryTimeout == null) {
status.write('You may also try increasing the time to wait for connected devices with the --${FlutterOptions.kDeviceTimeout} flag. ');
if (attachedDevices.isNotEmpty) {
globals.printStatus('${attachedDevices.length} connected ${pluralize('device', attachedDevices.length)}:\n');
await Device.printDevices(attachedDevices, globals.logger);
}
if (wirelessDevices.isNotEmpty) {
if (attachedDevices.isNotEmpty) {
globals.printStatus('');
}
status.write('Visit https://flutter.dev/setup/ for troubleshooting tips.');

globals.printStatus(status.toString());
} else {
globals.printStatus('${devices.length} connected ${pluralize('device', devices.length)}:\n');
await Device.printDevices(devices, globals.logger);
globals.printStatus('${wirelessDevices.length} wirelessly connected ${pluralize('device', wirelessDevices.length)}:\n');
await Device.printDevices(wirelessDevices, globals.logger);
}
await _printDiagnostics();
}
await _printDiagnostics();
}

void _printNoDevicesDetected() {
final StringBuffer status = StringBuffer('No devices detected.');
status.writeln();
status.writeln();
status.writeln('Run "flutter emulators" to list and start any available device emulators.');
status.writeln();
status.write('If you expected your device to be detected, please run "flutter doctor" to diagnose potential issues. ');
if (deviceDiscoveryTimeout == null) {
status.write('You may also try increasing the time to wait for connected devices with the --${FlutterOptions.kDeviceTimeout} flag. ');
}
status.write('Visit https://flutter.dev/setup/ for troubleshooting tips.');

globals.printStatus(status.toString());
}

Future<void> _printDiagnostics() async {
Expand Down
3 changes: 1 addition & 2 deletions packages/flutter_tools/lib/src/commands/drive.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import '../device.dart';
import '../drive/drive_service.dart';
import '../globals.dart' as globals;
import '../ios/devices.dart';
import '../ios/iproxy.dart';
import '../resident_runner.dart';
import '../runner/flutter_command.dart' show FlutterCommandCategory, FlutterCommandResult, FlutterOptions;
import '../web/web_device.dart';
Expand Down Expand Up @@ -220,7 +219,7 @@ class DriveCommand extends RunCommandBase {
Future<bool> get disablePortPublication async {
final ArgResults? localArgResults = argResults;
final Device? device = await targetedDevice;
final bool isNetworkDevice = device is IOSDevice && device.interfaceType == IOSDeviceConnectionInterface.network;
final bool isNetworkDevice = device is IOSDevice && device.isWirelesslyConnected;
if (isNetworkDevice && localArgResults != null && !localArgResults.wasParsed('publish-port')) {
_logger.printTrace('Network device is being used. Changing `publish-port` to be enabled.');
return false;
Expand Down
5 changes: 2 additions & 3 deletions packages/flutter_tools/lib/src/commands/run.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import '../device.dart';
import '../features.dart';
import '../globals.dart' as globals;
import '../ios/devices.dart';
import '../ios/iproxy.dart';
import '../project.dart';
import '../reporting/reporting.dart';
import '../resident_runner.dart';
Expand Down Expand Up @@ -426,7 +425,7 @@ class RunCommand extends RunCommandBase {
final TargetPlatform platform = await device.targetPlatform;
anyAndroidDevices = platform == TargetPlatform.android;
anyIOSDevices = platform == TargetPlatform.ios;
if (device is IOSDevice && device.interfaceType == IOSDeviceConnectionInterface.network) {
if (device is IOSDevice && device.isWirelesslyConnected) {
anyIOSNetworkDevices = true;
}
deviceType = getNameForTargetPlatform(platform);
Expand All @@ -440,7 +439,7 @@ class RunCommand extends RunCommandBase {
final TargetPlatform platform = await device.targetPlatform;
anyAndroidDevices = anyAndroidDevices || (platform == TargetPlatform.android);
anyIOSDevices = anyIOSDevices || (platform == TargetPlatform.ios);
if (device is IOSDevice && device.interfaceType == IOSDeviceConnectionInterface.network) {
if (device is IOSDevice && device.isWirelesslyConnected) {
anyIOSNetworkDevices = true;
}
if (anyAndroidDevices && anyIOSDevices) {
Expand Down
5 changes: 2 additions & 3 deletions packages/flutter_tools/lib/src/device.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import 'base/utils.dart';
import 'build_info.dart';
import 'devfs.dart';
import 'device_port_forwarder.dart';
import 'ios/iproxy.dart';
import 'project.dart';
import 'vmservice.dart';

Expand Down Expand Up @@ -1098,7 +1097,7 @@ class DebuggingOptions {
String? route,
Map<String, Object?> platformArgs, {
bool ipv6 = false,
IOSDeviceConnectionInterface interfaceType = IOSDeviceConnectionInterface.none
DeviceConnectionInterface interfaceType = DeviceConnectionInterface.attached,
}) {
final String dartVmFlags = computeDartVmFlags(this);
return <String>[
Expand Down Expand Up @@ -1137,7 +1136,7 @@ class DebuggingOptions {
if (environmentType == EnvironmentType.simulator && hostVmServicePort != null)
'--vm-service-port=$hostVmServicePort',
// Tell the VM service to listen on all interfaces, don't restrict to the loopback.
if (interfaceType == IOSDeviceConnectionInterface.network)
if (interfaceType == DeviceConnectionInterface.wireless)
'--vm-service-host=${ipv6 ? '::0' : '0.0.0.0'}',
if (enableEmbedderApi) '--enable-embedder-api',
];
Expand Down
25 changes: 13 additions & 12 deletions packages/flutter_tools/lib/src/ios/devices.dart
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ class IOSDevice extends Device {
required FileSystem fileSystem,
required this.name,
required this.cpuArchitecture,
required this.interfaceType,
required this.connectionInterface,
String? sdkVersion,
required Platform platform,
required IOSDeploy iosDeploy,
Expand Down Expand Up @@ -199,7 +199,8 @@ class IOSDevice extends Device {

final DarwinArch cpuArchitecture;

final IOSDeviceConnectionInterface interfaceType;
@override
final DeviceConnectionInterface connectionInterface;

final Map<IOSApp?, DeviceLogReader> _logReaders = <IOSApp?, DeviceLogReader>{};

Expand Down Expand Up @@ -256,7 +257,7 @@ class IOSDevice extends Device {
bundlePath: bundle.path,
appDeltaDirectory: app.appDeltaDirectory,
launchArguments: <String>[],
interfaceType: interfaceType,
interfaceType: connectionInterface,
);
} on ProcessException catch (e) {
_logger.printError(e.message);
Expand Down Expand Up @@ -311,7 +312,7 @@ class IOSDevice extends Device {
@visibleForTesting Duration? discoveryTimeout,
}) async {
String? packageId;
if (interfaceType == IOSDeviceConnectionInterface.network &&
if (isWirelesslyConnected &&
debuggingOptions.debuggingEnabled &&
debuggingOptions.disablePortPublication) {
throwToolExit('Cannot start app on wirelessly tethered iOS device. Try running again with the --publish-port flag');
Expand Down Expand Up @@ -351,7 +352,7 @@ class IOSDevice extends Device {
route,
platformArgs,
ipv6: ipv6,
interfaceType: interfaceType,
interfaceType: connectionInterface,
);
Status startAppStatus = _logger.startProgress(
'Installing and launching...',
Expand All @@ -371,7 +372,7 @@ class IOSDevice extends Device {
bundlePath: bundle.path,
appDeltaDirectory: package.appDeltaDirectory,
launchArguments: launchArguments,
interfaceType: interfaceType,
interfaceType: connectionInterface,
uninstallFirst: debuggingOptions.uninstallFirst,
);
if (deviceLogReader is IOSDeviceLogReader) {
Expand All @@ -381,7 +382,7 @@ class IOSDevice extends Device {
// Don't port foward if debugging with a network device.
vmServiceDiscovery = ProtocolDiscovery.vmService(
deviceLogReader,
portForwarder: interfaceType == IOSDeviceConnectionInterface.network ? null : portForwarder,
portForwarder: isWirelesslyConnected ? null : portForwarder,
hostPort: debuggingOptions.hostVmServicePort,
devicePort: debuggingOptions.deviceVmServicePort,
ipv6: ipv6,
Expand All @@ -394,7 +395,7 @@ class IOSDevice extends Device {
bundlePath: bundle.path,
appDeltaDirectory: package.appDeltaDirectory,
launchArguments: launchArguments,
interfaceType: interfaceType,
interfaceType: connectionInterface,
uninstallFirst: debuggingOptions.uninstallFirst,
);
} else {
Expand All @@ -414,13 +415,13 @@ class IOSDevice extends Device {

_logger.printTrace('Application launched on the device. Waiting for Dart VM Service url.');

final int defaultTimeout = interfaceType == IOSDeviceConnectionInterface.network ? 45 : 30;
final int defaultTimeout = isWirelesslyConnected ? 45 : 30;
final Timer timer = Timer(discoveryTimeout ?? Duration(seconds: defaultTimeout), () {
_logger.printError('The Dart VM Service was not discovered after $defaultTimeout seconds. This is taking much longer than expected...');

// If debugging with a wireless device and the timeout is reached, remind the
// user to allow local network permissions.
if (interfaceType == IOSDeviceConnectionInterface.network) {
if (isWirelesslyConnected) {
_logger.printError(
'\nClick "Allow" to the prompt asking if you would like to find and connect devices on your local network. '
'This is required for wireless debugging. If you selected "Don\'t Allow", '
Expand All @@ -433,7 +434,7 @@ class IOSDevice extends Device {
});

Uri? localUri;
if (interfaceType == IOSDeviceConnectionInterface.network) {
if (isWirelesslyConnected) {
// Wait for Dart VM Service to start up.
final Uri? serviceURL = await vmServiceDiscovery?.uri;
if (serviceURL == null) {
Expand Down Expand Up @@ -538,7 +539,7 @@ class IOSDevice extends Device {

@override
Future<void> takeScreenshot(File outputFile) async {
await _iMobileDevice.takeScreenshot(outputFile, id, interfaceType);
await _iMobileDevice.takeScreenshot(outputFile, id, connectionInterface);
}

@override
Expand Down
14 changes: 7 additions & 7 deletions packages/flutter_tools/lib/src/ios/ios_deploy.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import '../base/platform.dart';
import '../base/process.dart';
import '../cache.dart';
import '../convert.dart';
import '../device.dart';
import 'code_signing.dart';
import 'iproxy.dart';

// Error message patterns from ios-deploy output
const String noProvisioningProfileErrorOne = 'Error 0xe8008015';
Expand Down Expand Up @@ -88,7 +88,7 @@ class IOSDeploy {
required String deviceId,
required String bundlePath,
required List<String>launchArguments,
required IOSDeviceConnectionInterface interfaceType,
required DeviceConnectionInterface interfaceType,
Directory? appDeltaDirectory,
}) async {
appDeltaDirectory?.createSync(recursive: true);
Expand All @@ -102,7 +102,7 @@ class IOSDeploy {
'--app_deltas',
appDeltaDirectory.path,
],
if (interfaceType != IOSDeviceConnectionInterface.network)
if (interfaceType != DeviceConnectionInterface.wireless)
'--no-wifi',
if (launchArguments.isNotEmpty) ...<String>[
'--args',
Expand All @@ -126,7 +126,7 @@ class IOSDeploy {
required String deviceId,
required String bundlePath,
required List<String> launchArguments,
required IOSDeviceConnectionInterface interfaceType,
required DeviceConnectionInterface interfaceType,
Directory? appDeltaDirectory,
required bool uninstallFirst,
}) {
Expand All @@ -149,7 +149,7 @@ class IOSDeploy {
if (uninstallFirst)
'--uninstall',
'--debug',
if (interfaceType != IOSDeviceConnectionInterface.network)
if (interfaceType != DeviceConnectionInterface.wireless)
'--no-wifi',
if (launchArguments.isNotEmpty) ...<String>[
'--args',
Expand All @@ -171,7 +171,7 @@ class IOSDeploy {
required String deviceId,
required String bundlePath,
required List<String> launchArguments,
required IOSDeviceConnectionInterface interfaceType,
required DeviceConnectionInterface interfaceType,
required bool uninstallFirst,
Directory? appDeltaDirectory,
}) async {
Expand All @@ -186,7 +186,7 @@ class IOSDeploy {
'--app_deltas',
appDeltaDirectory.path,
],
if (interfaceType != IOSDeviceConnectionInterface.network)
if (interfaceType != DeviceConnectionInterface.wireless)
'--no-wifi',
if (uninstallFirst)
'--uninstall',
Expand Down
6 changes: 0 additions & 6 deletions packages/flutter_tools/lib/src/ios/iproxy.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@ import '../base/io.dart';
import '../base/logger.dart';
import '../base/process.dart';

enum IOSDeviceConnectionInterface {
none,
usb,
network,
}

/// Wraps iproxy command line tool port forwarding.
///
/// See https://github.com/libimobiledevice/libusbmuxd.
Expand Down
Loading

0 comments on commit 27248d4

Please sign in to comment.