modernize iOS device lookup in driver (#10780)
diff --git a/packages/flutter_tools/lib/src/commands/drive.dart b/packages/flutter_tools/lib/src/commands/drive.dart
index bdc0b9f..0bb14a0 100644
--- a/packages/flutter_tools/lib/src/commands/drive.dart
+++ b/packages/flutter_tools/lib/src/commands/drive.dart
@@ -4,11 +4,9 @@
import 'dart:async';
-import '../android/android_device.dart' show AndroidDevice;
import '../application_package.dart';
import '../base/common.dart';
import '../base/file_system.dart';
-import '../base/platform.dart';
import '../base/process.dart';
import '../build_info.dart';
import '../cache.dart';
@@ -16,7 +14,6 @@
import '../dart/sdk.dart';
import '../device.dart';
import '../globals.dart';
-import '../ios/simulators.dart' show SimControl, IOSSimulatorUtils;
import '../resident_runner.dart';
import 'run.dart';
@@ -198,56 +195,15 @@
return devices.first;
}
-
- if (platform.isMacOS) {
- // On Mac we look for the iOS Simulator. If available, we use that. Then
- // we look for an Android device. If there's one, we use that. Otherwise,
- // we launch a new iOS Simulator.
- Device reusableDevice;
- for (Device device in devices) {
- if (await device.isLocalEmulator) {
- reusableDevice = device;
- break;
- }
- }
- if (reusableDevice == null) {
- for (Device device in devices) {
- if (device is AndroidDevice) {
- reusableDevice = device;
- break;
- }
- }
- }
-
- if (reusableDevice != null) {
- printStatus('Found connected ${await reusableDevice.isLocalEmulator ? "emulator" : "device"} "${reusableDevice.name}"; will reuse it.');
- return reusableDevice;
- }
-
- // No running emulator found. Attempt to start one.
- printStatus('Starting iOS Simulator, because did not find existing connected devices.');
- final bool started = await SimControl.instance.boot();
- if (started) {
- return IOSSimulatorUtils.instance.getAttachedDevices().first;
- } else {
- printError('Failed to start iOS Simulator.');
- return null;
- }
- } else if (platform.isLinux || platform.isWindows) {
- // On Linux and Windows, for now, we just grab the first connected device we can find.
- if (devices.isEmpty) {
- printError('No devices found.');
- return null;
- } else if (devices.length > 1) {
- printStatus('Found multiple connected devices:');
- printStatus(devices.map((Device d) => ' - ${d.name}\n').join(''));
- }
- printStatus('Using device ${devices.first.name}.');
- return devices.first;
- } else {
- printError('The operating system on this computer is not supported.');
+ if (devices.isEmpty) {
+ printError('No devices found.');
return null;
+ } else if (devices.length > 1) {
+ printStatus('Found multiple connected devices:');
+ printStatus(devices.map((Device d) => ' - ${d.name}\n').join(''));
}
+ printStatus('Using device ${devices.first.name}.');
+ return devices.first;
}
/// Starts the application on the device given command configuration.
diff --git a/packages/flutter_tools/lib/src/ios/simulators.dart b/packages/flutter_tools/lib/src/ios/simulators.dart
index 5a57b38..697be3b 100644
--- a/packages/flutter_tools/lib/src/ios/simulators.dart
+++ b/packages/flutter_tools/lib/src/ios/simulators.dart
@@ -59,117 +59,6 @@
/// Returns [SimControl] active in the current app context (i.e. zone).
static SimControl get instance => context[SimControl];
- Future<bool> boot({ String deviceName }) async {
- if (_isAnyConnected())
- return true;
-
- if (deviceName == null) {
- final SimDevice testDevice = _createTestDevice();
- if (testDevice == null) {
- return false;
- }
- deviceName = testDevice.name;
- }
-
- // `xcrun instruments` requires a template (-t). @yjbanov has no idea what
- // "template" is but the built-in 'Blank' seems to work. -l causes xcrun to
- // quit after a time limit without killing the simulator. We quit after
- // 1 second.
- final List<String> args = <String>[_xcrunPath, 'instruments', '-w', deviceName, '-t', 'Blank', '-l', '1'];
- printTrace(args.join(' '));
- runDetached(args);
- printStatus('Waiting for iOS Simulator to boot...');
-
- bool connected = false;
- int attempted = 0;
- while (!connected && attempted < 20) {
- connected = _isAnyConnected();
- if (!connected) {
- printStatus('Still waiting for iOS Simulator to boot...');
- await new Future<Null>.delayed(const Duration(seconds: 1));
- }
- attempted++;
- }
-
- if (connected) {
- printStatus('Connected to iOS Simulator.');
- return true;
- } else {
- printStatus('Timed out waiting for iOS Simulator to boot.');
- return false;
- }
- }
-
- SimDevice _createTestDevice() {
- final SimDeviceType deviceType = _findSuitableDeviceType();
- if (deviceType == null)
- return null;
-
- final String runtime = _findSuitableRuntime();
- if (runtime == null)
- return null;
-
- // Delete any old test devices
- getDevices()
- .where((SimDevice d) => d.name.endsWith(_kFlutterTestDeviceSuffix))
- .forEach(_deleteDevice);
-
- // Create new device
- final String deviceName = '${deviceType.name} $_kFlutterTestDeviceSuffix';
- final List<String> args = <String>[_xcrunPath, 'simctl', 'create', deviceName, deviceType.identifier, runtime];
- printTrace(args.join(' '));
- runCheckedSync(args);
-
- return getDevices().firstWhere((SimDevice d) => d.name == deviceName);
- }
-
- SimDeviceType _findSuitableDeviceType() {
- final List<Map<String, dynamic>> allTypes = _list(SimControlListSection.devicetypes);
- final List<Map<String, dynamic>> usableTypes = allTypes
- .where((Map<String, dynamic> info) => info['name'].startsWith('iPhone'))
- .toList()
- ..sort((Map<String, dynamic> r1, Map<String, dynamic> r2) => -compareIphoneVersions(r1['identifier'], r2['identifier']));
-
- if (usableTypes.isEmpty) {
- printError(
- 'No suitable device type found.\n'
- 'You may launch an iOS Simulator manually and Flutter will attempt to use it.'
- );
- }
-
- return new SimDeviceType(
- usableTypes.first['name'],
- usableTypes.first['identifier']
- );
- }
-
- String _findSuitableRuntime() {
- final List<Map<String, dynamic>> allRuntimes = _list(SimControlListSection.runtimes);
- final List<Map<String, dynamic>> usableRuntimes = allRuntimes
- .where((Map<String, dynamic> info) => info['name'].startsWith('iOS'))
- .toList()
- ..sort((Map<String, dynamic> r1, Map<String, dynamic> r2) => -compareIosVersions(r1['version'], r2['version']));
-
- if (usableRuntimes.isEmpty) {
- printError(
- 'No suitable iOS runtime found.\n'
- 'You may launch an iOS Simulator manually and Flutter will attempt to use it.'
- );
- }
-
- return usableRuntimes.first['identifier'];
- }
-
- void _deleteDevice(SimDevice device) {
- try {
- final List<String> args = <String>[_xcrunPath, 'simctl', 'delete', device.name];
- printTrace(args.join(' '));
- runCheckedSync(args);
- } catch(e) {
- printError(e);
- }
- }
-
/// Runs `simctl list --json` and returns the JSON of the corresponding
/// [section].
///
@@ -226,8 +115,6 @@
return getDevices().where((SimDevice device) => device.isBooted).toList();
}
- bool _isAnyConnected() => getConnectedDevices().isNotEmpty;
-
Future<bool> isInstalled(String deviceId, String appId) {
return exitsHappyAsync(<String>[
_xcrunPath,
diff --git a/packages/flutter_tools/test/commands/drive_test.dart b/packages/flutter_tools/test/commands/drive_test.dart
index beef686..aac7695 100644
--- a/packages/flutter_tools/test/commands/drive_test.dart
+++ b/packages/flutter_tools/test/commands/drive_test.dart
@@ -13,7 +13,6 @@
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/drive.dart';
import 'package:flutter_tools/src/device.dart';
-import 'package:flutter_tools/src/ios/simulators.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
@@ -238,52 +237,7 @@
});
});
- group('findTargetDevice on iOS', () {
- Platform macOsPlatform() => new FakePlatform(operatingSystem: 'macos');
-
- testUsingContext('uses existing emulator', () async {
- withMockDevice();
- when(mockDevice.name).thenReturn('mock-simulator');
- when(mockDevice.isLocalEmulator).thenReturn(new Future<bool>.value(true));
-
- final Device device = await findTargetDevice();
- expect(device.name, 'mock-simulator');
- }, overrides: <Type, Generator>{
- FileSystem: () => fs,
- Platform: macOsPlatform,
- });
-
- testUsingContext('uses existing Android device if and there are no simulators', () async {
- mockDevice = new MockAndroidDevice();
- when(mockDevice.name).thenReturn('mock-android-device');
- when(mockDevice.isLocalEmulator).thenReturn(new Future<bool>.value(false));
- withMockDevice(mockDevice);
-
- final Device device = await findTargetDevice();
- expect(device.name, 'mock-android-device');
- }, overrides: <Type, Generator>{
- FileSystem: () => fs,
- Platform: macOsPlatform,
- });
-
- testUsingContext('launches emulator', () async {
- when(SimControl.instance.boot()).thenReturn(true);
- final Device emulator = new MockDevice();
- when(emulator.name).thenReturn('new-simulator');
- when(IOSSimulatorUtils.instance.getAttachedDevices())
- .thenReturn(<Device>[emulator]);
-
- final Device device = await findTargetDevice();
- expect(device.name, 'new-simulator');
- }, overrides: <Type, Generator>{
- FileSystem: () => fs,
- Platform: macOsPlatform,
- });
- });
-
void findTargetDeviceOnOperatingSystem(String operatingSystem) {
- assert(operatingSystem == 'windows' || operatingSystem == 'linux');
-
Platform platform() => new FakePlatform(operatingSystem: operatingSystem);
testUsingContext('returns null if no devices found', () async {
@@ -313,6 +267,24 @@
group('findTargetDevice on Windows', () {
findTargetDeviceOnOperatingSystem('windows');
});
+
+ group('findTargetDevice on macOS', () {
+ findTargetDeviceOnOperatingSystem('macos');
+
+ Platform macOsPlatform() => new FakePlatform(operatingSystem: 'macos');
+
+ testUsingContext('uses existing simulator', () async {
+ withMockDevice();
+ when(mockDevice.name).thenReturn('mock-simulator');
+ when(mockDevice.isLocalEmulator).thenReturn(new Future<bool>.value(true));
+
+ final Device device = await findTargetDevice();
+ expect(device.name, 'mock-simulator');
+ }, overrides: <Type, Generator>{
+ FileSystem: () => fs,
+ Platform: macOsPlatform,
+ });
+ });
});
}