Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions packages/flutter_tools/lib/src/ios/devices.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class IOSDevices extends PollingDeviceDiscovery {
);
}

return await _xcdevice.getAvailableTetheredIOSDevices(timeout: timeout);
return await _xcdevice.getAvailableIOSDevices(timeout: timeout);
}

@override
Expand All @@ -73,11 +73,18 @@ class IOSDevices extends PollingDeviceDiscovery {
}
}

enum IOSDeviceInterface {
none,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is none exclusively simulators?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK but it's also a fallback in case they add some new type we can't parse.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a clarifying comment.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

usb,
network,
}

class IOSDevice extends Device {
IOSDevice(String id, {
@required FileSystem fileSystem,
@required this.name,
@required this.cpuArchitecture,
@required this.interfaceType,
@required String sdkVersion,
@required Platform platform,
@required Artifacts artifacts,
Expand Down Expand Up @@ -123,16 +130,21 @@ class IOSDevice extends Device {
}

@override
bool get supportsHotReload => true;
bool get supportsHotReload => interfaceType == IOSDeviceInterface.usb;

@override
bool get supportsHotRestart => true;
bool get supportsHotRestart => interfaceType == IOSDeviceInterface.usb;

@override
bool get supportsFlutterExit => interfaceType == IOSDeviceInterface.usb;

@override
final String name;

final DarwinArch cpuArchitecture;

final IOSDeviceInterface interfaceType;

Map<IOSApp, DeviceLogReader> _logReaders;

DevicePortForwarder _portForwarder;
Expand Down Expand Up @@ -178,6 +190,7 @@ class IOSDevice extends Device {
deviceId: id,
bundlePath: bundle.path,
launchArguments: <String>[],
interfaceType: interfaceType,
);
} on ProcessException catch (e) {
_logger.printError(e.message);
Expand Down Expand Up @@ -319,6 +332,7 @@ class IOSDevice extends Device {
deviceId: id,
bundlePath: bundle.path,
launchArguments: launchArguments,
interfaceType: interfaceType,
);
if (installationResult != 0) {
_logger.printError('Could not run ${bundle.path} on $id.');
Expand Down Expand Up @@ -410,7 +424,7 @@ class IOSDevice extends Device {
void clearLogs() { }

@override
bool get supportsScreenshot => _iMobileDevice.isInstalled;
bool get supportsScreenshot => _iMobileDevice.isInstalled && interfaceType == IOSDeviceInterface.usb;

@override
Future<void> takeScreenshot(File outputFile) async {
Expand Down
9 changes: 7 additions & 2 deletions packages/flutter_tools/lib/src/ios/ios_deploy.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import '../base/process.dart';
import '../build_info.dart';
import '../cache.dart';
import 'code_signing.dart';
import 'devices.dart';

// Error message patterns from ios-deploy output
const String noProvisioningProfileErrorOne = 'Error 0xe8008015';
Expand Down Expand Up @@ -84,14 +85,16 @@ class IOSDeploy {
@required String deviceId,
@required String bundlePath,
@required List<String>launchArguments,
@required IOSDeviceInterface interfaceType,
}) async {
final List<String> launchCommand = <String>[
_binaryPath,
'--id',
deviceId,
'--bundle',
bundlePath,
'--no-wifi',
if (interfaceType != IOSDeviceInterface.network)
'--no-wifi',
if (launchArguments.isNotEmpty) ...<String>[
'--args',
launchArguments.join(' '),
Expand All @@ -113,14 +116,16 @@ class IOSDeploy {
@required String deviceId,
@required String bundlePath,
@required List<String> launchArguments,
@required IOSDeviceInterface interfaceType,
}) async {
final List<String> launchCommand = <String>[
_binaryPath,
'--id',
deviceId,
'--bundle',
bundlePath,
'--no-wifi',
if (interfaceType != IOSDeviceInterface.network)
'--no-wifi',
'--justlaunch',
if (launchArguments.isNotEmpty) ...<String>[
'--args',
Expand Down
24 changes: 18 additions & 6 deletions packages/flutter_tools/lib/src/macos/xcode.dart
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ class XCDevice {
List<dynamic> _cachedListResults;

/// [timeout] defaults to 2 seconds.
Future<List<IOSDevice>> getAvailableTetheredIOSDevices({ Duration timeout }) async {
Future<List<IOSDevice>> getAvailableIOSDevices({ Duration timeout }) async {
final List<dynamic> allAvailableDevices = await _getAllDevices(timeout: timeout ?? const Duration(seconds: 2));

if (allAvailableDevices == null) {
Expand Down Expand Up @@ -364,15 +364,19 @@ class XCDevice {
}
}

final IOSDeviceInterface interface = _interfaceType(deviceProperties);

// Only support USB devices, skip "network" interface (Xcode > Window > Devices and Simulators > Connect via network).
if (!_isUSBTethered(deviceProperties)) {
// TODO(jmagman): Remove this check once wirelessly detected devices can be observed and attached, https://github.com/flutter/flutter/issues/15072.
if (interface != IOSDeviceInterface.usb) {
continue;
}

devices.add(IOSDevice(
device['identifier'] as String,
name: device['name'] as String,
cpuArchitecture: _cpuArchitecture(deviceProperties),
interfaceType: interface,
sdkVersion: _sdkVersion(deviceProperties),
artifacts: globals.artifacts,
fileSystem: globals.fs,
Expand Down Expand Up @@ -409,10 +413,18 @@ class XCDevice {
return null;
}

static bool _isUSBTethered(Map<String, dynamic> deviceProperties) {
// Interface can be "usb", "network", or not present for simulators.
return deviceProperties.containsKey('interface') &&
(deviceProperties['interface'] as String).toLowerCase() == 'usb';
static IOSDeviceInterface _interfaceType(Map<String, dynamic> deviceProperties) {
// Interface can be "usb", "network", or "none" for simulators
// and unknown future interfaces.
if (deviceProperties.containsKey('interface')) {
if ((deviceProperties['interface'] as String).toLowerCase() == 'network') {
return IOSDeviceInterface.network;
} else {
return IOSDeviceInterface.usb;
}
}

return IOSDeviceInterface.none;
}

static String _sdkVersion(Map<String, dynamic> deviceProperties) {
Expand Down
23 changes: 16 additions & 7 deletions packages/flutter_tools/test/general.shard/ios/devices_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ void main() {
iMobileDevice: iMobileDevice,
name: 'iPhone 1',
sdkVersion: '13.3',
cpuArchitecture: DarwinArch.arm64
cpuArchitecture: DarwinArch.arm64,
interfaceType: IOSDeviceInterface.usb,
);
});

Expand All @@ -87,7 +88,8 @@ void main() {
iMobileDevice: iMobileDevice,
name: 'iPhone 1',
cpuArchitecture: DarwinArch.arm64,
sdkVersion: '1.0.0'
sdkVersion: '1.0.0',
interfaceType: IOSDeviceInterface.usb,
).majorSdkVersion, 1);
expect(IOSDevice(
'device-123',
Expand All @@ -99,7 +101,8 @@ void main() {
iMobileDevice: iMobileDevice,
name: 'iPhone 1',
cpuArchitecture: DarwinArch.arm64,
sdkVersion: '13.1.1'
sdkVersion: '13.1.1',
interfaceType: IOSDeviceInterface.usb,
).majorSdkVersion, 13);
expect(IOSDevice(
'device-123',
Expand All @@ -111,7 +114,8 @@ void main() {
iMobileDevice: iMobileDevice,
name: 'iPhone 1',
cpuArchitecture: DarwinArch.arm64,
sdkVersion: '10'
sdkVersion: '10',
interfaceType: IOSDeviceInterface.usb,
).majorSdkVersion, 10);
expect(IOSDevice(
'device-123',
Expand All @@ -123,7 +127,8 @@ void main() {
iMobileDevice: iMobileDevice,
name: 'iPhone 1',
cpuArchitecture: DarwinArch.arm64,
sdkVersion: '0'
sdkVersion: '0',
interfaceType: IOSDeviceInterface.usb,
).majorSdkVersion, 0);
expect(IOSDevice(
'device-123',
Expand All @@ -135,7 +140,8 @@ void main() {
iMobileDevice: iMobileDevice,
name: 'iPhone 1',
cpuArchitecture: DarwinArch.arm64,
sdkVersion: 'bogus'
sdkVersion: 'bogus',
interfaceType: IOSDeviceInterface.usb,
).majorSdkVersion, 0);
});

Expand All @@ -154,6 +160,7 @@ void main() {
name: 'iPhone 1',
sdkVersion: '13.3',
cpuArchitecture: DarwinArch.arm64,
interfaceType: IOSDeviceInterface.usb,
);
},
throwsAssertionError,
Expand Down Expand Up @@ -237,6 +244,7 @@ void main() {
name: 'iPhone 1',
sdkVersion: '13.3',
cpuArchitecture: DarwinArch.arm64,
interfaceType: IOSDeviceInterface.usb,
);
logReader1 = createLogReader(device, appPackage1, mockProcess1);
logReader2 = createLogReader(device, appPackage2, mockProcess2);
Expand Down Expand Up @@ -321,8 +329,9 @@ void main() {
logger: logger,
platform: macPlatform,
fileSystem: MemoryFileSystem.test(),
interfaceType: IOSDeviceInterface.usb,
);
when(mockXcdevice.getAvailableTetheredIOSDevices())
when(mockXcdevice.getAvailableIOSDevices())
.thenAnswer((Invocation invocation) => Future<List<IOSDevice>>.value(<IOSDevice>[device]));

final List<Device> devices = await iosDevices.pollingGetDevices();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const Map<String, String> kDyLdLibEntry = <String, String>{
};

void main() {
testWithoutContext('IOSDevice.installApp calls ios-deploy correctly', () async {
testWithoutContext('IOSDevice.installApp calls ios-deploy correctly with USB', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final IOSApp iosApp = PrebuiltIOSApp(
projectBundleId: 'app',
Expand All @@ -47,6 +47,36 @@ void main() {
final IOSDevice device = setUpIOSDevice(
processManager: processManager,
fileSystem: fileSystem,
interfaceType: IOSDeviceInterface.usb,
);
final bool wasInstalled = await device.installApp(iosApp);

expect(wasInstalled, true);
expect(processManager.hasRemainingExpectations, false);
});

testWithoutContext('IOSDevice.installApp calls ios-deploy correctly with network', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final IOSApp iosApp = PrebuiltIOSApp(
projectBundleId: 'app',
bundleDir: fileSystem.currentDirectory,
);
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand(command: <String>[
'ios-deploy',
'--id',
'1234',
'--bundle',
'/',
], environment: <String, String>{
'PATH': '/usr/bin:null',
...kDyLdLibEntry,
})
]);
final IOSDevice device = setUpIOSDevice(
processManager: processManager,
fileSystem: fileSystem,
interfaceType: IOSDeviceInterface.network,
);
final bool wasInstalled = await device.installApp(iosApp);

Expand Down Expand Up @@ -237,6 +267,7 @@ IOSDevice setUpIOSDevice({
@required ProcessManager processManager,
FileSystem fileSystem,
Logger logger,
IOSDeviceInterface interfaceType,
}) {
logger ??= BufferLogger.test();
final FakePlatform platform = FakePlatform(
Expand Down Expand Up @@ -270,6 +301,7 @@ IOSDevice setUpIOSDevice({
cache: cache,
),
artifacts: artifacts,
interfaceType: interfaceType,
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ IOSDevice setUpIOSDevice(FileSystem fileSystem) {
sdkVersion: '13.3',
cpuArchitecture: DarwinArch.arm64,
artifacts: artifacts,
interfaceType: IOSDeviceInterface.usb,
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ IOSDevice setUpIOSDevice({
cache: cache,
),
cpuArchitecture: DarwinArch.arm64,
interfaceType: IOSDeviceInterface.usb,
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ IOSDevice setUpIOSDevice({
cache: cache,
),
cpuArchitecture: DarwinArch.arm64,
interfaceType: IOSDeviceInterface.usb,
);
}

Expand Down
Loading