Find Java for gradlew executions (#18821)

diff --git a/dev/devicelab/bin/tasks/flutter_gallery_instrumentation_test.dart b/dev/devicelab/bin/tasks/flutter_gallery_instrumentation_test.dart
index 8bff974..668be9e 100644
--- a/dev/devicelab/bin/tasks/flutter_gallery_instrumentation_test.dart
+++ b/dev/devicelab/bin/tasks/flutter_gallery_instrumentation_test.dart
@@ -21,9 +21,8 @@
       await flutter('packages', options: <String>['get']);
       await flutter('clean');
       await flutter('build', options: <String>['apk', '--target', 'test/live_smoketest.dart']);
-      final String androidStudioPath = grep('Android Studio at', from: await evalFlutter('doctor', options: <String>['-v'])).first.split(' ').last;
       await exec('./tool/run_instrumentation_test.sh', <String>[], environment: <String, String>{
-        'JAVA_HOME': '$androidStudioPath/jre',
+        'JAVA_HOME': await findJavaHome(),
       });
     });
 
diff --git a/dev/devicelab/bin/tasks/gradle_plugin_test.dart b/dev/devicelab/bin/tasks/gradle_plugin_test.dart
index 9f828c9..e19110b 100644
--- a/dev/devicelab/bin/tasks/gradle_plugin_test.dart
+++ b/dev/devicelab/bin/tasks/gradle_plugin_test.dart
@@ -27,10 +27,12 @@
 
 void main() async {
   await task(() async {
-    section('Running flutter doctor to get JAVA_HOME');
-    final String flutterDoctor = await evalFlutter('doctor', options: <String>['-v']);
-    final RegExp javaHomeExtractor = new RegExp(r'Android Studio at (.*)');
-    javaHome = javaHomeExtractor.firstMatch(flutterDoctor).group(1) + '/jre';
+    section('Find Java');
+
+    javaHome = await findJavaHome();
+    if (javaHome == null)
+      return new TaskResult.failure('Could not find Java');
+    print('\nUsing JAVA_HOME=$javaHome');
 
     try {
       await runTest((FlutterProject project, FlutterPluginProject pluginProject) async {
diff --git a/dev/devicelab/bin/tasks/module_test.dart b/dev/devicelab/bin/tasks/module_test.dart
index 20faa2e..8d178ee 100644
--- a/dev/devicelab/bin/tasks/module_test.dart
+++ b/dev/devicelab/bin/tasks/module_test.dart
@@ -13,6 +13,13 @@
 Future<Null> main() async {
   await task(() async {
 
+    section('Find Java');
+
+    final String javaHome = await findJavaHome();
+    if (javaHome == null)
+      return new TaskResult.failure('Could not find Java');
+    print('\nUsing JAVA_HOME=$javaHome');
+
     section('Create Flutter module project');
 
     final Directory directory = await Directory.systemTemp.createTemp('module');
@@ -27,7 +34,11 @@
       section('Build Android .aar');
 
       await inDirectory(new Directory(path.join(directory.path, 'hello', '.android')), () async {
-        await exec('./gradlew', <String>['flutter:assembleDebug']);
+        await exec(
+          './gradlew',
+          <String>['flutter:assembleDebug'],
+          environment: <String, String>{ 'JAVA_HOME': javaHome },
+        );
       });
 
       final bool aarBuilt = exists(new File(path.join(
@@ -63,7 +74,10 @@
 
       await inDirectory(hostApp, () async {
         await exec('chmod', <String>['+x', 'gradlew']);
-        await exec('./gradlew', <String>['app:assembleDebug']);
+        await exec('./gradlew',
+          <String>['app:assembleDebug'],
+          environment: <String, String>{ 'JAVA_HOME': javaHome },
+        );
       });
 
       final bool appBuilt = exists(new File(path.join(
diff --git a/dev/devicelab/lib/framework/utils.dart b/dev/devicelab/lib/framework/utils.dart
index 9d9440b..59ed19c 100644
--- a/dev/devicelab/lib/framework/utils.dart
+++ b/dev/devicelab/lib/framework/utils.dart
@@ -348,6 +348,20 @@
 
 Future<int> dart(List<String> args) => exec(dartBin, args);
 
+/// Returns a future that completes with a path suitable for JAVA_HOME
+/// or with null, if Java cannot be found.
+Future<String> findJavaHome() async {
+  final Iterable<String> hits = grep(
+    'Java binary at: ',
+    from: await evalFlutter('doctor', options: <String>['-v']),
+  );
+  if (hits.isEmpty)
+    return null;
+  final String javaBinary = hits.first.split(': ').last;
+  // javaBinary == /some/path/to/java/home/bin/java
+  return path.dirname(path.dirname(javaBinary));
+}
+
 Future<dynamic> inDirectory(dynamic directory, Future<dynamic> action()) async {
   final String previousCwd = cwd;
   try {