Read information about AVDs from config.ini
diff --git a/packages/flutter_tools/lib/src/android/android_emulator.dart b/packages/flutter_tools/lib/src/android/android_emulator.dart
index 3602aa0..30dd0fc 100644
--- a/packages/flutter_tools/lib/src/android/android_emulator.dart
+++ b/packages/flutter_tools/lib/src/android/android_emulator.dart
@@ -8,6 +8,7 @@
import '../android/android_sdk.dart';
import '../android/android_workflow.dart';
+import '../base/file_system.dart';
import '../base/process.dart';
import '../emulator.dart';
import 'android_sdk.dart';
@@ -24,12 +25,19 @@
}
class AndroidEmulator extends Emulator {
- AndroidEmulator(
- String id
- ) : super(id);
+ AndroidEmulator(String id, [this._properties])
+ : super(id, _properties != null && _properties.isNotEmpty);
+
+ Map<String, String> _properties;
@override
- String get name => id;
+ String get name => _properties['hw.device.name'];
+
+ @override
+ String get manufacturer => _properties['hw.device.manufacturer'];
+
+ @override
+ String get label => _properties['avd.ini.displayname'];
// @override
// Future<bool> launch() async {
@@ -41,20 +49,57 @@
/// Return the list of available emulator AVDs.
List<AndroidEmulator> getEmulatorAvds() {
final String emulatorPath = getEmulatorPath(androidSdk);
- if (emulatorPath == null)
+ if (emulatorPath == null) {
return <AndroidEmulator>[];
- final String text = runSync(<String>[emulatorPath, '-list-avds']);
+ }
+
+ final String listAvdsOutput = runSync(<String>[emulatorPath, '-list-avds']);
+
final List<AndroidEmulator> emulators = <AndroidEmulator>[];
- parseEmulatorAvdOutput(text, emulators);
+ extractEmulatorAvdInfo(listAvdsOutput, emulators);
return emulators;
}
/// Parse the given `emulator -list-avds` output in [text], and fill out the given list
-/// of emulators.
-@visibleForTesting
-void parseEmulatorAvdOutput(String text,
- List<AndroidEmulator> emulators) {
- for (String line in text.trim().split('\n')) {
- emulators.add(new AndroidEmulator(line));
+/// of emulators by reading information from the relevant ini files.
+void extractEmulatorAvdInfo(String text, List<AndroidEmulator> emulators) {
+ for (String id in text.trim().split('\n')) {
+ emulators.add(_createEmulator(id));
}
}
+
+AndroidEmulator _createEmulator(String id) {
+ id = id.trim();
+ final File iniFile = fs.file(fs.path.join(getAvdPath(), '$id.ini'));
+ final Map<String, String> ini = _parseIniLines(iniFile.readAsLinesSync());
+
+ if (ini['path'] != null) {
+ final File configFile = fs.file(fs.path.join(ini['path'], 'config.ini'));
+ if (configFile.existsSync()) {
+ final Map<String, String> properties = _parseIniLines(configFile.readAsLinesSync());
+ return new AndroidEmulator(id, properties);
+ }
+ }
+
+ return new AndroidEmulator(id);
+}
+
+// TODO: Tests
+@visibleForTesting
+Map<String, String> _parseIniLines(List<String> contents) {
+ final Map<String, String> results = <String, String>{};
+
+ final Iterable<List<String>> properties = contents
+ .map((String l) => l.trim())
+ .where((String l) =>
+ l != '' && !l.startsWith('#')) // Strip blank lines/comments
+ .where((String l) =>
+ l.contains('=')) // Discard anything that isn't simple name=value
+ .map((String l) => l.split('=')); // Split into name/value
+
+ for (List<String> property in properties) {
+ results[property[0].trim()] = property[1].trim();
+ }
+
+ return results;
+}
diff --git a/packages/flutter_tools/lib/src/android/android_sdk.dart b/packages/flutter_tools/lib/src/android/android_sdk.dart
index 1875c48..bc10b95 100644
--- a/packages/flutter_tools/lib/src/android/android_sdk.dart
+++ b/packages/flutter_tools/lib/src/android/android_sdk.dart
@@ -59,9 +59,9 @@
}
}
-/// Locate ADB. Prefer to use one from an Android SDK, if we can locate that.
-/// This should be used over accessing androidSdk.adbPath directly because it
-/// will work for those users who have Android Platform Tools installed but
+/// Locate 'emulator'. Prefer to use one from an Android SDK, if we can locate that.
+/// 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]) {
if (existingSdk?.emulatorPath != null)
@@ -76,6 +76,18 @@
}
}
+/// Locate the path for storing AVD emulator images. Returns null if none found.
+String getAvdPath() {
+ final List<String> searchPaths = <String>[
+ platform.environment['ANDROID_AVD_HOME'],
+ fs.path.join(platform.environment['HOME'], '.android', 'avd'),
+ ];
+ return searchPaths.where((String p) => p != null).firstWhere(
+ (String p) => fs.directory(p).existsSync(),
+ orElse: () => null,
+ );
+}
+
class AndroidSdk {
AndroidSdk(this.directory, [this.ndkDirectory, this.ndkCompiler,
this.ndkCompilerArgs]) {
diff --git a/packages/flutter_tools/lib/src/android/android_workflow.dart b/packages/flutter_tools/lib/src/android/android_workflow.dart
index db40d65..737eb1f 100644
--- a/packages/flutter_tools/lib/src/android/android_workflow.dart
+++ b/packages/flutter_tools/lib/src/android/android_workflow.dart
@@ -43,7 +43,7 @@
bool get canLaunchDevices => androidSdk != null && androidSdk.validateSdkWellFormed().isEmpty;
@override
- bool get canListEmulators => getEmulatorPath(androidSdk) != null;
+ bool get canListEmulators => getEmulatorPath(androidSdk) != null && getAvdPath() != null;
static const String _kJdkDownload = 'https://www.oracle.com/technetwork/java/javase/downloads/';
diff --git a/packages/flutter_tools/lib/src/emulator.dart b/packages/flutter_tools/lib/src/emulator.dart
index 57c647a..af243ed 100644
--- a/packages/flutter_tools/lib/src/emulator.dart
+++ b/packages/flutter_tools/lib/src/emulator.dart
@@ -115,11 +115,13 @@
}
abstract class Emulator {
- Emulator(this.id);
+ Emulator(this.id, this.hasConfig);
final String id;
-
- String get name => id;
+ final bool hasConfig;
+ String get name;
+ String get manufacturer;
+ String get label;
@override
int get hashCode => id.hashCode;
@@ -145,6 +147,8 @@
for (Emulator emulator in emulators) {
table.add(<String>[
emulator.name,
+ emulator.manufacturer,
+ emulator.label,
emulator.id,
]);
}