Unverified Commit 0c9a4205 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Migrate android_device to null safety (#92128)

parent 53e04de6
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:async'; import 'dart:async';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
...@@ -60,13 +58,13 @@ class AndroidDevice extends Device { ...@@ -60,13 +58,13 @@ class AndroidDevice extends Device {
AndroidDevice( AndroidDevice(
String id, { String id, {
this.productID, this.productID,
this.modelID, required this.modelID,
this.deviceCodeName, this.deviceCodeName,
@required Logger logger, required Logger logger,
@required ProcessManager processManager, required ProcessManager processManager,
@required Platform platform, required Platform platform,
@required AndroidSdk androidSdk, required AndroidSdk androidSdk,
@required FileSystem fileSystem, required FileSystem fileSystem,
AndroidConsoleSocketFactory androidConsoleSocketFactory = kAndroidConsoleSocketFactory, AndroidConsoleSocketFactory androidConsoleSocketFactory = kAndroidConsoleSocketFactory,
}) : _logger = logger, }) : _logger = logger,
_processManager = processManager, _processManager = processManager,
...@@ -90,17 +88,12 @@ class AndroidDevice extends Device { ...@@ -90,17 +88,12 @@ class AndroidDevice extends Device {
final ProcessUtils _processUtils; final ProcessUtils _processUtils;
final AndroidConsoleSocketFactory _androidConsoleSocketFactory; final AndroidConsoleSocketFactory _androidConsoleSocketFactory;
final String productID; final String? productID;
final String modelID; final String modelID;
final String deviceCodeName; final String? deviceCodeName;
Map<String, String> _properties;
bool _isLocalEmulator;
TargetPlatform _applicationPlatform;
Future<String> _getProperty(String name) async { late final Future<Map<String, String>> _properties = () async {
if (_properties == null) { Map<String, String> properties = <String, String>{};
_properties = <String, String>{};
final List<String> propCommand = adbCommandForDevice(<String>['shell', 'getprop']); final List<String> propCommand = adbCommandForDevice(<String>['shell', 'getprop']);
_logger.printTrace(propCommand.join(' ')); _logger.printTrace(propCommand.join(' '));
...@@ -114,7 +107,7 @@ class AndroidDevice extends Device { ...@@ -114,7 +107,7 @@ class AndroidDevice extends Device {
stderrEncoding: latin1, stderrEncoding: latin1,
); );
if (result.exitCode == 0 || _allowHeapCorruptionOnWindows(result.exitCode, _platform)) { if (result.exitCode == 0 || _allowHeapCorruptionOnWindows(result.exitCode, _platform)) {
_properties = parseAdbDeviceProperties(result.stdout as String); properties = parseAdbDeviceProperties(result.stdout as String);
} else { } else {
_logger.printError('Error ${result.exitCode} retrieving device properties for $name:'); _logger.printError('Error ${result.exitCode} retrieving device properties for $name:');
_logger.printError(result.stderr as String); _logger.printError(result.stderr as String);
...@@ -122,28 +115,26 @@ class AndroidDevice extends Device { ...@@ -122,28 +115,26 @@ class AndroidDevice extends Device {
} on ProcessException catch (error) { } on ProcessException catch (error) {
_logger.printError('Error retrieving device properties for $name: $error'); _logger.printError('Error retrieving device properties for $name: $error');
} }
} return properties;
}();
return _properties[name]; Future<String?> _getProperty(String name) async {
return (await _properties)[name];
} }
@override @override
Future<bool> get isLocalEmulator async { late final Future<bool> isLocalEmulator = () async {
if (_isLocalEmulator == null) { final String? hardware = await _getProperty('ro.hardware');
final String hardware = await _getProperty('ro.hardware');
_logger.printTrace('ro.hardware = $hardware'); _logger.printTrace('ro.hardware = $hardware');
if (kKnownHardware.containsKey(hardware)) { if (kKnownHardware.containsKey(hardware)) {
// Look for known hardware models. // Look for known hardware models.
_isLocalEmulator = kKnownHardware[hardware] == HardwareType.emulator; return kKnownHardware[hardware] == HardwareType.emulator;
} else { }
// Fall back to a best-effort heuristic-based approach. // Fall back to a best-effort heuristic-based approach.
final String characteristics = await _getProperty('ro.build.characteristics'); final String? characteristics = await _getProperty('ro.build.characteristics');
_logger.printTrace('ro.build.characteristics = $characteristics'); _logger.printTrace('ro.build.characteristics = $characteristics');
_isLocalEmulator = characteristics != null && characteristics.contains('emulator'); return characteristics != null && characteristics.contains('emulator');
} }();
}
return _isLocalEmulator;
}
/// The unique identifier for the emulator that corresponds to this device, or /// The unique identifier for the emulator that corresponds to this device, or
/// null if it is not an emulator. /// null if it is not an emulator.
...@@ -152,7 +143,7 @@ class AndroidDevice extends Device { ...@@ -152,7 +143,7 @@ class AndroidDevice extends Device {
/// this name may require connecting to the device and if an error occurs null /// this name may require connecting to the device and if an error occurs null
/// will be returned. /// will be returned.
@override @override
Future<String> get emulatorId async { Future<String?> get emulatorId async {
if (!(await isLocalEmulator)) { if (!(await isLocalEmulator)) {
return null; return null;
} }
...@@ -161,13 +152,13 @@ class AndroidDevice extends Device { ...@@ -161,13 +152,13 @@ class AndroidDevice extends Device {
// Android Console port number. // Android Console port number.
final RegExp emulatorPortRegex = RegExp(r'emulator-(\d+)'); final RegExp emulatorPortRegex = RegExp(r'emulator-(\d+)');
final Match portMatch = emulatorPortRegex.firstMatch(id); final Match? portMatch = emulatorPortRegex.firstMatch(id);
if (portMatch == null || portMatch.groupCount < 1) { if (portMatch == null || portMatch.groupCount < 1) {
return null; return null;
} }
const String host = 'localhost'; const String host = 'localhost';
final int port = int.parse(portMatch.group(1)); final int port = int.parse(portMatch.group(1)!);
_logger.printTrace('Fetching avd name for $name via Android console on $host:$port'); _logger.printTrace('Fetching avd name for $name via Android console on $host:$port');
try { try {
...@@ -196,8 +187,7 @@ class AndroidDevice extends Device { ...@@ -196,8 +187,7 @@ class AndroidDevice extends Device {
} }
@override @override
Future<TargetPlatform> get targetPlatform async { late final Future<TargetPlatform> targetPlatform = () async {
if (_applicationPlatform == null) {
// http://developer.android.com/ndk/guides/abis.html (x86, armeabi-v7a, ...) // http://developer.android.com/ndk/guides/abis.html (x86, armeabi-v7a, ...)
switch (await _getProperty('ro.product.cpu.abi')) { switch (await _getProperty('ro.product.cpu.abi')) {
case 'arm64-v8a': case 'arm64-v8a':
...@@ -205,27 +195,20 @@ class AndroidDevice extends Device { ...@@ -205,27 +195,20 @@ class AndroidDevice extends Device {
// like the Kindle Fire 8, misreport the abilist. We might not // like the Kindle Fire 8, misreport the abilist. We might not
// be able to retrieve this property, in which case we fall back // be able to retrieve this property, in which case we fall back
// to assuming 64 bit. // to assuming 64 bit.
final String abilist = await _getProperty('ro.product.cpu.abilist'); final String? abilist = await _getProperty('ro.product.cpu.abilist');
if (abilist == null || abilist.contains('arm64-v8a')) { if (abilist == null || abilist.contains('arm64-v8a')) {
_applicationPlatform = TargetPlatform.android_arm64; return TargetPlatform.android_arm64;
} else { } else {
_applicationPlatform = TargetPlatform.android_arm; return TargetPlatform.android_arm;
} }
break;
case 'x86_64': case 'x86_64':
_applicationPlatform = TargetPlatform.android_x64; return TargetPlatform.android_x64;
break;
case 'x86': case 'x86':
_applicationPlatform = TargetPlatform.android_x86; return TargetPlatform.android_x86;
break;
default: default:
_applicationPlatform = TargetPlatform.android_arm; return TargetPlatform.android_arm;
break;
}
}
return _applicationPlatform;
} }
}();
@override @override
Future<bool> supportsRuntimeMode(BuildMode buildMode) async { Future<bool> supportsRuntimeMode(BuildMode buildMode) async {
...@@ -249,28 +232,27 @@ class AndroidDevice extends Device { ...@@ -249,28 +232,27 @@ class AndroidDevice extends Device {
case TargetPlatform.windows_x64: case TargetPlatform.windows_x64:
throw UnsupportedError('Invalid target platform for Android'); throw UnsupportedError('Invalid target platform for Android');
} }
throw null; // dead code, remove after null migration
} }
@override @override
Future<String> get sdkNameAndVersion async => 'Android ${await _sdkVersion} (API ${await apiVersion})'; Future<String> get sdkNameAndVersion async => 'Android ${await _sdkVersion} (API ${await apiVersion})';
Future<String> get _sdkVersion => _getProperty('ro.build.version.release'); Future<String?> get _sdkVersion => _getProperty('ro.build.version.release');
@visibleForTesting @visibleForTesting
Future<String> get apiVersion => _getProperty('ro.build.version.sdk'); Future<String?> get apiVersion => _getProperty('ro.build.version.sdk');
AdbLogReader _logReader; AdbLogReader? _logReader;
AdbLogReader _pastLogReader; AdbLogReader? _pastLogReader;
AndroidDevicePortForwarder _portForwarder; AndroidDevicePortForwarder? _portForwarder;
List<String> adbCommandForDevice(List<String> args) { List<String> adbCommandForDevice(List<String> args) {
return <String>[_androidSdk.adbPath, '-s', id, ...args]; return <String>[_androidSdk.adbPath!, '-s', id, ...args];
} }
Future<RunResult> runAdbCheckedAsync( Future<RunResult> runAdbCheckedAsync(
List<String> params, { List<String> params, {
String workingDirectory, String? workingDirectory,
bool allowReentrantFlutter = false, bool allowReentrantFlutter = false,
}) async { }) async {
return _processUtils.run( return _processUtils.run(
...@@ -284,11 +266,11 @@ class AndroidDevice extends Device { ...@@ -284,11 +266,11 @@ class AndroidDevice extends Device {
bool _isValidAdbVersion(String adbVersion) { bool _isValidAdbVersion(String adbVersion) {
// Sample output: 'Android Debug Bridge version 1.0.31' // Sample output: 'Android Debug Bridge version 1.0.31'
final Match versionFields = RegExp(r'(\d+)\.(\d+)\.(\d+)').firstMatch(adbVersion); final Match? versionFields = RegExp(r'(\d+)\.(\d+)\.(\d+)').firstMatch(adbVersion);
if (versionFields != null) { if (versionFields != null) {
final int majorVersion = int.parse(versionFields[1]); final int majorVersion = int.parse(versionFields[1]!);
final int minorVersion = int.parse(versionFields[2]); final int minorVersion = int.parse(versionFields[2]!);
final int patchVersion = int.parse(versionFields[3]); final int patchVersion = int.parse(versionFields[3]!);
if (majorVersion > 1) { if (majorVersion > 1) {
return true; return true;
} }
...@@ -306,19 +288,20 @@ class AndroidDevice extends Device { ...@@ -306,19 +288,20 @@ class AndroidDevice extends Device {
} }
Future<bool> _checkForSupportedAdbVersion() async { Future<bool> _checkForSupportedAdbVersion() async {
if (_androidSdk == null) { final String? adbPath = _androidSdk.adbPath;
if (adbPath == null) {
return false; return false;
} }
try { try {
final RunResult adbVersion = await _processUtils.run( final RunResult adbVersion = await _processUtils.run(
<String>[_androidSdk.adbPath, 'version'], <String>[adbPath, 'version'],
throwOnError: true, throwOnError: true,
); );
if (_isValidAdbVersion(adbVersion.stdout)) { if (_isValidAdbVersion(adbVersion.stdout)) {
return true; return true;
} }
_logger.printError('The ADB at "${_androidSdk.adbPath}" is too old; please install version 1.0.39 or later.'); _logger.printError('The ADB at "$adbPath" is too old; please install version 1.0.39 or later.');
} on Exception catch (error, trace) { } on Exception catch (error, trace) {
_logger.printError('Error running ADB: $error', stackTrace: trace); _logger.printError('Error running ADB: $error', stackTrace: trace);
} }
...@@ -327,13 +310,17 @@ class AndroidDevice extends Device { ...@@ -327,13 +310,17 @@ class AndroidDevice extends Device {
} }
Future<bool> _checkForSupportedAndroidVersion() async { Future<bool> _checkForSupportedAndroidVersion() async {
final String? adbPath = _androidSdk.adbPath;
if (adbPath == null) {
return false;
}
try { try {
// If the server is automatically restarted, then we get irrelevant // If the server is automatically restarted, then we get irrelevant
// output lines like this, which we want to ignore: // output lines like this, which we want to ignore:
// adb server is out of date. killing.. // adb server is out of date. killing..
// * daemon started successfully * // * daemon started successfully *
await _processUtils.run( await _processUtils.run(
<String>[_androidSdk.adbPath, 'start-server'], <String>[adbPath, 'start-server'],
throwOnError: true, throwOnError: true,
); );
...@@ -343,7 +330,7 @@ class AndroidDevice extends Device { ...@@ -343,7 +330,7 @@ class AndroidDevice extends Device {
final String sdkVersion = await _getProperty('ro.build.version.sdk') final String sdkVersion = await _getProperty('ro.build.version.sdk')
?? minApiLevel.toString(); ?? minApiLevel.toString();
final int sdkVersionParsed = int.tryParse(sdkVersion); final int? sdkVersionParsed = int.tryParse(sdkVersion);
if (sdkVersionParsed == null) { if (sdkVersionParsed == null) {
_logger.printError('Unexpected response from getprop: "$sdkVersion"'); _logger.printError('Unexpected response from getprop: "$sdkVersion"');
return false; return false;
...@@ -385,7 +372,7 @@ class AndroidDevice extends Device { ...@@ -385,7 +372,7 @@ class AndroidDevice extends Device {
@override @override
Future<bool> isAppInstalled( Future<bool> isAppInstalled(
AndroidApk app, { AndroidApk app, {
String userIdentifier, String? userIdentifier,
}) async { }) async {
// This call takes 400ms - 600ms. // This call takes 400ms - 600ms.
try { try {
...@@ -414,9 +401,9 @@ class AndroidDevice extends Device { ...@@ -414,9 +401,9 @@ class AndroidDevice extends Device {
@override @override
Future<bool> installApp( Future<bool> installApp(
AndroidApk app, { AndroidApk app, {
String userIdentifier, String? userIdentifier,
}) async { }) async {
if (!await _isAdbValid()) { if (!await _adbIsValid) {
return false; return false;
} }
final bool wasInstalled = await isAppInstalled(app, userIdentifier: userIdentifier); final bool wasInstalled = await isAppInstalled(app, userIdentifier: userIdentifier);
...@@ -446,7 +433,7 @@ class AndroidDevice extends Device { ...@@ -446,7 +433,7 @@ class AndroidDevice extends Device {
Future<bool> _installApp( Future<bool> _installApp(
AndroidApk app, { AndroidApk app, {
String userIdentifier, String? userIdentifier,
}) async { }) async {
if (!app.file.existsSync()) { if (!app.file.existsSync()) {
_logger.printError('"${_fileSystem.path.relative(app.file.path)}" does not exist.'); _logger.printError('"${_fileSystem.path.relative(app.file.path)}" does not exist.');
...@@ -469,7 +456,7 @@ class AndroidDevice extends Device { ...@@ -469,7 +456,7 @@ class AndroidDevice extends Device {
// Some versions of adb exit with exit code 0 even on failure :( // Some versions of adb exit with exit code 0 even on failure :(
// Parsing the output to check for failures. // Parsing the output to check for failures.
final RegExp failureExp = RegExp(r'^Failure.*$', multiLine: true); final RegExp failureExp = RegExp(r'^Failure.*$', multiLine: true);
final String failure = failureExp.stringMatch(installResult.stdout); final String? failure = failureExp.stringMatch(installResult.stdout);
if (failure != null) { if (failure != null) {
_logger.printError('Package install error: $failure'); _logger.printError('Package install error: $failure');
return false; return false;
...@@ -497,9 +484,9 @@ class AndroidDevice extends Device { ...@@ -497,9 +484,9 @@ class AndroidDevice extends Device {
@override @override
Future<bool> uninstallApp( Future<bool> uninstallApp(
AndroidApk app, { AndroidApk app, {
String userIdentifier, String? userIdentifier,
}) async { }) async {
if (!await _isAdbValid()) { if (!await _adbIsValid) {
return false; return false;
} }
...@@ -519,7 +506,7 @@ class AndroidDevice extends Device { ...@@ -519,7 +506,7 @@ class AndroidDevice extends Device {
return false; return false;
} }
final RegExp failureExp = RegExp(r'^Failure.*$', multiLine: true); final RegExp failureExp = RegExp(r'^Failure.*$', multiLine: true);
final String failure = failureExp.stringMatch(uninstallOut); final String? failure = failureExp.stringMatch(uninstallOut);
if (failure != null) { if (failure != null) {
_logger.printError('Package uninstall error: $failure'); _logger.printError('Package uninstall error: $failure');
return false; return false;
...@@ -528,25 +515,24 @@ class AndroidDevice extends Device { ...@@ -528,25 +515,24 @@ class AndroidDevice extends Device {
} }
// Whether the adb and Android versions are aligned. // Whether the adb and Android versions are aligned.
bool _adbIsValid; late final Future<bool> _adbIsValid = () async {
Future<bool> _isAdbValid() async { return await _checkForSupportedAdbVersion() && await _checkForSupportedAndroidVersion();
return _adbIsValid ??= await _checkForSupportedAdbVersion() && await _checkForSupportedAndroidVersion(); }();
}
AndroidApk _package; AndroidApk? _package;
@override @override
Future<LaunchResult> startApp( Future<LaunchResult> startApp(
AndroidApk package, { AndroidApk package, {
String mainPath, String? mainPath,
String route, String? route,
DebuggingOptions debuggingOptions, required DebuggingOptions debuggingOptions,
Map<String, dynamic> platformArgs = const <String, Object>{}, Map<String, Object?> platformArgs = const <String, Object>{},
bool prebuiltApplication = false, bool prebuiltApplication = false,
bool ipv6 = false, bool ipv6 = false,
String userIdentifier, String? userIdentifier,
}) async { }) async {
if (!await _isAdbValid()) { if (!await _adbIsValid) {
return LaunchResult.failed(); return LaunchResult.failed();
} }
...@@ -589,19 +575,19 @@ class AndroidDevice extends Device { ...@@ -589,19 +575,19 @@ class AndroidDevice extends Device {
if (!prebuiltApplication || _androidSdk.licensesAvailable && _androidSdk.latestVersion == null) { if (!prebuiltApplication || _androidSdk.licensesAvailable && _androidSdk.latestVersion == null) {
_logger.printTrace('Building APK'); _logger.printTrace('Building APK');
final FlutterProject project = FlutterProject.current(); final FlutterProject project = FlutterProject.current();
await androidBuilder.buildApk( await androidBuilder!.buildApk(
project: project, project: project,
target: mainPath, target: mainPath ?? 'lib/main.dart',
androidBuildInfo: AndroidBuildInfo( androidBuildInfo: AndroidBuildInfo(
debuggingOptions.buildInfo, debuggingOptions.buildInfo,
targetArchs: <AndroidArch>[androidArch], targetArchs: <AndroidArch>[androidArch],
fastStart: debuggingOptions.fastStart, fastStart: debuggingOptions.fastStart,
multidexEnabled: (platformArgs['multidex'] as bool) ?? false, multidexEnabled: (platformArgs['multidex'] as bool?) ?? false,
), ),
); );
// Package has been built, so we can get the updated application ID and // Package has been built, so we can get the updated application ID and
// activity name from the .apk. // activity name from the .apk.
package = await ApplicationPackageFactory.instance package = await ApplicationPackageFactory.instance!
.getPackageForPlatform(devicePlatform, buildInfo: debuggingOptions.buildInfo) as AndroidApk; .getPackageForPlatform(devicePlatform, buildInfo: debuggingOptions.buildInfo) as AndroidApk;
} }
// There was a failure parsing the android project information. // There was a failure parsing the android project information.
...@@ -616,8 +602,8 @@ class AndroidDevice extends Device { ...@@ -616,8 +602,8 @@ class AndroidDevice extends Device {
return LaunchResult.failed(); return LaunchResult.failed();
} }
final bool traceStartup = platformArgs['trace-startup'] as bool ?? false; final bool traceStartup = platformArgs['trace-startup'] as bool? ?? false;
ProtocolDiscovery observatoryDiscovery; ProtocolDiscovery? observatoryDiscovery;
if (debuggingOptions.debuggingEnabled) { if (debuggingOptions.debuggingEnabled) {
observatoryDiscovery = ProtocolDiscovery.observatory( observatoryDiscovery = ProtocolDiscovery.observatory(
...@@ -637,6 +623,8 @@ class AndroidDevice extends Device { ...@@ -637,6 +623,8 @@ class AndroidDevice extends Device {
} }
final String dartVmFlags = computeDartVmFlags(debuggingOptions); final String dartVmFlags = computeDartVmFlags(debuggingOptions);
final String? traceAllowlist = debuggingOptions.traceAllowlist;
final String? traceSkiaAllowlist = debuggingOptions.traceSkiaAllowlist;
final List<String> cmd = <String>[ final List<String> cmd = <String>[
'shell', 'am', 'start', 'shell', 'am', 'start',
'-a', 'android.intent.action.RUN', '-a', 'android.intent.action.RUN',
...@@ -653,10 +641,10 @@ class AndroidDevice extends Device { ...@@ -653,10 +641,10 @@ class AndroidDevice extends Device {
...<String>['--ez', 'skia-deterministic-rendering', 'true'], ...<String>['--ez', 'skia-deterministic-rendering', 'true'],
if (debuggingOptions.traceSkia) if (debuggingOptions.traceSkia)
...<String>['--ez', 'trace-skia', 'true'], ...<String>['--ez', 'trace-skia', 'true'],
if (debuggingOptions.traceAllowlist != null) if (traceAllowlist != null)
...<String>['--es', 'trace-allowlist', debuggingOptions.traceAllowlist], ...<String>['--es', 'trace-allowlist', traceAllowlist],
if (debuggingOptions.traceSkiaAllowlist != null) if (traceSkiaAllowlist != null)
...<String>['--es', 'trace-skia-allowlist', debuggingOptions.traceSkiaAllowlist], ...<String>['--es', 'trace-skia-allowlist', traceSkiaAllowlist],
if (debuggingOptions.traceSystrace) if (debuggingOptions.traceSystrace)
...<String>['--ez', 'trace-systrace', 'true'], ...<String>['--ez', 'trace-systrace', 'true'],
if (debuggingOptions.endlessTraceBuffer) if (debuggingOptions.endlessTraceBuffer)
...@@ -703,9 +691,9 @@ class AndroidDevice extends Device { ...@@ -703,9 +691,9 @@ class AndroidDevice extends Device {
// device has printed "Observatory is listening on...". // device has printed "Observatory is listening on...".
_logger.printTrace('Waiting for observatory port to be available...'); _logger.printTrace('Waiting for observatory port to be available...');
try { try {
Uri observatoryUri; Uri? observatoryUri;
if (debuggingOptions.buildInfo.isDebug || debuggingOptions.buildInfo.isProfile) { if (debuggingOptions.buildInfo.isDebug || debuggingOptions.buildInfo.isProfile) {
observatoryUri = await observatoryDiscovery.uri; observatoryUri = await observatoryDiscovery?.uri;
if (observatoryUri == null) { if (observatoryUri == null) {
_logger.printError( _logger.printError(
'Error waiting for a debug connection: ' 'Error waiting for a debug connection: '
...@@ -719,7 +707,7 @@ class AndroidDevice extends Device { ...@@ -719,7 +707,7 @@ class AndroidDevice extends Device {
_logger.printError('Error waiting for a debug connection: $error'); _logger.printError('Error waiting for a debug connection: $error');
return LaunchResult.failed(); return LaunchResult.failed();
} finally { } finally {
await observatoryDiscovery.cancel(); await observatoryDiscovery?.cancel();
} }
} }
...@@ -735,7 +723,7 @@ class AndroidDevice extends Device { ...@@ -735,7 +723,7 @@ class AndroidDevice extends Device {
@override @override
Future<bool> stopApp( Future<bool> stopApp(
AndroidApk app, { AndroidApk app, {
String userIdentifier, String? userIdentifier,
}) { }) {
if (app == null) { if (app == null) {
return Future<bool>.value(false); return Future<bool>.value(false);
...@@ -754,11 +742,16 @@ class AndroidDevice extends Device { ...@@ -754,11 +742,16 @@ class AndroidDevice extends Device {
@override @override
Future<MemoryInfo> queryMemoryInfo() async { Future<MemoryInfo> queryMemoryInfo() async {
final AndroidApk? package = _package;
if (package == null) {
_logger.printError('Android package unknown, skipping dumpsys meminfo.');
return const MemoryInfo.empty();
}
final RunResult runResult = await _processUtils.run(adbCommandForDevice(<String>[ final RunResult runResult = await _processUtils.run(adbCommandForDevice(<String>[
'shell', 'shell',
'dumpsys', 'dumpsys',
'meminfo', 'meminfo',
_package.id, package.id,
'-d', '-d',
])); ]));
...@@ -775,7 +768,7 @@ class AndroidDevice extends Device { ...@@ -775,7 +768,7 @@ class AndroidDevice extends Device {
@override @override
FutureOr<DeviceLogReader> getLogReader({ FutureOr<DeviceLogReader> getLogReader({
AndroidApk app, AndroidApk? app,
bool includePastLogs = false, bool includePastLogs = false,
}) async { }) async {
// The Android log reader isn't app-specific. The `app` parameter isn't used. // The Android log reader isn't app-specific. The `app` parameter isn't used.
...@@ -794,19 +787,25 @@ class AndroidDevice extends Device { ...@@ -794,19 +787,25 @@ class AndroidDevice extends Device {
} }
@override @override
DevicePortForwarder get portForwarder => _portForwarder ??= AndroidDevicePortForwarder( late final DevicePortForwarder? portForwarder = () {
final String? adbPath = _androidSdk.adbPath;
if (adbPath == null) {
return null;
}
return AndroidDevicePortForwarder(
processManager: _processManager, processManager: _processManager,
logger: _logger, logger: _logger,
deviceId: id, deviceId: id,
adbPath: _androidSdk.adbPath, adbPath: adbPath,
); );
}();
static final RegExp _timeRegExp = RegExp(r'^\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}', multiLine: true); static final RegExp _timeRegExp = RegExp(r'^\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}', multiLine: true);
/// Return the most recent timestamp in the Android log or [null] if there is /// Return the most recent timestamp in the Android log or [null] if there is
/// no available timestamp. The format can be passed to logcat's -T option. /// no available timestamp. The format can be passed to logcat's -T option.
@visibleForTesting @visibleForTesting
Future<String> lastLogcatTimestamp() async { Future<String?> lastLogcatTimestamp() async {
RunResult output; RunResult output;
try { try {
output = await runAdbCheckedAsync(<String>[ output = await runAdbCheckedAsync(<String>[
...@@ -816,7 +815,7 @@ class AndroidDevice extends Device { ...@@ -816,7 +815,7 @@ class AndroidDevice extends Device {
_logger.printError('Failed to extract the most recent timestamp from the Android log: $error.'); _logger.printError('Failed to extract the most recent timestamp from the Android log: $error.');
return null; return null;
} }
final Match timeMatch = _timeRegExp.firstMatch(output.stdout); final Match? timeMatch = _timeRegExp.firstMatch(output.stdout);
return timeMatch?.group(0); return timeMatch?.group(0);
} }
...@@ -854,7 +853,7 @@ Map<String, String> parseAdbDeviceProperties(String str) { ...@@ -854,7 +853,7 @@ Map<String, String> parseAdbDeviceProperties(String str) {
final Map<String, String> properties = <String, String>{}; final Map<String, String> properties = <String, String>{};
final RegExp propertyExp = RegExp(r'\[(.*?)\]: \[(.*?)\]'); final RegExp propertyExp = RegExp(r'\[(.*?)\]: \[(.*?)\]');
for (final Match match in propertyExp.allMatches(str)) { for (final Match match in propertyExp.allMatches(str)) {
properties[match.group(1)] = match.group(2); properties[match.group(1)!] = match.group(2)!;
} }
return properties; return properties;
} }
...@@ -1011,12 +1010,7 @@ class AndroidMemoryInfo extends MemoryInfo { ...@@ -1011,12 +1010,7 @@ class AndroidMemoryInfo extends MemoryInfo {
/// A log reader that logs from `adb logcat`. /// A log reader that logs from `adb logcat`.
class AdbLogReader extends DeviceLogReader { class AdbLogReader extends DeviceLogReader {
AdbLogReader._(this._adbProcess, this.name) { AdbLogReader._(this._adbProcess, this.name);
_linesController = StreamController<String>.broadcast(
onListen: _start,
onCancel: _stop,
);
}
@visibleForTesting @visibleForTesting
factory AdbLogReader.test(Process adbProcess, String name) = AdbLogReader._; factory AdbLogReader.test(Process adbProcess, String name) = AdbLogReader._;
...@@ -1029,7 +1023,7 @@ class AdbLogReader extends DeviceLogReader { ...@@ -1029,7 +1023,7 @@ class AdbLogReader extends DeviceLogReader {
}) async { }) async {
// logcat -T is not supported on Android releases before Lollipop. // logcat -T is not supported on Android releases before Lollipop.
const int kLollipopVersionCode = 21; const int kLollipopVersionCode = 21;
final int apiVersion = (String v) { final int? apiVersion = (String? v) {
// If the API version string isn't found, conservatively assume that the // If the API version string isn't found, conservatively assume that the
// version is less recent than the one we're looking for. // version is less recent than the one we're looking for.
return v == null ? kLollipopVersionCode - 1 : int.tryParse(v); return v == null ? kLollipopVersionCode - 1 : int.tryParse(v);
...@@ -1052,7 +1046,7 @@ class AdbLogReader extends DeviceLogReader { ...@@ -1052,7 +1046,7 @@ class AdbLogReader extends DeviceLogReader {
} else if (apiVersion != null && apiVersion >= kLollipopVersionCode) { } else if (apiVersion != null && apiVersion >= kLollipopVersionCode) {
// Otherwise, filter for logs appearing past the present. // Otherwise, filter for logs appearing past the present.
// '-T 0` means the timestamp of the logcat command invocation. // '-T 0` means the timestamp of the logcat command invocation.
final String lastLogcatTimestamp = await device.lastLogcatTimestamp(); final String? lastLogcatTimestamp = await device.lastLogcatTimestamp();
args.addAll(<String>[ args.addAll(<String>[
'-T', '-T',
if (lastLogcatTimestamp != null) "'$lastLogcatTimestamp'" else '0', if (lastLogcatTimestamp != null) "'$lastLogcatTimestamp'" else '0',
...@@ -1067,7 +1061,10 @@ class AdbLogReader extends DeviceLogReader { ...@@ -1067,7 +1061,10 @@ class AdbLogReader extends DeviceLogReader {
@override @override
final String name; final String name;
StreamController<String> _linesController; late final StreamController<String> _linesController = StreamController<String>.broadcast(
onListen: _start,
onCancel: _stop,
);
@override @override
Stream<String> get logLines => _linesController.stream; Stream<String> get logLines => _linesController.stream;
...@@ -1128,14 +1125,14 @@ class AdbLogReader extends DeviceLogReader { ...@@ -1128,14 +1125,14 @@ class AdbLogReader extends DeviceLogReader {
if (_linesController.isClosed) { if (_linesController.isClosed) {
return; return;
} }
final Match timeMatch = AndroidDevice._timeRegExp.firstMatch(line); final Match? timeMatch = AndroidDevice._timeRegExp.firstMatch(line);
if (timeMatch == null || line.length == timeMatch.end) { if (timeMatch == null || line.length == timeMatch.end) {
_acceptedLastLine = false; _acceptedLastLine = false;
return; return;
} }
// Chop off the time. // Chop off the time.
line = line.substring(timeMatch.end + 1); line = line.substring(timeMatch.end + 1);
final Match logMatch = _logFormat.firstMatch(line); final Match? logMatch = _logFormat.firstMatch(line);
if (logMatch != null) { if (logMatch != null) {
bool acceptLine = false; bool acceptLine = false;
...@@ -1143,19 +1140,19 @@ class AdbLogReader extends DeviceLogReader { ...@@ -1143,19 +1140,19 @@ class AdbLogReader extends DeviceLogReader {
// While a fatal crash is going on, only accept lines from the crash // While a fatal crash is going on, only accept lines from the crash
// Otherwise the crash log in the console may get interrupted // Otherwise the crash log in the console may get interrupted
final Match fatalMatch = _tombstoneLine.firstMatch(line); final Match? fatalMatch = _tombstoneLine.firstMatch(line);
if (fatalMatch != null) { if (fatalMatch != null) {
acceptLine = true; acceptLine = true;
line = fatalMatch[1]; line = fatalMatch[1]!;
if (_tombstoneTerminator.hasMatch(fatalMatch[1])) { if (_tombstoneTerminator.hasMatch(line)) {
// Hit crash terminator, stop logging the crash info // Hit crash terminator, stop logging the crash info
_fatalCrash = false; _fatalCrash = false;
} }
} }
} else if (appPid != null && int.parse(logMatch.group(1)) == appPid) { } else if (appPid != null && int.parse(logMatch.group(1)!) == appPid) {
acceptLine = true; acceptLine = true;
if (_fatalLog.hasMatch(line)) { if (_fatalLog.hasMatch(line)) {
...@@ -1189,7 +1186,7 @@ class AdbLogReader extends DeviceLogReader { ...@@ -1189,7 +1186,7 @@ class AdbLogReader extends DeviceLogReader {
void _stop() { void _stop() {
_linesController.close(); _linesController.close();
_adbProcess?.kill(); _adbProcess.kill();
} }
@override @override
...@@ -1201,10 +1198,10 @@ class AdbLogReader extends DeviceLogReader { ...@@ -1201,10 +1198,10 @@ class AdbLogReader extends DeviceLogReader {
/// A [DevicePortForwarder] implemented for Android devices that uses adb. /// A [DevicePortForwarder] implemented for Android devices that uses adb.
class AndroidDevicePortForwarder extends DevicePortForwarder { class AndroidDevicePortForwarder extends DevicePortForwarder {
AndroidDevicePortForwarder({ AndroidDevicePortForwarder({
@required ProcessManager processManager, required ProcessManager processManager,
@required Logger logger, required Logger logger,
@required String deviceId, required String deviceId,
@required String adbPath, required String adbPath,
}) : _deviceId = deviceId, }) : _deviceId = deviceId,
_adbPath = adbPath, _adbPath = adbPath,
_logger = logger, _logger = logger,
...@@ -1215,7 +1212,7 @@ class AndroidDevicePortForwarder extends DevicePortForwarder { ...@@ -1215,7 +1212,7 @@ class AndroidDevicePortForwarder extends DevicePortForwarder {
final Logger _logger; final Logger _logger;
final ProcessUtils _processUtils; final ProcessUtils _processUtils;
static int _extractPort(String portString) { static int? _extractPort(String portString) {
return int.tryParse(portString.trim()); return int.tryParse(portString.trim());
} }
...@@ -1253,8 +1250,8 @@ class AndroidDevicePortForwarder extends DevicePortForwarder { ...@@ -1253,8 +1250,8 @@ class AndroidDevicePortForwarder extends DevicePortForwarder {
} }
// Attempt to extract ports. // Attempt to extract ports.
final int hostPort = _extractPort(splitLine[1]); final int? hostPort = _extractPort(splitLine[1]);
final int devicePort = _extractPort(splitLine[2]); final int? devicePort = _extractPort(splitLine[2]);
// Failed, skip. // Failed, skip.
if (hostPort == null || devicePort == null) { if (hostPort == null || devicePort == null) {
...@@ -1268,7 +1265,7 @@ class AndroidDevicePortForwarder extends DevicePortForwarder { ...@@ -1268,7 +1265,7 @@ class AndroidDevicePortForwarder extends DevicePortForwarder {
} }
@override @override
Future<int> forward(int devicePort, { int hostPort }) async { Future<int> forward(int devicePort, { int? hostPort }) async {
hostPort ??= 0; hostPort ??= 0;
final RunResult process = await _processUtils.run( final RunResult process = await _processUtils.run(
<String>[ <String>[
...@@ -1320,7 +1317,7 @@ class AndroidDevicePortForwarder extends DevicePortForwarder { ...@@ -1320,7 +1317,7 @@ class AndroidDevicePortForwarder extends DevicePortForwarder {
} }
} }
return hostPort; return hostPort!;
} }
@override @override
...@@ -1335,7 +1332,6 @@ class AndroidDevicePortForwarder extends DevicePortForwarder { ...@@ -1335,7 +1332,6 @@ class AndroidDevicePortForwarder extends DevicePortForwarder {
'--remove', '--remove',
tcpLine, tcpLine,
], ],
throwOnError: false,
); );
if (runResult.exitCode == 0) { if (runResult.exitCode == 0) {
return; return;
......
...@@ -2,9 +2,6 @@ ...@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:meta/meta.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
import '../base/common.dart'; import '../base/common.dart';
...@@ -29,13 +26,13 @@ import 'android_workflow.dart'; ...@@ -29,13 +26,13 @@ import 'android_workflow.dart';
/// * [AndroidDevice], the type of discovered device. /// * [AndroidDevice], the type of discovered device.
class AndroidDevices extends PollingDeviceDiscovery { class AndroidDevices extends PollingDeviceDiscovery {
AndroidDevices({ AndroidDevices({
@required AndroidWorkflow androidWorkflow, required AndroidWorkflow androidWorkflow,
@required ProcessManager processManager, required ProcessManager processManager,
@required Logger logger, required Logger logger,
@required AndroidSdk androidSdk, AndroidSdk? androidSdk,
@required FileSystem fileSystem, required FileSystem fileSystem,
@required Platform platform, required Platform platform,
@required UserMessages userMessages, required UserMessages userMessages,
}) : _androidWorkflow = androidWorkflow, }) : _androidWorkflow = androidWorkflow,
_androidSdk = androidSdk, _androidSdk = androidSdk,
_processUtils = ProcessUtils( _processUtils = ProcessUtils(
...@@ -51,7 +48,7 @@ class AndroidDevices extends PollingDeviceDiscovery { ...@@ -51,7 +48,7 @@ class AndroidDevices extends PollingDeviceDiscovery {
final AndroidWorkflow _androidWorkflow; final AndroidWorkflow _androidWorkflow;
final ProcessUtils _processUtils; final ProcessUtils _processUtils;
final AndroidSdk _androidSdk; final AndroidSdk? _androidSdk;
final ProcessManager _processManager; final ProcessManager _processManager;
final Logger _logger; final Logger _logger;
final FileSystem _fileSystem; final FileSystem _fileSystem;
...@@ -65,13 +62,13 @@ class AndroidDevices extends PollingDeviceDiscovery { ...@@ -65,13 +62,13 @@ class AndroidDevices extends PollingDeviceDiscovery {
bool get canListAnything => _androidWorkflow.canListDevices; bool get canListAnything => _androidWorkflow.canListDevices;
@override @override
Future<List<Device>> pollingGetDevices({ Duration timeout }) async { Future<List<Device>> pollingGetDevices({ Duration? timeout }) async {
if (_doesNotHaveAdb()) { if (_doesNotHaveAdb()) {
return <AndroidDevice>[]; return <AndroidDevice>[];
} }
String text; String text;
try { try {
text = (await _processUtils.run(<String>[_androidSdk.adbPath, 'devices', '-l'], text = (await _processUtils.run(<String>[_androidSdk!.adbPath!, 'devices', '-l'],
throwOnError: true, throwOnError: true,
)).stdout.trim(); )).stdout.trim();
} on ProcessException catch (exception) { } on ProcessException catch (exception) {
...@@ -94,7 +91,7 @@ class AndroidDevices extends PollingDeviceDiscovery { ...@@ -94,7 +91,7 @@ class AndroidDevices extends PollingDeviceDiscovery {
return <String>[]; return <String>[];
} }
final RunResult result = await _processUtils.run(<String>[_androidSdk.adbPath, 'devices', '-l']); final RunResult result = await _processUtils.run(<String>[_androidSdk!.adbPath!, 'devices', '-l']);
if (result.exitCode != 0) { if (result.exitCode != 0) {
return <String>[]; return <String>[];
} }
...@@ -108,8 +105,8 @@ class AndroidDevices extends PollingDeviceDiscovery { ...@@ -108,8 +105,8 @@ class AndroidDevices extends PollingDeviceDiscovery {
bool _doesNotHaveAdb() { bool _doesNotHaveAdb() {
return _androidSdk == null || return _androidSdk == null ||
_androidSdk.adbPath == null || _androidSdk?.adbPath == null ||
!_processManager.canRun(_androidSdk.adbPath); !_processManager.canRun(_androidSdk!.adbPath);
} }
// 015d172c98400a03 device usb:340787200X product:nakasi model:Nexus_7 device:grouper // 015d172c98400a03 device usb:340787200X product:nakasi model:Nexus_7 device:grouper
...@@ -120,8 +117,8 @@ class AndroidDevices extends PollingDeviceDiscovery { ...@@ -120,8 +117,8 @@ class AndroidDevices extends PollingDeviceDiscovery {
/// in which case information for that parameter won't be populated. /// in which case information for that parameter won't be populated.
void _parseADBDeviceOutput( void _parseADBDeviceOutput(
String text, { String text, {
List<AndroidDevice> devices, List<AndroidDevice>? devices,
List<String> diagnostics, List<String>? diagnostics,
}) { }) {
// Check for error messages from adb // Check for error messages from adb
if (!text.contains('List of devices')) { if (!text.contains('List of devices')) {
...@@ -146,11 +143,11 @@ class AndroidDevices extends PollingDeviceDiscovery { ...@@ -146,11 +143,11 @@ class AndroidDevices extends PollingDeviceDiscovery {
} }
if (_kDeviceRegex.hasMatch(line)) { if (_kDeviceRegex.hasMatch(line)) {
final Match match = _kDeviceRegex.firstMatch(line); final Match match = _kDeviceRegex.firstMatch(line)!;
final String deviceID = match[1]; final String deviceID = match[1]!;
final String deviceState = match[2]; final String deviceState = match[2]!;
String rest = match[3]; String rest = match[3]!;
final Map<String, String> info = <String, String>{}; final Map<String, String> info = <String, String>{};
if (rest != null && rest.isNotEmpty) { if (rest != null && rest.isNotEmpty) {
...@@ -163,8 +160,9 @@ class AndroidDevices extends PollingDeviceDiscovery { ...@@ -163,8 +160,9 @@ class AndroidDevices extends PollingDeviceDiscovery {
} }
} }
if (info['model'] != null) { final String? model = info['model'];
info['model'] = cleanAdbDeviceName(info['model']); if (model != null) {
info['model'] = cleanAdbDeviceName(model);
} }
if (deviceState == 'unauthorized') { if (deviceState == 'unauthorized') {
...@@ -180,7 +178,7 @@ class AndroidDevices extends PollingDeviceDiscovery { ...@@ -180,7 +178,7 @@ class AndroidDevices extends PollingDeviceDiscovery {
productID: info['product'], productID: info['product'],
modelID: info['model'] ?? deviceID, modelID: info['model'] ?? deviceID,
deviceCodeName: info['device'], deviceCodeName: info['device'],
androidSdk: _androidSdk, androidSdk: _androidSdk!,
fileSystem: _fileSystem, fileSystem: _fileSystem,
logger: _logger, logger: _logger,
platform: _platform, platform: _platform,
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:async'; import 'dart:async';
import 'package:flutter_tools/src/android/android_device.dart'; import 'package:flutter_tools/src/android/android_device.dart';
...@@ -183,7 +181,7 @@ void main() { ...@@ -183,7 +181,7 @@ void main() {
}); });
} }
AndroidDevice createFakeDevice(int sdkLevel) { AndroidDevice createFakeDevice(int? sdkLevel) {
return FakeAndroidDevice( return FakeAndroidDevice(
sdkLevel.toString(), sdkLevel.toString(),
kLastLogcatTimestamp, kLastLogcatTimestamp,
......
...@@ -72,7 +72,6 @@ void main() { ...@@ -72,7 +72,6 @@ void main() {
testWithoutContext('AndroidDevices returns empty device list and diagnostics on null Android SDK', () async { testWithoutContext('AndroidDevices returns empty device list and diagnostics on null Android SDK', () async {
final AndroidDevices androidDevices = AndroidDevices( final AndroidDevices androidDevices = AndroidDevices(
androidSdk: null,
logger: BufferLogger.test(), logger: BufferLogger.test(),
androidWorkflow: AndroidWorkflow( androidWorkflow: AndroidWorkflow(
androidSdk: FakeAndroidSdk(null), androidSdk: FakeAndroidSdk(null),
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_tools/src/android/android_device.dart'; import 'package:flutter_tools/src/android/android_device.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/device_port_forwarder.dart'; import 'package:flutter_tools/src/device_port_forwarder.dart';
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/android_device.dart'; import 'package:flutter_tools/src/android/android_device.dart';
import 'package:flutter_tools/src/android/android_sdk.dart'; import 'package:flutter_tools/src/android/android_sdk.dart';
...@@ -42,9 +40,9 @@ const FakeCommand kShaCommand = FakeCommand( ...@@ -42,9 +40,9 @@ const FakeCommand kShaCommand = FakeCommand(
); );
void main() { void main() {
FileSystem fileSystem; late FileSystem fileSystem;
FakeProcessManager processManager; late FakeProcessManager processManager;
AndroidSdk androidSdk; late AndroidSdk androidSdk;
setUp(() { setUp(() {
processManager = FakeProcessManager.empty(); processManager = FakeProcessManager.empty();
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/android_device.dart';
import 'package:flutter_tools/src/android/android_sdk.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:test/fake.dart';
import '../../src/common.dart';
import '../../src/fake_process_manager.dart';
void main() {
testWithoutContext('AndroidDevice.stopApp handles a null ApplicationPackage', () async {
final AndroidDevice androidDevice = AndroidDevice('1234',
androidSdk: FakeAndroidSdk(),
fileSystem: MemoryFileSystem.test(),
logger: BufferLogger.test(),
platform: FakePlatform(),
processManager: FakeProcessManager.any(),
);
expect(await androidDevice.stopApp(null), false);
});
}
class FakeAndroidSdk extends Fake implements AndroidSdk { }
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:typed_data'; import 'dart:typed_data';
...@@ -459,15 +457,16 @@ Uptime: 441088659 Realtime: 521464097 ...@@ -459,15 +457,16 @@ Uptime: 441088659 Realtime: 521464097
} }
AndroidDevice setUpAndroidDevice({ AndroidDevice setUpAndroidDevice({
String id, String? id,
AndroidSdk androidSdk, AndroidSdk? androidSdk,
FileSystem fileSystem, FileSystem? fileSystem,
ProcessManager processManager, ProcessManager? processManager,
Platform platform, Platform? platform,
AndroidConsoleSocketFactory androidConsoleSocketFactory = kAndroidConsoleSocketFactory, AndroidConsoleSocketFactory androidConsoleSocketFactory = kAndroidConsoleSocketFactory,
}) { }) {
androidSdk ??= FakeAndroidSdk(); androidSdk ??= FakeAndroidSdk();
return AndroidDevice(id ?? '1234', return AndroidDevice(id ?? '1234',
modelID: 'TestModel',
logger: BufferLogger.test(), logger: BufferLogger.test(),
platform: platform ?? FakePlatform(), platform: platform ?? FakePlatform(),
androidSdk: androidSdk, androidSdk: androidSdk,
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/android_device.dart'; import 'package:flutter_tools/src/android/android_device.dart';
import 'package:flutter_tools/src/android/android_sdk.dart'; import 'package:flutter_tools/src/android/android_sdk.dart';
...@@ -41,8 +39,8 @@ const FakeCommand kStoreShaCommand = FakeCommand( ...@@ -41,8 +39,8 @@ const FakeCommand kStoreShaCommand = FakeCommand(
); );
void main() { void main() {
FileSystem fileSystem; late FileSystem fileSystem;
BufferLogger logger; late BufferLogger logger;
setUp(() { setUp(() {
fileSystem = MemoryFileSystem.test(); fileSystem = MemoryFileSystem.test();
...@@ -50,15 +48,16 @@ void main() { ...@@ -50,15 +48,16 @@ void main() {
}); });
AndroidDevice setUpAndroidDevice({ AndroidDevice setUpAndroidDevice({
AndroidSdk androidSdk, AndroidSdk? androidSdk,
ProcessManager processManager, ProcessManager? processManager,
}) { }) {
androidSdk ??= FakeAndroidSdk(); androidSdk ??= FakeAndroidSdk();
return AndroidDevice('1234', return AndroidDevice('1234',
modelID: 'TestModel',
logger: logger, logger: logger,
platform: FakePlatform(), platform: FakePlatform(),
androidSdk: androidSdk, androidSdk: androidSdk,
fileSystem: fileSystem ?? MemoryFileSystem.test(), fileSystem: fileSystem,
processManager: processManager ?? FakeProcessManager.any(), processManager: processManager ?? FakeProcessManager.any(),
); );
} }
......
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