Unverified Commit 4954a46f authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] shrink API surface of Android SDK (#63867)

Attempt to simplify the Android SDK interface ahead of refactoring it. The locateAndroidSdk static method is called at startup to locate the android SDK, returning null if it cannot be found. These helper methods attempted to first look up the AndroidSDK if it was already null - which could only cover the case where someone installed the Android SDK while flutter was running (possibly through an IDE)
parent 6f781314
...@@ -56,7 +56,7 @@ class AndroidEmulators extends EmulatorDiscovery { ...@@ -56,7 +56,7 @@ class AndroidEmulators extends EmulatorDiscovery {
/// Return the list of available emulator AVDs. /// Return the list of available emulator AVDs.
Future<List<AndroidEmulator>> _getEmulatorAvds() async { Future<List<AndroidEmulator>> _getEmulatorAvds() async {
final String emulatorPath = getEmulatorPath(_androidSdk); final String emulatorPath = _androidSdk.emulatorPath;
if (emulatorPath == null) { if (emulatorPath == null) {
return <AndroidEmulator>[]; return <AndroidEmulator>[];
} }
...@@ -81,7 +81,7 @@ class AndroidEmulators extends EmulatorDiscovery { ...@@ -81,7 +81,7 @@ class AndroidEmulators extends EmulatorDiscovery {
AndroidEmulator _loadEmulatorInfo(String id) { AndroidEmulator _loadEmulatorInfo(String id) {
id = id.trim(); id = id.trim();
final String avdPath = getAvdPath(); final String avdPath = _androidSdk.getAvdPath();
final AndroidEmulator androidEmulatorWithoutProperties = AndroidEmulator( final AndroidEmulator androidEmulatorWithoutProperties = AndroidEmulator(
id, id,
processManager: _processManager, processManager: _processManager,
...@@ -150,7 +150,7 @@ class AndroidEmulator extends Emulator { ...@@ -150,7 +150,7 @@ class AndroidEmulator extends Emulator {
@override @override
Future<void> launch() async { Future<void> launch() async {
final Process process = await _processUtils.start( final Process process = await _processUtils.start(
<String>[getEmulatorPath(_androidSdk), '-avd', id], <String>[_androidSdk.emulatorPath, '-avd', id],
); );
// Record output from the emulator process. // Record output from the emulator process.
......
...@@ -19,20 +19,6 @@ import 'android_studio.dart'; ...@@ -19,20 +19,6 @@ import 'android_studio.dart';
const String kAndroidHome = 'ANDROID_HOME'; const String kAndroidHome = 'ANDROID_HOME';
const String kAndroidSdkRoot = 'ANDROID_SDK_ROOT'; const String kAndroidSdkRoot = 'ANDROID_SDK_ROOT';
// Android SDK layout:
// $ANDROID_SDK_ROOT/platform-tools/adb
// $ANDROID_SDK_ROOT/build-tools/19.1.0/aapt, dx, zipalign
// $ANDROID_SDK_ROOT/build-tools/22.0.1/aapt
// $ANDROID_SDK_ROOT/build-tools/23.0.2/aapt
// $ANDROID_SDK_ROOT/build-tools/24.0.0-preview/aapt
// $ANDROID_SDK_ROOT/build-tools/25.0.2/apksigner
// $ANDROID_SDK_ROOT/platforms/android-22/android.jar
// $ANDROID_SDK_ROOT/platforms/android-23/android.jar
// $ANDROID_SDK_ROOT/platforms/android-N/android.jar
final RegExp _numberedAndroidPlatformRe = RegExp(r'^android-([0-9]+)$'); final RegExp _numberedAndroidPlatformRe = RegExp(r'^android-([0-9]+)$');
final RegExp _sdkVersionRe = RegExp(r'^ro.build.version.sdk=([0-9]+)$'); final RegExp _sdkVersionRe = RegExp(r'^ro.build.version.sdk=([0-9]+)$');
...@@ -43,66 +29,29 @@ const int minimumAndroidSdkVersion = 25; ...@@ -43,66 +29,29 @@ const int minimumAndroidSdkVersion = 25;
/// This should be used over accessing androidSdk.adbPath directly because it /// This should be used over accessing androidSdk.adbPath directly because it
/// will work for those users who have Android Platform Tools installed but /// will work for those users who have Android Platform Tools installed but
/// not the full SDK. /// not the full SDK.
String getAdbPath([ AndroidSdk existingSdk ]) { String getAdbPath(AndroidSdk existingSdk) {
if (existingSdk?.adbPath != null) { if (existingSdk?.adbPath != null) {
return existingSdk.adbPath; return existingSdk.adbPath;
} }
if (existingSdk?.latestVersion == null) {
final AndroidSdk sdk = AndroidSdk.locateAndroidSdk();
if (sdk?.latestVersion == null) {
return globals.os.which('adb')?.path; return globals.os.which('adb')?.path;
} else {
return sdk?.adbPath;
} }
return existingSdk?.adbPath;
} }
/// Locate 'emulator'. Prefer to use one from an Android SDK, if we can locate that. // Android SDK layout:
/// This should be used over accessing androidSdk.emulatorPath directly because it
/// will work for those users who have Android Tools installed but
/// not the full SDK.
String getEmulatorPath([ AndroidSdk existingSdk ]) {
return existingSdk?.emulatorPath ??
AndroidSdk.locateAndroidSdk()?.emulatorPath;
}
/// Locate the path for storing AVD emulator images. Returns null if none found.
String getAvdPath() {
final List<String> searchPaths = <String>[
globals.platform.environment['ANDROID_AVD_HOME'],
if (globals.platform.environment['HOME'] != null)
globals.fs.path.join(globals.platform.environment['HOME'], '.android', 'avd'),
];
if (globals.platform.isWindows) {
final String homeDrive = globals.platform.environment['HOMEDRIVE'];
final String homePath = globals.platform.environment['HOMEPATH'];
if (homeDrive != null && homePath != null) {
// Can't use path.join for HOMEDRIVE/HOMEPATH
// https://github.com/dart-lang/path/issues/37
final String home = homeDrive + homePath;
searchPaths.add(globals.fs.path.join(home, '.android', 'avd'));
}
}
return searchPaths.where((String p) => p != null).firstWhere( // $ANDROID_SDK_ROOT/platform-tools/adb
(String p) => globals.fs.directory(p).existsSync(),
orElse: () => null,
);
}
/// Locate 'avdmanager'. Prefer to use one from an Android SDK, if we can locate that. // $ANDROID_SDK_ROOT/build-tools/19.1.0/aapt, dx, zipalign
/// This should be used over accessing androidSdk.avdManagerPath directly because it // $ANDROID_SDK_ROOT/build-tools/22.0.1/aapt
/// will work for those users who have Android Tools installed but // $ANDROID_SDK_ROOT/build-tools/23.0.2/aapt
/// not the full SDK. // $ANDROID_SDK_ROOT/build-tools/24.0.0-preview/aapt
String getAvdManagerPath([ AndroidSdk existingSdk ]) { // $ANDROID_SDK_ROOT/build-tools/25.0.2/apksigner
return existingSdk?.avdManagerPath ??
AndroidSdk.locateAndroidSdk()?.avdManagerPath;
}
// $ANDROID_SDK_ROOT/platforms/android-22/android.jar
// $ANDROID_SDK_ROOT/platforms/android-23/android.jar
// $ANDROID_SDK_ROOT/platforms/android-N/android.jar
class AndroidSdk { class AndroidSdk {
AndroidSdk(this.directory) { AndroidSdk(this.directory) {
reinitialize(); reinitialize();
...@@ -240,6 +189,32 @@ class AndroidSdk { ...@@ -240,6 +189,32 @@ class AndroidSdk {
String get avdManagerPath => getAvdManagerPath(); String get avdManagerPath => getAvdManagerPath();
/// Locate the path for storing AVD emulator images. Returns null if none found.
String getAvdPath() {
final List<String> searchPaths = <String>[
globals.platform.environment['ANDROID_AVD_HOME'],
if (globals.platform.environment['HOME'] != null)
globals.fs.path.join(globals.platform.environment['HOME'], '.android', 'avd'),
];
if (globals.platform.isWindows) {
final String homeDrive = globals.platform.environment['HOMEDRIVE'];
final String homePath = globals.platform.environment['HOMEPATH'];
if (homeDrive != null && homePath != null) {
// Can't use path.join for HOMEDRIVE/HOMEPATH
// https://github.com/dart-lang/path/issues/37
final String home = homeDrive + homePath;
searchPaths.add(globals.fs.path.join(home, '.android', 'avd'));
}
}
return searchPaths.where((String p) => p != null).firstWhere(
(String p) => globals.fs.directory(p).existsSync(),
orElse: () => null,
);
}
Directory get _platformsDir => globals.fs.directory(globals.fs.path.join(directory, 'platforms')); Directory get _platformsDir => globals.fs.directory(globals.fs.path.join(directory, 'platforms'));
Iterable<Directory> get _platforms { Iterable<Directory> get _platforms {
......
...@@ -64,7 +64,7 @@ class AndroidWorkflow implements Workflow { ...@@ -64,7 +64,7 @@ class AndroidWorkflow implements Workflow {
bool get canLaunchDevices => _androidSdk != null && _androidSdk.validateSdkWellFormed().isEmpty; bool get canLaunchDevices => _androidSdk != null && _androidSdk.validateSdkWellFormed().isEmpty;
@override @override
bool get canListEmulators => getEmulatorPath(_androidSdk) != null; bool get canListEmulators => _androidSdk.emulatorPath != null;
} }
class AndroidValidator extends DoctorValidator { class AndroidValidator extends DoctorValidator {
......
...@@ -140,7 +140,7 @@ class EmulatorManager { ...@@ -140,7 +140,7 @@ class EmulatorManager {
.trim(); .trim();
} }
final RunResult runResult = await _processUtils.run(<String>[ final RunResult runResult = await _processUtils.run(<String>[
getAvdManagerPath(_androidSdk), _androidSdk?.avdManagerPath,
'create', 'create',
'avd', 'avd',
'-n', name, '-n', name,
...@@ -163,7 +163,7 @@ class EmulatorManager { ...@@ -163,7 +163,7 @@ class EmulatorManager {
Future<String> _getPreferredAvailableDevice() async { Future<String> _getPreferredAvailableDevice() async {
final List<String> args = <String>[ final List<String> args = <String>[
getAvdManagerPath(_androidSdk), _androidSdk?.avdManagerPath,
'list', 'list',
'device', 'device',
'-c', '-c',
...@@ -191,7 +191,7 @@ class EmulatorManager { ...@@ -191,7 +191,7 @@ class EmulatorManager {
// It seems that to get the available list of images, we need to send a // It seems that to get the available list of images, we need to send a
// request to create without the image and it'll provide us a list :-( // request to create without the image and it'll provide us a list :-(
final List<String> args = <String>[ final List<String> args = <String>[
getAvdManagerPath(_androidSdk), _androidSdk?.avdManagerPath,
'create', 'create',
'avd', 'avd',
'-n', 'temp', '-n', 'temp',
......
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter_tools/src/android/android_sdk.dart'
show getEmulatorPath;
import 'package:flutter_tools/src/android/android_emulator.dart'; import 'package:flutter_tools/src/android/android_emulator.dart';
import 'package:flutter_tools/src/base/common.dart'; import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
...@@ -144,8 +142,6 @@ void main() { ...@@ -144,8 +142,6 @@ void main() {
logger: BufferLogger.test(), logger: BufferLogger.test(),
); );
expect(getEmulatorPath(mockSdk), mockSdk.emulatorPath);
final Completer<void> completer = Completer<void>(); final Completer<void> completer = Completer<void>();
FakeAsync().run((FakeAsync time) { FakeAsync().run((FakeAsync time) {
unawaited(emulator.launch().whenComplete(completer.complete)); unawaited(emulator.launch().whenComplete(completer.complete));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment