Use idevice_id, ideviceinfo for iOS device listing (#11883)
This patch migrates iOS device listing from using Xcode instruments to
using the libimobiledevice tools idevice_id and ideviceinfo.
ideviceinfo was previously incompatible with iOS 11 physical devices;
this has now been fixed.
In 37bb5f1300e67fe590c44bb9ecda653b2967e347 flutter_tools migrated from
libimobiledevice-based device listing on iOS to using Xcode instruments
to work around the lack of support for iOS 11. Using instruments entails
several downsides, including a significantly higher performance hit, and
leaking hung DTServiceHub processes in certain cases when a simulator is
running, necessitating workarounds in which we watched for, and cleaned
up leaked DTServiceHub processes. This patch returns reverts the move to
instruments now that it's no longer necessary.
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart
index e6460ae..c33a696 100644
--- a/packages/flutter_tools/lib/src/ios/mac.dart
+++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -70,6 +70,28 @@
return await exitsHappyAsync(<String>['idevicename']);
}
+ Future<String> getAvailableDeviceIDs() async {
+ try {
+ final ProcessResult result = await processManager.run(<String>['idevice_id', '-l']);
+ if (result.exitCode != 0)
+ throw new ToolExit('idevice_id returned an error:\n${result.stderr}');
+ return result.stdout;
+ } on ProcessException {
+ throw new ToolExit('Failed to invoke idevice_id. Run flutter doctor.');
+ }
+ }
+
+ Future<String> getInfoForDevice(String deviceID, String key) async {
+ try {
+ final ProcessResult result = await processManager.run(<String>['ideviceinfo', '-u', deviceID, '-k', key,]);
+ if (result.exitCode != 0)
+ throw new ToolExit('idevice_id returned an error:\n${result.stderr}');
+ return result.stdout.trim();
+ } on ProcessException {
+ throw new ToolExit('Failed to invoke idevice_id. Run flutter doctor.');
+ }
+ }
+
/// Starts `idevicesyslog` and returns the running process.
Future<Process> startLogger() => runCommand(<String>['idevicesyslog']);
@@ -164,48 +186,6 @@
return false;
return _xcodeVersionCheckValid(xcodeMajorVersion, xcodeMinorVersion);
}
-
- final RegExp _processRegExp = new RegExp(r'^(\S+)\s+1\s+(\d+)\s+(.+)$');
-
- /// Kills any orphaned Instruments processes belonging to the user.
- ///
- /// In some cases, we've seen interactions between Instruments and the iOS
- /// simulator that cause hung instruments and DTServiceHub processes. If
- /// enough instances pile up, the host machine eventually becomes
- /// unresponsive. Until the underlying issue is resolved, manually kill any
- /// orphaned instances (where the parent process has died and PPID is 1)
- /// before launching another instruments run.
- Future<Null> _killOrphanedInstrumentsProcesses() async {
- final ProcessResult result = await processManager.run(<String>['ps', '-e', '-o', 'user,ppid,pid,comm']);
- if (result.exitCode != 0)
- return;
- for (String line in result.stdout.split('\n')) {
- final Match match = _processRegExp.firstMatch(line.trim());
- if (match == null || match[1] != platform.environment['USER'])
- continue;
- if (<String>['/instruments', '/DTServiceHub'].any(match[3].endsWith)) {
- try {
- printTrace('Killing orphaned Instruments process: ${match[2]}');
- processManager.killPid(int.parse(match[2]));
- } catch (_) {
- printTrace('Failed to kill orphaned Instruments process:\n$line');
- }
- }
- }
- }
-
- Future<String> getAvailableDevices() async {
- await _killOrphanedInstrumentsProcesses();
- try {
- final ProcessResult result = await processManager.run(
- <String>['/usr/bin/instruments', '-s', 'devices']);
- if (result.exitCode != 0)
- throw new ToolExit('/usr/bin/instruments returned an error:\n${result.stderr}');
- return result.stdout;
- } on ProcessException {
- throw new ToolExit('Failed to invoke /usr/bin/instruments. Is Xcode installed?');
- }
- }
}
bool _xcodeVersionCheckValid(int major, int minor) {