Bump minimum ios_deploy version (#24550)

diff --git a/packages/flutter_tools/lib/src/ios/ios_workflow.dart b/packages/flutter_tools/lib/src/ios/ios_workflow.dart
index 07b30ad..c8bc17f 100644
--- a/packages/flutter_tools/lib/src/ios/ios_workflow.dart
+++ b/packages/flutter_tools/lib/src/ios/ios_workflow.dart
@@ -49,7 +49,7 @@
 
   Future<bool> get hasIosDeploy => exitsHappyAsync(<String>['ios-deploy', '--version']);
 
-  String get iosDeployMinimumVersion => '1.9.2';
+  String get iosDeployMinimumVersion => '1.9.4';
 
   Future<String> get iosDeployVersionText async => (await runAsync(<String>['ios-deploy', '--version'])).processResult.stdout.replaceAll('\n', '');
 
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart
index 1847f78..845a696 100644
--- a/packages/flutter_tools/lib/src/ios/mac.dart
+++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -105,6 +105,12 @@
   Future<bool> get isWorking async {
     if (!isInstalled)
       return false;
+    // If usage info is printed in a hyphenated id, we need to update.
+    const String fakeIphoneId = '00008020-001C2D903C42002E';
+    final ProcessResult ideviceResult = (await runAsync(<String>['ideviceinfo', '-u', fakeIphoneId])).processResult;
+    if (ideviceResult.stdout.contains('Usage: ideviceinfo')) {
+      return false;
+    }
 
     // If no device is attached, we're unable to detect any problems. Assume all is well.
     final ProcessResult result = (await runAsync(<String>['idevice_id', '-l'])).processResult;
diff --git a/packages/flutter_tools/test/ios/ios_workflow_test.dart b/packages/flutter_tools/test/ios/ios_workflow_test.dart
index 1004131..8b531e1 100644
--- a/packages/flutter_tools/test/ios/ios_workflow_test.dart
+++ b/packages/flutter_tools/test/ios/ios_workflow_test.dart
@@ -162,6 +162,42 @@
       CocoaPods: () => cocoaPods,
     });
 
+    testUsingContext('Emits partial status when libimobiledevice is installed but not working', () async {
+      when(xcode.isInstalled).thenReturn(true);
+      when(xcode.versionText)
+          .thenReturn('Xcode 8.2.1\nBuild version 8C1002\n');
+      when(xcode.isInstalledAndMeetsVersionCheck).thenReturn(true);
+      when(xcode.eulaSigned).thenReturn(true);
+      when(xcode.isSimctlInstalled).thenReturn(true);
+      when(processManager.run(
+        <String>['ideviceinfo', '-u', '00008020-001C2D903C42002E'],
+        workingDirectory: anyNamed('workingDirectory'),
+        environment: anyNamed('environment')),
+      ).thenAnswer((Invocation _) async {
+        final MockProcessResult result = MockProcessResult();
+        when<String>(result.stdout).thenReturn(r'''
+Usage: ideviceinfo [OPTIONS]
+Show information about a connected device.
+
+  -d, --debug		enable communication debugging
+  -s, --simple		use a simple connection to avoid auto-pairing with the device
+  -u, --udid UDID	target specific device by its 40-digit device UDID
+  -q, --domain NAME	set domain of query to NAME. Default: None
+  -k, --key NAME	only query key specified by NAME. Default: All keys.
+  -x, --xml		output information as xml plist instead of key/value pairs
+  -h, --help		prints usage information
+        ''');
+      });
+      final IOSWorkflowTestTarget workflow = IOSWorkflowTestTarget();
+      final ValidationResult result = await workflow.validate();
+      expect(result.type, ValidationType.partial);
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => processManager,
+      Xcode: () => xcode,
+      CocoaPods: () => cocoaPods,
+    });
+
+
     testUsingContext('Emits partial status when ios-deploy is not installed', () async {
       when(xcode.isInstalled).thenReturn(true);
       when(xcode.versionText)
@@ -313,12 +349,13 @@
 class MockXcode extends Mock implements Xcode {}
 class MockProcessManager extends Mock implements ProcessManager {}
 class MockCocoaPods extends Mock implements CocoaPods {}
+class MockProcessResult extends Mock implements ProcessResult {}
 
 class IOSWorkflowTestTarget extends IOSValidator {
   IOSWorkflowTestTarget({
     this.hasHomebrew = true,
     bool hasIosDeploy = true,
-    String iosDeployVersionText = '1.9.2',
+    String iosDeployVersionText = '1.9.4',
     bool hasIDeviceInstaller = true,
   }) : hasIosDeploy = Future<bool>.value(hasIosDeploy),
        iosDeployVersionText = Future<String>.value(iosDeployVersionText),