
Depending on whether can read the AVD (or it even has all fields populated) we might get extra "empty" columns, so this trims all blank cells from the end.
140 lines
4.3 KiB
Dart
140 lines
4.3 KiB
Dart
// Copyright 2018 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'dart:async';
|
|
import 'dart:math' as math;
|
|
|
|
import 'android/android_emulator.dart';
|
|
import 'base/context.dart';
|
|
import 'globals.dart';
|
|
import 'ios/ios_emulators.dart';
|
|
|
|
EmulatorManager get emulatorManager => context[EmulatorManager];
|
|
|
|
/// A class to get all available emulators.
|
|
class EmulatorManager {
|
|
/// Constructing EmulatorManager is cheap; they only do expensive work if some
|
|
/// of their methods are called.
|
|
EmulatorManager() {
|
|
// Register the known discoverers.
|
|
_emulatorDiscoverers.add(new AndroidEmulators());
|
|
_emulatorDiscoverers.add(new IOSEmulators());
|
|
}
|
|
|
|
final List<EmulatorDiscovery> _emulatorDiscoverers = <EmulatorDiscovery>[];
|
|
|
|
Future<List<Emulator>> getEmulatorsMatching(String searchText) async {
|
|
final List<Emulator> emulators = await getAllAvailableEmulators();
|
|
searchText = searchText.toLowerCase();
|
|
bool exactlyMatchesEmulatorId(Emulator emulator) =>
|
|
emulator.id?.toLowerCase() == searchText ||
|
|
emulator.name?.toLowerCase() == searchText;
|
|
bool startsWithEmulatorId(Emulator emulator) =>
|
|
emulator.id?.toLowerCase()?.startsWith(searchText) == true ||
|
|
emulator.name?.toLowerCase()?.startsWith(searchText) == true;
|
|
|
|
final Emulator exactMatch = emulators.firstWhere(
|
|
exactlyMatchesEmulatorId, orElse: () => null);
|
|
if (exactMatch != null) {
|
|
return <Emulator>[exactMatch];
|
|
}
|
|
|
|
// Match on a id or name starting with [emulatorId].
|
|
return emulators.where(startsWithEmulatorId).toList();
|
|
}
|
|
|
|
Iterable<EmulatorDiscovery> get _platformDiscoverers {
|
|
return _emulatorDiscoverers.where((EmulatorDiscovery discoverer) => discoverer.supportsPlatform);
|
|
}
|
|
|
|
/// Return the list of all available emulators.
|
|
Future<List<Emulator>> getAllAvailableEmulators() async {
|
|
final List<Emulator> emulators = <Emulator>[];
|
|
await Future.forEach(_platformDiscoverers, (EmulatorDiscovery discoverer) async {
|
|
emulators.addAll(await discoverer.emulators);
|
|
});
|
|
return emulators;
|
|
}
|
|
|
|
/// Whether we're capable of listing any emulators given the current environment configuration.
|
|
bool get canListAnything {
|
|
return _platformDiscoverers.any((EmulatorDiscovery discoverer) => discoverer.canListAnything);
|
|
}
|
|
}
|
|
|
|
/// An abstract class to discover and enumerate a specific type of emulators.
|
|
abstract class EmulatorDiscovery {
|
|
bool get supportsPlatform;
|
|
|
|
/// Whether this emulator discovery is capable of listing any emulators given the
|
|
/// current environment configuration.
|
|
bool get canListAnything;
|
|
|
|
Future<List<Emulator>> get emulators;
|
|
}
|
|
|
|
abstract class Emulator {
|
|
Emulator(this.id, this.hasConfig);
|
|
|
|
final String id;
|
|
final bool hasConfig;
|
|
String get name;
|
|
String get manufacturer;
|
|
String get label;
|
|
|
|
@override
|
|
int get hashCode => id.hashCode;
|
|
|
|
@override
|
|
bool operator ==(dynamic other) {
|
|
if (identical(this, other))
|
|
return true;
|
|
if (other is! Emulator)
|
|
return false;
|
|
return id == other.id;
|
|
}
|
|
|
|
Future<void> launch();
|
|
|
|
@override
|
|
String toString() => name;
|
|
|
|
static List<String> descriptions(List<Emulator> emulators) {
|
|
if (emulators.isEmpty)
|
|
return <String>[];
|
|
|
|
// Extract emulators information
|
|
final List<List<String>> table = <List<String>>[];
|
|
for (Emulator emulator in emulators) {
|
|
table.add(<String>[
|
|
emulator.id ?? '',
|
|
emulator.name ?? '',
|
|
emulator.manufacturer ?? '',
|
|
emulator.label ?? '',
|
|
]);
|
|
}
|
|
|
|
// Calculate column widths
|
|
final List<int> indices = new List<int>.generate(table[0].length - 1, (int i) => i);
|
|
List<int> widths = indices.map((int i) => 0).toList();
|
|
for (List<String> row in table) {
|
|
widths = indices.map((int i) => math.max(widths[i], row[i].length)).toList();
|
|
}
|
|
|
|
// Join columns into lines of text
|
|
final RegExp whiteSpaceAndDots = new RegExp(r'[•\s]+$');
|
|
return table.map((List<String> row) {
|
|
return indices
|
|
.map((int i) => row[i].padRight(widths[i]))
|
|
.join(' • ') + ' • ${row.last}';
|
|
})
|
|
.map((String line) => line.replaceAll(whiteSpaceAndDots, ''))
|
|
.toList();
|
|
}
|
|
|
|
static void printEmulators(List<Emulator> emulators) {
|
|
descriptions(emulators).forEach(printStatus);
|
|
}
|
|
}
|