[flutter_tools] support new SDK structure for sdkmanager (#51980) (#53194)

diff --git a/packages/flutter_tools/lib/src/android/android_sdk.dart b/packages/flutter_tools/lib/src/android/android_sdk.dart
index 6fbe3d3..09f8404 100644
--- a/packages/flutter_tools/lib/src/android/android_sdk.dart
+++ b/packages/flutter_tools/lib/src/android/android_sdk.dart
@@ -283,13 +283,15 @@
   List<AndroidSdkVersion> _sdkVersions;
   AndroidSdkVersion _latestVersion;
 
-  /// Whether the `platform-tools` directory exists in the Android SDK.
+  /// Whether the `platform-tools` or `cmdline-tools` directory exists in the Android SDK.
   ///
   /// It is possible to have an Android SDK folder that is missing this with
   /// the expectation that it will be downloaded later, e.g. by gradle or the
   /// sdkmanager. The [licensesAvailable] property should be used to determine
   /// whether the licenses are at least possibly accepted.
-  bool get platformToolsAvailable => fs.directory(fs.path.join(directory, 'platform-tools')).existsSync();
+  bool get platformToolsAvailable =>
+    fs.directory(fs.path.join(directory, 'cmdline-tools')).existsSync() ||
+    fs.directory(fs.path.join(directory, 'platform-tools')).existsSync();
 
   /// Whether the `licenses` directory exists in the Android SDK.
   ///
@@ -531,8 +533,17 @@
     _latestVersion = _sdkVersions.isEmpty ? null : _sdkVersions.last;
   }
 
-  /// Returns the filesystem path of the Android SDK manager tool or null if not found.
+  /// Returns the filesystem path of the Android SDK manager tool.
+  ///
+  /// The sdkmanager was previously in the tools directory but this component
+  /// was marked as obsolete in 3.6.
   String get sdkManagerPath {
+    final File cmdlineTool = fs.file(
+      fs.path.join(directory, 'cmdline-tools', 'latest', 'bin', 'sdkmanager')
+    );
+    if (cmdlineTool.existsSync()) {
+      return cmdlineTool.path;
+    }
     return fs.path.join(directory, 'tools', 'bin', 'sdkmanager');
   }
 
diff --git a/packages/flutter_tools/lib/src/android/android_workflow.dart b/packages/flutter_tools/lib/src/android/android_workflow.dart
index 543067b..3d415b4 100644
--- a/packages/flutter_tools/lib/src/android/android_workflow.dart
+++ b/packages/flutter_tools/lib/src/android/android_workflow.dart
@@ -311,12 +311,6 @@
       throwToolExit(userMessages.androidMissingSdkManager(androidSdk.sdkManagerPath));
     }
 
-    final Version sdkManagerVersion = Version.parse(androidSdk.sdkManagerVersion);
-    if (sdkManagerVersion == null || sdkManagerVersion.major < 26) {
-      // SDK manager is found, but needs to be updated.
-      throwToolExit(userMessages.androidSdkManagerOutdated(androidSdk.sdkManagerPath));
-    }
-
     try {
       final Process process = await processUtils.start(
         <String>[androidSdk.sdkManagerPath, '--licenses'],
diff --git a/packages/flutter_tools/test/general.shard/android/android_sdk_test.dart b/packages/flutter_tools/test/general.shard/android/android_sdk_test.dart
index 684e57d..98e4154 100644
--- a/packages/flutter_tools/test/general.shard/android/android_sdk_test.dart
+++ b/packages/flutter_tools/test/general.shard/android/android_sdk_test.dart
@@ -8,6 +8,7 @@
 import 'package:flutter_tools/src/base/io.dart' show ProcessResult;
 import 'package:flutter_tools/src/base/platform.dart';
 import 'package:flutter_tools/src/base/config.dart';
+import 'package:flutter_tools/src/globals.dart';
 import 'package:mockito/mockito.dart';
 import 'package:process/process.dart';
 
@@ -60,11 +61,27 @@
       ProcessManager: () => FakeProcessManager.any(),
     });
 
-    testUsingContext('returns sdkmanager path', () {
+    testUsingContext('returns sdkmanager path under cmdline tools', () {
       sdkDir = MockAndroidSdk.createSdkDirectory();
       Config.instance.setValue('android-sdk', sdkDir.path);
 
       final AndroidSdk sdk = AndroidSdk.locateAndroidSdk();
+      fs.file(
+        fs.path.join(sdk.directory, 'cmdline-tools', 'latest', 'bin', 'sdkmanager')
+      ).createSync(recursive: true);
+
+      expect(sdk.sdkManagerPath, fs.path.join(sdk.directory, 'cmdline-tools', 'latest', 'bin', 'sdkmanager'));
+    }, overrides: <Type, Generator>{
+      FileSystem: () => fs,
+      ProcessManager: () => FakeProcessManager.any(),
+    });
+
+    testUsingContext('returns sdkmanager path under tools if cmdline doesnt exist', () {
+      sdkDir = MockAndroidSdk.createSdkDirectory();
+      config.setValue('android-sdk', sdkDir.path);
+
+      final AndroidSdk sdk = AndroidSdk.locateAndroidSdk();
+
       expect(sdk.sdkManagerPath, fs.path.join(sdk.directory, 'tools', 'bin', 'sdkmanager'));
     }, overrides: <Type, Generator>{
       FileSystem: () => fs,
diff --git a/packages/flutter_tools/test/general.shard/android/android_workflow_test.dart b/packages/flutter_tools/test/general.shard/android/android_workflow_test.dart
index 5807ef9..a3b374b 100644
--- a/packages/flutter_tools/test/general.shard/android/android_workflow_test.dart
+++ b/packages/flutter_tools/test/general.shard/android/android_workflow_test.dart
@@ -154,32 +154,6 @@
     Stdio: () => stdio,
   }));
 
-  testUsingContext('runLicenseManager errors for version < 26', () async {
-    when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager');
-    when(sdk.sdkManagerVersion).thenReturn('25.0.0');
-
-    expect(AndroidLicenseValidator.runLicenseManager(), throwsToolExit(message: 'To update, run'));
-  }, overrides: Map<Type, Generator>.unmodifiable(<Type, Generator>{
-    AndroidSdk: () => sdk,
-    FileSystem: () => fs,
-    ProcessManager: () => processManager,
-    Platform: () => FakePlatform()..environment = <String, String>{'HOME': '/home/me'},
-    Stdio: () => stdio,
-  }));
-
-  testUsingContext('runLicenseManager errors correctly for null version', () async {
-    when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager');
-    when(sdk.sdkManagerVersion).thenReturn(null);
-
-    expect(AndroidLicenseValidator.runLicenseManager(), throwsToolExit(message: 'To update, run'));
-  }, overrides: Map<Type, Generator>.unmodifiable(<Type, Generator>{
-    AndroidSdk: () => sdk,
-    FileSystem: () => fs,
-    ProcessManager: () => processManager,
-    Platform: () => FakePlatform()..environment = <String, String>{'HOME': '/home/me'},
-    Stdio: () => stdio,
-  }));
-
   testUsingContext('runLicenseManager errors when sdkmanager is not found', () async {
     when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager');
     processManager.canRunSucceeds = false;