Zachary Anderson 6a6874ecf9
Update Android minSdkVersion to 21 (#142267)
This PR increases Android's `minSdkVersion` to 21.

There are two changes in this PR aside from simply increasing the number
from 19 to 21 everywhere.

First, tests using `flutter_gallery` fail without updating the
lockfiles. The changes in the PR are the results of running
`dev/tools/bin/generate_gradle_lockfiles.dart` on that app.

Second, from
[here](https://developer.android.com/build/multidex#mdex-pre-l):
> if your minSdkVersion is 21 or higher, multidex is enabled by default
and you don't need the multidex library.

As a result, the `multidex` option everywhere is obsolete. This PR
removes all logic and tests related to that option that I could find.
`Google testing` and `customer_tests` pass on this PR, so it seems like
this won't be too breaking if it is at all. If needed I'll give this
some time to bake in the framework before landing the flutter/engine
PRs.

Context: https://github.com/flutter/flutter/issues/138117,
https://github.com/flutter/flutter/issues/141277, b/319373605
2024-01-29 09:49:09 -08:00

238 lines
6.5 KiB
Dart

// 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.
import 'dart:async';
import 'base/file_system.dart';
import 'base/logger.dart';
import 'build_info.dart';
import 'globals.dart' as globals;
import 'resident_runner.dart';
import 'tracing.dart';
import 'vmservice.dart';
const String kFlutterTestOutputsDirEnvName = 'FLUTTER_TEST_OUTPUTS_DIR';
class ColdRunner extends ResidentRunner {
ColdRunner(
super.flutterDevices, {
required super.target,
required super.debuggingOptions,
this.traceStartup = false,
this.awaitFirstFrameWhenTracing = true,
this.applicationBinary,
bool super.ipv6 = false,
super.stayResident,
super.machine,
super.devtoolsHandler,
}) : super(
hotMode: false,
);
final bool traceStartup;
final bool awaitFirstFrameWhenTracing;
final File? applicationBinary;
bool _didAttach = false;
@override
bool get canHotReload => false;
@override
Logger get logger => globals.logger;
@override
FileSystem get fileSystem => globals.fs;
@override
Future<int> run({
Completer<DebugConnectionInfo>? connectionInfoCompleter,
Completer<void>? appStartedCompleter,
bool enableDevTools = false,
String? route,
}) async {
try {
for (final FlutterDevice? device in flutterDevices) {
final int result = await device!.runCold(
coldRunner: this,
route: route,
);
if (result != 0) {
appFailedToStart();
return result;
}
}
} on Exception catch (err, stack) {
globals.printError('$err\n$stack');
appFailedToStart();
return 1;
}
// Connect to the VM Service.
if (debuggingEnabled) {
try {
await connectToServiceProtocol(allowExistingDdsInstance: false);
} on Exception catch (exception) {
globals.printError(exception.toString());
appFailedToStart();
return 2;
}
}
if (debuggingEnabled) {
if (enableDevTools) {
// The method below is guaranteed never to return a failing future.
unawaited(residentDevtoolsHandler!.serveAndAnnounceDevTools(
devToolsServerAddress: debuggingOptions.devToolsServerAddress,
flutterDevices: flutterDevices,
isStartPaused: debuggingOptions.startPaused,
));
}
if (debuggingOptions.serveObservatory) {
await enableObservatory();
}
}
if (flutterDevices.first.vmServiceUris != null) {
// For now, only support one debugger connection.
connectionInfoCompleter?.complete(DebugConnectionInfo(
httpUri: flutterDevices.first.vmService!.httpAddress,
wsUri: flutterDevices.first.vmService!.wsAddress,
));
}
globals.printTrace('Application running.');
for (final FlutterDevice? device in flutterDevices) {
if (device!.vmService == null) {
continue;
}
await device.initLogReader();
globals.printTrace('Connected to ${device.device!.name}');
}
if (traceStartup) {
// Only trace startup for the first device.
final FlutterDevice device = flutterDevices.first;
if (device.vmService != null) {
globals.printStatus('Tracing startup on ${device.device!.name}.');
final String outputPath = globals.platform.environment[kFlutterTestOutputsDirEnvName] ?? getBuildDirectory();
await downloadStartupTrace(
device.vmService!,
awaitFirstFrame: awaitFirstFrameWhenTracing,
logger: globals.logger,
output: globals.fs.directory(outputPath),
);
}
appFinished();
}
appStartedCompleter?.complete();
writeVmServiceFile();
if (stayResident && !traceStartup) {
return waitForAppToFinish();
}
await cleanupAtFinish();
return 0;
}
@override
Future<int> attach({
Completer<DebugConnectionInfo>? connectionInfoCompleter,
Completer<void>? appStartedCompleter,
bool allowExistingDdsInstance = false,
bool enableDevTools = false,
bool needsFullRestart = true,
}) async {
_didAttach = true;
try {
await connectToServiceProtocol(
getSkSLMethod: writeSkSL,
allowExistingDdsInstance: allowExistingDdsInstance,
);
} on Exception catch (error) {
globals.printError('Error connecting to the service protocol: $error');
return 2;
}
for (final FlutterDevice? device in flutterDevices) {
await device!.initLogReader();
}
for (final FlutterDevice? device in flutterDevices) {
final List<FlutterView> views = await device!.vmService!.getFlutterViews();
for (final FlutterView view in views) {
globals.printTrace('Connected to $view.');
}
}
if (debuggingEnabled) {
if (enableDevTools) {
// The method below is guaranteed never to return a failing future.
unawaited(residentDevtoolsHandler!.serveAndAnnounceDevTools(
devToolsServerAddress: debuggingOptions.devToolsServerAddress,
flutterDevices: flutterDevices,
isStartPaused: debuggingOptions.startPaused,
));
}
if (debuggingOptions.serveObservatory) {
await enableObservatory();
}
}
appStartedCompleter?.complete();
if (stayResident) {
return waitForAppToFinish();
}
await cleanupAtFinish();
return 0;
}
@override
Future<void> cleanupAfterSignal() async {
await stopEchoingDeviceLog();
if (_didAttach) {
appFinished();
}
await exitApp();
}
@override
Future<void> cleanupAtFinish() async {
for (final FlutterDevice? flutterDevice in flutterDevices) {
await flutterDevice!.device!.dispose();
}
await residentDevtoolsHandler!.shutdown();
await stopEchoingDeviceLog();
}
@override
void printHelp({ required bool details }) {
globals.printStatus('Flutter run key commands.');
if (details) {
printHelpDetails();
commandHelp.hWithDetails.print();
} else {
commandHelp.hWithoutDetails.print();
}
if (_didAttach) {
commandHelp.d.print();
}
commandHelp.c.print();
commandHelp.q.print();
printDebuggerList();
}
@override
Future<void> preExit() async {
for (final FlutterDevice? device in flutterDevices) {
// If we're running in release mode, stop the app using the device logic.
if (device!.vmService == null) {
await device.device!.stopApp(device.package, userIdentifier: device.userIdentifier);
}
}
await super.preExit();
}
}