diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart index 083153ca0b6f4..bc8664d158817 100644 --- a/packages/flutter_tools/lib/src/ios/devices.dart +++ b/packages/flutter_tools/lib/src/ios/devices.dart @@ -465,7 +465,7 @@ class IOSDevice extends Device { Future get targetPlatform async => TargetPlatform.ios; @override - Future get sdkNameAndVersion async => 'iOS $_sdkVersion'; + Future get sdkNameAndVersion async => 'iOS ${_sdkVersion ?? 'unknown version'}'; @override DeviceLogReader getLogReader({ diff --git a/packages/flutter_tools/lib/src/macos/xcdevice.dart b/packages/flutter_tools/lib/src/macos/xcdevice.dart index bc611cb790df4..b060814f4f12e 100644 --- a/packages/flutter_tools/lib/src/macos/xcdevice.dart +++ b/packages/flutter_tools/lib/src/macos/xcdevice.dart @@ -301,12 +301,21 @@ class XCDevice { continue; } + String sdkVersion = _sdkVersion(device); + + if (sdkVersion != null) { + final String buildVersion = _buildVersion(device); + if (buildVersion != null) { + sdkVersion = '$sdkVersion $buildVersion'; + } + } + devices.add(IOSDevice( device['identifier'] as String, name: device['name'] as String, cpuArchitecture: _cpuArchitecture(device), interfaceType: interface, - sdkVersion: _sdkVersion(device), + sdkVersion: sdkVersion, iProxy: _iProxy, fileSystem: globals.fs, logger: _logger, @@ -317,6 +326,7 @@ class XCDevice { } } return devices; + } /// Despite the name, com.apple.platform.iphoneos includes iPhone, iPads, and all iOS devices. @@ -363,7 +373,20 @@ class XCDevice { // "13.3 (17C54)" final RegExp operatingSystemRegex = RegExp(r'(.*) \(.*\)$'); final String operatingSystemVersion = deviceProperties['operatingSystemVersion'] as String; - return operatingSystemRegex.firstMatch(operatingSystemVersion.trim())?.group(1); + if(operatingSystemRegex.hasMatch(operatingSystemVersion.trim())) { + return operatingSystemRegex.firstMatch(operatingSystemVersion.trim())?.group(1); + } + return operatingSystemVersion; + } + return null; + } + + static String _buildVersion(Map deviceProperties) { + if (deviceProperties.containsKey('operatingSystemVersion')) { + // Parse out the build version, for example 17C54 from "13.3 (17C54)". + final RegExp buildVersionRegex = RegExp(r'\(.*\)$'); + final String operatingSystemVersion = deviceProperties['operatingSystemVersion'] as String; + return buildVersionRegex.firstMatch(operatingSystemVersion)?.group(0)?.replaceAll(RegExp('[()]'), ''); } return null; } diff --git a/packages/flutter_tools/test/general.shard/ios/devices_test.dart b/packages/flutter_tools/test/general.shard/ios/devices_test.dart index 1c89f6e451759..26bbc56174a0f 100644 --- a/packages/flutter_tools/test/general.shard/ios/devices_test.dart +++ b/packages/flutter_tools/test/general.shard/ios/devices_test.dart @@ -148,6 +148,24 @@ void main() { ).majorSdkVersion, 0); }); + testWithoutContext('has build number in sdkNameAndVersion', () async { + final IOSDevice device = IOSDevice( + 'device-123', + iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()), + fileSystem: nullFileSystem, + logger: logger, + platform: macPlatform, + iosDeploy: iosDeploy, + iMobileDevice: iMobileDevice, + name: 'iPhone 1', + sdkVersion: '13.3 17C54', + cpuArchitecture: DarwinArch.arm64, + interfaceType: IOSDeviceInterface.usb, + ); + + expect(await device.sdkNameAndVersion,'iOS 13.3 17C54'); + }); + testWithoutContext('Supports debug, profile, and release modes', () { final IOSDevice device = IOSDevice( 'device-123', diff --git a/packages/flutter_tools/test/general.shard/macos/xcode_test.dart b/packages/flutter_tools/test/general.shard/macos/xcode_test.dart index 885719863435a..d9bb28b9bc3f4 100644 --- a/packages/flutter_tools/test/general.shard/macos/xcode_test.dart +++ b/packages/flutter_tools/test/general.shard/macos/xcode_test.dart @@ -513,15 +513,15 @@ void main() { expect(devices, hasLength(3)); expect(devices[0].id, '00008027-00192736010F802E'); expect(devices[0].name, 'An iPhone (Space Gray)'); - expect(await devices[0].sdkNameAndVersion, 'iOS 13.3'); + expect(await devices[0].sdkNameAndVersion, 'iOS 13.3 17C54'); expect(devices[0].cpuArchitecture, DarwinArch.arm64); expect(devices[1].id, '98206e7a4afd4aedaff06e687594e089dede3c44'); expect(devices[1].name, 'iPad 1'); - expect(await devices[1].sdkNameAndVersion, 'iOS 10.1'); + expect(await devices[1].sdkNameAndVersion, 'iOS 10.1 14C54'); expect(devices[1].cpuArchitecture, DarwinArch.armv7); expect(devices[2].id, 'f577a7903cc54959be2e34bc4f7f80b7009efcf4'); expect(devices[2].name, 'iPad 2'); - expect(await devices[2].sdkNameAndVersion, 'iOS 10.1'); + expect(await devices[2].sdkNameAndVersion, 'iOS 10.1 14C54'); expect(devices[2].cpuArchitecture, DarwinArch.arm64); // Defaults to arm64 for unknown architecture. expect(fakeProcessManager.hasRemainingExpectations, isFalse); }, overrides: { @@ -627,6 +627,59 @@ void main() { Platform: () => macPlatform, Artifacts: () => Artifacts.test(), }); + + testUsingContext('Sdk Version is parsed correctly',() async { + const String devicesOutput = ''' +[ + { + "simulator" : false, + "operatingSystemVersion" : "13.3 (17C54)", + "interface" : "usb", + "available" : true, + "platform" : "com.apple.platform.iphoneos", + "modelCode" : "iPhone8,1", + "identifier" : "00008027-00192736010F802E", + "architecture" : "arm64", + "modelName" : "iPhone 6s", + "name" : "An iPhone (Space Gray)" + }, + { + "simulator" : false, + "operatingSystemVersion" : "10.1", + "interface" : "usb", + "available" : true, + "platform" : "com.apple.platform.iphoneos", + "modelCode" : "iPad11,4", + "identifier" : "234234234234234234345445687594e089dede3c44", + "architecture" : "arm64", + "modelName" : "iPad Air 3rd Gen", + "name" : "A networked iPad" + }, + { + "simulator" : false, + "interface" : "usb", + "available" : true, + "platform" : "com.apple.platform.iphoneos", + "modelCode" : "iPad11,4", + "identifier" : "f577a7903cc54959be2e34bc4f7f80b7009efcf4", + "architecture" : "BOGUS", + "modelName" : "iPad Air 3rd Gen", + "name" : "iPad 2" + } +] +'''; + fakeProcessManager.addCommand(const FakeCommand( + command: ['xcrun', 'xcdevice', 'list', '--timeout', '2'], + stdout: devicesOutput, + )); + + final List devices = await xcdevice.getAvailableIOSDevices(); + expect(await devices[0].sdkNameAndVersion,'iOS 13.3 17C54'); + expect(await devices[1].sdkNameAndVersion,'iOS 10.1'); + expect(await devices[2].sdkNameAndVersion,'iOS unknown version'); + }, overrides: { + Platform: () => macPlatform, + }); }); group('diagnostics', () {