Commit 4d7c3c77 authored by Danny Tuppeny's avatar Danny Tuppeny Committed by Danny Tuppeny

Read information about AVDs from config.ini

parent 486e9534
......@@ -8,6 +8,7 @@ import 'package:meta/meta.dart';
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 AndroidEmulators extends EmulatorDiscovery {
}
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 => _properties['hw.device.name'];
@override
String get manufacturer => _properties['hw.device.manufacturer'];
@override
String get name => id;
String get label => _properties['avd.ini.displayname'];
// @override
// Future<bool> launch() async {
......@@ -41,20 +49,57 @@ class AndroidEmulator extends Emulator {
/// 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.
/// 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
void parseEmulatorAvdOutput(String text,
List<AndroidEmulator> emulators) {
for (String line in text.trim().split('\n')) {
emulators.add(new AndroidEmulator(line));
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;
}
......@@ -59,9 +59,9 @@ String getAdbPath([AndroidSdk existingSdk]) {
}
}
/// 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 @@ String getEmulatorPath([AndroidSdk existingSdk]) {
}
}
/// 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]) {
......
......@@ -43,7 +43,7 @@ class AndroidWorkflow extends DoctorValidator implements Workflow {
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/';
......
......@@ -115,11 +115,13 @@ abstract class EmulatorDiscovery {
}
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 @@ abstract class Emulator {
for (Emulator emulator in emulators) {
table.add(<String>[
emulator.name,
emulator.manufacturer,
emulator.label,
emulator.id,
]);
}
......
......@@ -19,9 +19,9 @@ void main() {
});
testUsingContext('getEmulatorsById', () async {
final _MockEmulator emulator1 = new _MockEmulator('Nexus_5');
final _MockEmulator emulator2 = new _MockEmulator('Nexus_5X_API_27_x86');
final _MockEmulator emulator3 = new _MockEmulator('iOS Simulator');
final _MockEmulator emulator1 = new _MockEmulator('Nexus_5', 'Nexus 5', 'Google', '');
final _MockEmulator emulator2 = new _MockEmulator('Nexus_5X_API_27_x86', 'Nexus 5X', 'Google', '');
final _MockEmulator emulator3 = new _MockEmulator('iOS Simulator', 'iOS Simulator', 'Apple', '');
final List<Emulator> emulators = <Emulator>[emulator1, emulator2, emulator3];
final EmulatorManager emulatorManager = new TestEmulatorManager(emulators);
......@@ -50,8 +50,15 @@ class TestEmulatorManager extends EmulatorManager {
}
class _MockEmulator extends Emulator {
_MockEmulator(String id) : super(id);
_MockEmulator(String id, this.name, this.manufacturer, this.label) : super(id, true);
@override
void noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
final String name;
@override
final String manufacturer;
@override
final String label;
}
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