blob: fef0bad531b47d757e092394ef9b33c2e43f80a0 [file] [log] [blame]
// Copyright 2016 The Vanadium 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:convert';
import 'dart:io';
import 'key_provider.dart';
import 'android.dart';
import 'ios.dart';
import 'device_spec.dart';
import '../globals.dart';
class Device implements GroupKeyProvider {
Device({
this.properties,
String groupKey
}) {
this._groupKey = groupKey;
}
Map<String, String> properties;
String _groupKey;
String get platform => properties['platform'];
String get id => properties['device-id'];
String get modelName => properties['model-name'];
String get screenSize => properties['screen-size'];
String get osVersion => properties['os-version'];
bool isAndroidDevice() => platform == 'android';
bool isIOSDevice() => platform == 'ios';
/// default to 'device-id'
@override
String groupKey() {
if (_groupKey == 'os-version') {
RegExp majorVersionPattern = new RegExp(r'^(\d+)\.\d+\.\d+$');
Match majorVersionMatch = majorVersionPattern.firstMatch(osVersion);
if (majorVersionMatch == null) {
printError('OS version $osVersion does not match semantic version.');
return null;
}
String majorVersion = majorVersionMatch.group(1);
return '$platform $majorVersion.x.x';
}
return properties[_groupKey ?? 'device-id'];
}
@override
String toString()
=> '<platform: $platform, device-id: $id, model-name: $modelName, '
'screen-size: $screenSize, os-version: $osVersion>';
}
Future<List<Device>> getDevices({String groupKey}) async {
List<Device> devices = <Device>[];
List<String> androidIDs = await getAndroidDeviceIDs();
List<String> iosIDs = await getIOSDeviceIDs();
await _getDeviceIDs().then((List<String> ids) async {
for(String id in ids) {
if (androidIDs.contains(id)) {
devices.add(await collectAndroidDeviceProps(id, groupKey: groupKey));
} else if (iosIDs.contains(id)) {
devices.add(await collectIOSDeviceProps(id, groupKey: groupKey));
} else {
// iOS simulator
printError('iOS simulator $id is not supported.');
}
}
});
return devices;
}
/// Run "flutter devices -v" to collect device ids from the output
Future<List<String>> _getDeviceIDs() async {
List<String> deviceIDs = <String>[];
Process process = await Process.start('flutter', ['devices', '-v']);
Stream lineStream = process.stdout
.transform(new Utf8Decoder())
.transform(new LineSplitter());
bool startReading = false;
RegExp startPattern = new RegExp(r'\d+ connected device|No devices detected');
RegExp deviceIDPattern = new RegExp(r'\d+ ms •.*•\s+(\S+)\s+•.*');
RegExp stopPattern = new RegExp(r"'flutter devices' took \d+ms; exiting with code");
await for (var line in lineStream) {
if (!startReading && startPattern.hasMatch(line.toString())) {
startReading = true;
continue;
}
if (stopPattern.hasMatch(line.toString()))
break;
if (startReading) {
Match idMatch = deviceIDPattern.firstMatch(line.toString());
if (idMatch != null) {
String deviceID = idMatch.group(1);
deviceIDs.add(deviceID);
}
}
}
process.stderr.drain();
return deviceIDs;
}
String expandOSVersion(String osVersion) {
RegExp singleNumber = new RegExp(r'^\d+$');
if (singleNumber.hasMatch(osVersion)) {
osVersion = '$osVersion.0.0';
}
RegExp doubleNumber = new RegExp(r'^\d+\.\d+$');
if (doubleNumber.hasMatch(osVersion)) {
osVersion = '$osVersion.0';
}
RegExp tripleNumber = new RegExp(r'^\d+\.\d+\.\d+$');
if (!tripleNumber.hasMatch(osVersion)) {
throw new FormatException(
'OS version $osVersion does not match semantic version.'
);
}
return osVersion;
}
String categorizeScreenSize(num diagonalSize) {
if (diagonalSize < 3.6) return 'small';
if (diagonalSize < 5) return 'normal';
if (diagonalSize < 8) return 'large';
return 'xlarge';
}
/// Uninstall tested apps
Future<int> uninstallTestingApps(
Map<DeviceSpec, Device> deviceMapping
) async {
int result = 0;
for (DeviceSpec spec in deviceMapping.keys) {
Device device = deviceMapping[spec];
if (device.isAndroidDevice()) {
result += await uninstallAndroidTestedApp(spec, device);
} else if (device.isIOSDevice()) {
result += await uninstallIOSTestedApp(spec, device);
} else {
printError(
'Cannot uninstall testing app from device ${device.id}. '
'Platform ${device.platform} is not supported.'
);
}
}
if (result != 0) {
printError('Cannot uninstall testing apps from devices');
return 1;
}
return 0;
}