Have android validator suggest ANDROID_SDK_ROOT instead of deprecated ANDROID_HOME (#49846)

diff --git a/packages/flutter_tools/lib/src/android/android_sdk.dart b/packages/flutter_tools/lib/src/android/android_sdk.dart
index a23fc9a..bb4a429 100644
--- a/packages/flutter_tools/lib/src/android/android_sdk.dart
+++ b/packages/flutter_tools/lib/src/android/android_sdk.dart
@@ -3,15 +3,17 @@
 // found in the LICENSE file.
 
 import 'package:meta/meta.dart';
+import 'package:platform/platform.dart';
 
 import '../base/common.dart';
 import '../base/context.dart';
 import '../base/file_system.dart';
+import '../base/os.dart';
 import '../base/process.dart';
 import '../base/version.dart';
 import '../convert.dart';
 import '../globals.dart' as globals;
-import 'android_studio.dart' as android_studio;
+import 'android_studio.dart';
 
 AndroidSdk get androidSdk => context.get<AndroidSdk>();
 
@@ -549,20 +551,25 @@
   }
 
   /// First try Java bundled with Android Studio, then sniff JAVA_HOME, then fallback to PATH.
-  static String findJavaBinary() {
-    if (android_studio.javaPath != null) {
-      return globals.fs.path.join(android_studio.javaPath, 'bin', 'java');
+  static String findJavaBinary({
+    @required AndroidStudio androidStudio,
+    @required FileSystem fileSystem,
+    @required OperatingSystemUtils operatingSystemUtils,
+    @required Platform platform,
+  }) {
+    if (androidStudio?.javaPath != null) {
+      return fileSystem.path.join(androidStudio.javaPath, 'bin', 'java');
     }
 
-    final String javaHomeEnv = globals.platform.environment[_javaHomeEnvironmentVariable];
+    final String javaHomeEnv = platform.environment[_javaHomeEnvironmentVariable];
     if (javaHomeEnv != null) {
       // Trust JAVA_HOME.
-      return globals.fs.path.join(javaHomeEnv, 'bin', 'java');
+      return fileSystem.path.join(javaHomeEnv, 'bin', 'java');
     }
 
     // MacOS specific logic to avoid popping up a dialog window.
     // See: http://stackoverflow.com/questions/14292698/how-do-i-check-if-the-java-jdk-is-installed-on-mac.
-    if (globals.platform.isMacOS) {
+    if (platform.isMacOS) {
       try {
         final String javaHomeOutput = processUtils.runSync(
           <String>['/usr/libexec/java_home'],
@@ -573,14 +580,14 @@
           final List<String> javaHomeOutputSplit = javaHomeOutput.split('\n');
           if ((javaHomeOutputSplit != null) && (javaHomeOutputSplit.isNotEmpty)) {
             final String javaHome = javaHomeOutputSplit[0].trim();
-            return globals.fs.path.join(javaHome, 'bin', 'java');
+            return fileSystem.path.join(javaHome, 'bin', 'java');
           }
         }
       } catch (_) { /* ignore */ }
     }
 
     // Fallback to PATH based lookup.
-    return globals.os.which(_javaExecutable)?.path;
+    return operatingSystemUtils.which(_javaExecutable)?.path;
   }
 
   Map<String, String> _sdkManagerEnv;
@@ -590,7 +597,12 @@
     if (_sdkManagerEnv == null) {
       // If we can locate Java, then add it to the path used to run the Android SDK manager.
       _sdkManagerEnv = <String, String>{};
-      final String javaBinary = findJavaBinary();
+      final String javaBinary = findJavaBinary(
+        androidStudio: globals.androidStudio,
+        fileSystem: globals.fs,
+        operatingSystemUtils: globals.os,
+        platform: globals.platform,
+      );
       if (javaBinary != null) {
         _sdkManagerEnv['PATH'] = globals.fs.path.dirname(javaBinary) +
                                  globals.os.pathVarSeparator +
diff --git a/packages/flutter_tools/lib/src/android/android_workflow.dart b/packages/flutter_tools/lib/src/android/android_workflow.dart
index 6045fa4..0043926 100644
--- a/packages/flutter_tools/lib/src/android/android_workflow.dart
+++ b/packages/flutter_tools/lib/src/android/android_workflow.dart
@@ -4,9 +4,16 @@
 
 import 'dart:async';
 
+import 'package:meta/meta.dart';
+import 'package:platform/platform.dart';
+import 'package:process/process.dart';
+
 import '../base/common.dart';
 import '../base/context.dart';
+import '../base/file_system.dart';
 import '../base/io.dart';
+import '../base/logger.dart';
+import '../base/os.dart';
 import '../base/process.dart';
 import '../base/user_messages.dart';
 import '../base/utils.dart';
@@ -15,6 +22,7 @@
 import '../doctor.dart';
 import '../globals.dart' as globals;
 import 'android_sdk.dart';
+import 'android_studio.dart';
 
 const int kAndroidSdkMinVersion = 28;
 final Version kAndroidJavaMinVersion = Version(1, 8, 0);
@@ -50,7 +58,37 @@
 }
 
 class AndroidValidator extends DoctorValidator {
-  AndroidValidator() : super('Android toolchain - develop for Android devices',);
+  AndroidValidator({
+    @required AndroidSdk androidSdk,
+    @required AndroidStudio androidStudio,
+    @required FileSystem fileSystem,
+    @required Logger logger,
+    @required Platform platform,
+    @required ProcessManager processManager,
+    @required UserMessages userMessages,
+  }) : _androidSdk = androidSdk,
+       _androidStudio = androidStudio,
+       _fileSystem = fileSystem,
+       _logger = logger,
+       _operatingSystemUtils = OperatingSystemUtils(
+         fileSystem: fileSystem,
+         logger: logger,
+         platform: platform,
+         processManager: processManager,
+       ),
+       _platform = platform,
+       _processManager = processManager,
+       _userMessages = userMessages,
+       super('Android toolchain - develop for Android devices');
+
+  final AndroidSdk _androidSdk;
+  final AndroidStudio _androidStudio;
+  final FileSystem _fileSystem;
+  final Logger _logger;
+  final OperatingSystemUtils _operatingSystemUtils;
+  final Platform _platform;
+  final ProcessManager _processManager;
+  final UserMessages _userMessages;
 
   @override
   String get slowWarning => '${_task ?? 'This'} is taking a long time...';
@@ -72,32 +110,32 @@
   Future<bool> _checkJavaVersion(String javaBinary, List<ValidationMessage> messages) async {
     _task = 'Checking Java status';
     try {
-      if (!globals.processManager.canRun(javaBinary)) {
-        messages.add(ValidationMessage.error(userMessages.androidCantRunJavaBinary(javaBinary)));
+      if (!_processManager.canRun(javaBinary)) {
+        messages.add(ValidationMessage.error(_userMessages.androidCantRunJavaBinary(javaBinary)));
         return false;
       }
       String javaVersionText;
       try {
-        globals.printTrace('java -version');
-        final ProcessResult result = await globals.processManager.run(<String>[javaBinary, '-version']);
+        _logger.printTrace('java -version');
+        final ProcessResult result = await _processManager.run(<String>[javaBinary, '-version']);
         if (result.exitCode == 0) {
           final List<String> versionLines = (result.stderr as String).split('\n');
           javaVersionText = versionLines.length >= 2 ? versionLines[1] : versionLines[0];
         }
       } catch (error) {
-        globals.printTrace(error.toString());
+        _logger.printTrace(error.toString());
       }
       if (javaVersionText == null || javaVersionText.isEmpty) {
         // Could not determine the java version.
-        messages.add(ValidationMessage.error(userMessages.androidUnknownJavaVersion));
+        messages.add(ValidationMessage.error(_userMessages.androidUnknownJavaVersion));
         return false;
       }
       final Version javaVersion = Version.parse(_extractJavaVersion(javaVersionText));
       if (javaVersion < kAndroidJavaMinVersion) {
-        messages.add(ValidationMessage.error(userMessages.androidJavaMinimumVersion(javaVersionText)));
+        messages.add(ValidationMessage.error(_userMessages.androidJavaMinimumVersion(javaVersionText)));
         return false;
       }
-      messages.add(ValidationMessage(userMessages.androidJavaVersion(javaVersionText)));
+      messages.add(ValidationMessage(_userMessages.androidJavaVersion(javaVersionText)));
       return true;
     } finally {
       _task = null;
@@ -108,72 +146,79 @@
   Future<ValidationResult> validate() async {
     final List<ValidationMessage> messages = <ValidationMessage>[];
 
-    if (androidSdk == null) {
+    if (_androidSdk == null) {
       // No Android SDK found.
-      if (globals.platform.environment.containsKey(kAndroidHome)) {
-        final String androidHomeDir = globals.platform.environment[kAndroidHome];
-        messages.add(ValidationMessage.error(userMessages.androidBadSdkDir(kAndroidHome, androidHomeDir)));
+      if (_platform.environment.containsKey(kAndroidHome)) {
+        final String androidHomeDir = _platform.environment[kAndroidHome];
+        messages.add(ValidationMessage.error(_userMessages.androidBadSdkDir(kAndroidHome, androidHomeDir)));
       } else {
-        messages.add(ValidationMessage.error(userMessages.androidMissingSdkInstructions(kAndroidHome)));
+        // Instruct user to set [kAndroidSdkRoot] and not deprecated [kAndroidHome]
+        // See https://github.com/flutter/flutter/issues/39301
+        messages.add(ValidationMessage.error(_userMessages.androidMissingSdkInstructions(kAndroidSdkRoot)));
       }
       return ValidationResult(ValidationType.missing, messages);
     }
 
-    if (androidSdk.licensesAvailable && !androidSdk.platformToolsAvailable) {
-      messages.add(ValidationMessage.hint(userMessages.androidSdkLicenseOnly(kAndroidHome)));
+    if (_androidSdk.licensesAvailable && !_androidSdk.platformToolsAvailable) {
+      messages.add(ValidationMessage.hint(_userMessages.androidSdkLicenseOnly(kAndroidHome)));
       return ValidationResult(ValidationType.partial, messages);
     }
 
-    messages.add(ValidationMessage(userMessages.androidSdkLocation(androidSdk.directory)));
+    messages.add(ValidationMessage(_userMessages.androidSdkLocation(_androidSdk.directory)));
 
-    messages.add(ValidationMessage(androidSdk.ndk == null
-          ? userMessages.androidMissingNdk
-          : userMessages.androidNdkLocation(androidSdk.ndk.directory)));
+    messages.add(ValidationMessage(_androidSdk.ndk == null
+          ? _userMessages.androidMissingNdk
+          : _userMessages.androidNdkLocation(_androidSdk.ndk.directory)));
 
     String sdkVersionText;
-    if (androidSdk.latestVersion != null) {
-      if (androidSdk.latestVersion.sdkLevel < 28 || androidSdk.latestVersion.buildToolsVersion < kAndroidSdkBuildToolsMinVersion) {
+    if (_androidSdk.latestVersion != null) {
+      if (_androidSdk.latestVersion.sdkLevel < 28 || _androidSdk.latestVersion.buildToolsVersion < kAndroidSdkBuildToolsMinVersion) {
         messages.add(ValidationMessage.error(
-          userMessages.androidSdkBuildToolsOutdated(androidSdk.sdkManagerPath, kAndroidSdkMinVersion, kAndroidSdkBuildToolsMinVersion.toString())),
+          _userMessages.androidSdkBuildToolsOutdated(_androidSdk.sdkManagerPath, kAndroidSdkMinVersion, kAndroidSdkBuildToolsMinVersion.toString())),
         );
         return ValidationResult(ValidationType.missing, messages);
       }
-      sdkVersionText = userMessages.androidStatusInfo(androidSdk.latestVersion.buildToolsVersionName);
+      sdkVersionText = _userMessages.androidStatusInfo(_androidSdk.latestVersion.buildToolsVersionName);
 
-      messages.add(ValidationMessage(userMessages.androidSdkPlatformToolsVersion(
-        androidSdk.latestVersion.platformName,
-        androidSdk.latestVersion.buildToolsVersionName)));
+      messages.add(ValidationMessage(_userMessages.androidSdkPlatformToolsVersion(
+        _androidSdk.latestVersion.platformName,
+        _androidSdk.latestVersion.buildToolsVersionName)));
     } else {
-      messages.add(ValidationMessage.error(userMessages.androidMissingSdkInstructions(kAndroidHome)));
+      messages.add(ValidationMessage.error(_userMessages.androidMissingSdkInstructions(kAndroidHome)));
     }
 
-    if (globals.platform.environment.containsKey(kAndroidHome)) {
-      final String androidHomeDir = globals.platform.environment[kAndroidHome];
+    if (_platform.environment.containsKey(kAndroidHome)) {
+      final String androidHomeDir = _platform.environment[kAndroidHome];
       messages.add(ValidationMessage('$kAndroidHome = $androidHomeDir'));
     }
-    if (globals.platform.environment.containsKey(kAndroidSdkRoot)) {
-      final String androidSdkRoot = globals.platform.environment[kAndroidSdkRoot];
+    if (_platform.environment.containsKey(kAndroidSdkRoot)) {
+      final String androidSdkRoot = _platform.environment[kAndroidSdkRoot];
       messages.add(ValidationMessage('$kAndroidSdkRoot = $androidSdkRoot'));
     }
 
-    final List<String> validationResult = androidSdk.validateSdkWellFormed();
+    final List<String> validationResult = _androidSdk.validateSdkWellFormed();
 
     if (validationResult.isNotEmpty) {
       // Android SDK is not functional.
       messages.addAll(validationResult.map<ValidationMessage>((String message) {
         return ValidationMessage.error(message);
       }));
-      messages.add(ValidationMessage(userMessages.androidSdkInstallHelp));
+      messages.add(ValidationMessage(_userMessages.androidSdkInstallHelp));
       return ValidationResult(ValidationType.partial, messages, statusInfo: sdkVersionText);
     }
 
     // Now check for the JDK.
-    final String javaBinary = AndroidSdk.findJavaBinary();
+    final String javaBinary = AndroidSdk.findJavaBinary(
+      androidStudio: _androidStudio,
+      fileSystem: _fileSystem,
+      operatingSystemUtils: _operatingSystemUtils,
+      platform: _platform,
+    );
     if (javaBinary == null) {
-      messages.add(ValidationMessage.error(userMessages.androidMissingJdk));
+      messages.add(ValidationMessage.error(_userMessages.androidMissingJdk));
       return ValidationResult(ValidationType.partial, messages, statusInfo: sdkVersionText);
     }
-    messages.add(ValidationMessage(userMessages.androidJdkLocation(javaBinary)));
+    messages.add(ValidationMessage(_userMessages.androidJdkLocation(javaBinary)));
 
     // Check JDK version.
     if (! await _checkJavaVersion(javaBinary, messages)) {
@@ -223,7 +268,12 @@
   }
 
   Future<bool> _checkJavaVersionNoOutput() async {
-    final String javaBinary = AndroidSdk.findJavaBinary();
+    final String javaBinary = AndroidSdk.findJavaBinary(
+      androidStudio: globals.androidStudio,
+      fileSystem: globals.fs,
+      operatingSystemUtils: globals.os,
+      platform: globals.platform,
+    );
     if (javaBinary == null) {
       return false;
     }
diff --git a/packages/flutter_tools/lib/src/cache.dart b/packages/flutter_tools/lib/src/cache.dart
index f375b36..545cbb6 100644
--- a/packages/flutter_tools/lib/src/cache.dart
+++ b/packages/flutter_tools/lib/src/cache.dart
@@ -101,7 +101,7 @@
   }) : _rootOverride = rootOverride,
        _logger = logger ?? globals.logger,
        _fileSystem = fileSystem ?? globals.fs,
-       _platform = platform ?? globals.platform ,
+       _platform = platform ?? globals.platform,
        _osUtils = osUtils ?? globals.os {
     // TODO(zra): Move to initializer list once logger and platform parameters
     // are required.
diff --git a/packages/flutter_tools/lib/src/context_runner.dart b/packages/flutter_tools/lib/src/context_runner.dart
index b6b0bf7..d0f3f54 100644
--- a/packages/flutter_tools/lib/src/context_runner.dart
+++ b/packages/flutter_tools/lib/src/context_runner.dart
@@ -69,7 +69,15 @@
       AndroidLicenseValidator: () => AndroidLicenseValidator(),
       AndroidSdk: AndroidSdk.locateAndroidSdk,
       AndroidStudio: AndroidStudio.latestValid,
-      AndroidValidator: () => AndroidValidator(),
+      AndroidValidator: () => AndroidValidator(
+        androidStudio: globals.androidStudio,
+        androidSdk: globals.androidSdk,
+        fileSystem: globals.fs,
+        logger: globals.logger,
+        platform: globals.platform,
+        processManager: globals.processManager,
+        userMessages: globals.userMessages,
+      ),
       AndroidWorkflow: () => AndroidWorkflow(),
       ApplicationPackageFactory: () => ApplicationPackageFactory(),
       Artifacts: () => CachedArtifacts(
diff --git a/packages/flutter_tools/lib/src/globals.dart b/packages/flutter_tools/lib/src/globals.dart
index eadba0c..1f05bd5 100644
--- a/packages/flutter_tools/lib/src/globals.dart
+++ b/packages/flutter_tools/lib/src/globals.dart
@@ -5,6 +5,8 @@
 import 'package:platform/platform.dart';
 import 'package:process/process.dart';
 
+import 'android/android_sdk.dart';
+import 'android/android_studio.dart';
 import 'artifacts.dart';
 import 'base/config.dart';
 import 'base/context.dart';
@@ -14,6 +16,7 @@
 import 'base/logger.dart';
 import 'base/os.dart';
 import 'base/terminal.dart';
+import 'base/user_messages.dart';
 import 'cache.dart';
 import 'ios/mac.dart';
 import 'macos/xcode.dart';
@@ -53,9 +56,12 @@
 
 Platform get platform => context.get<Platform>() ?? _kLocalPlatform;
 
-Xcode get xcode => context.get<Xcode>();
+AndroidStudio get androidStudio => context.get<AndroidStudio>();
+AndroidSdk get androidSdk => context.get<AndroidSdk>();
 FlutterVersion get flutterVersion => context.get<FlutterVersion>();
 IMobileDevice get iMobileDevice => context.get<IMobileDevice>();
+UserMessages get userMessages => context.get<UserMessages>();
+Xcode get xcode => context.get<Xcode>();
 
 XCDevice get xcdevice => context.get<XCDevice>();