Unverified Commit 39bdff16 authored by Gray Mackall's avatar Gray Mackall Committed by GitHub

Remove embedding v1 code in framework (#144726)

Pre work for https://github.com/flutter/engine/pull/51229. Removes a lot of code referencing v1 of the android embedding, though not necessarily all of it (I may have missed some, it is hard to know).

Will hopefully make landing that PR less painful (or maybe painless?)
parent f9f77a48
......@@ -277,38 +277,6 @@ String? _readFileContent(File file) {
return file.existsSync() ? file.readAsStringSync() : null;
}
const String _androidPluginRegistryTemplateOldEmbedding = '''
package io.flutter.plugins;
import io.flutter.plugin.common.PluginRegistry;
{{#methodChannelPlugins}}
import {{package}}.{{class}};
{{/methodChannelPlugins}}
/**
* Generated file. Do not edit.
*/
public final class GeneratedPluginRegistrant {
public static void registerWith(PluginRegistry registry) {
if (alreadyRegisteredWith(registry)) {
return;
}
{{#methodChannelPlugins}}
{{class}}.registerWith(registry.registrarFor("{{package}}.{{class}}"));
{{/methodChannelPlugins}}
}
private static boolean alreadyRegisteredWith(PluginRegistry registry) {
final String key = GeneratedPluginRegistrant.class.getCanonicalName();
if (registry.hasPlugin(key)) {
return true;
}
registry.registrarFor(key);
return false;
}
}
''';
const String _androidPluginRegistryTemplateNewEmbedding = '''
package io.flutter.plugins;
......@@ -317,9 +285,6 @@ import androidx.annotation.NonNull;
import io.flutter.Log;
import io.flutter.embedding.engine.FlutterEngine;
{{#needsShim}}
import io.flutter.embedding.engine.plugins.shim.ShimPluginRegistry;
{{/needsShim}}
/**
* Generated file. Do not edit.
......@@ -330,9 +295,6 @@ import io.flutter.embedding.engine.plugins.shim.ShimPluginRegistry;
public final class GeneratedPluginRegistrant {
private static final String TAG = "GeneratedPluginRegistrant";
public static void registerWith(@NonNull FlutterEngine flutterEngine) {
{{#needsShim}}
ShimPluginRegistry shimPluginRegistry = new ShimPluginRegistry(flutterEngine);
{{/needsShim}}
{{#methodChannelPlugins}}
{{#supportsEmbeddingV2}}
try {
......@@ -341,15 +303,6 @@ public final class GeneratedPluginRegistrant {
Log.e(TAG, "Error registering plugin {{name}}, {{package}}.{{class}}", e);
}
{{/supportsEmbeddingV2}}
{{^supportsEmbeddingV2}}
{{#supportsEmbeddingV1}}
try {
{{package}}.{{class}}.registerWith(shimPluginRegistry.registrarFor("{{package}}.{{class}}"));
} catch (Exception e) {
Log.e(TAG, "Error registering plugin {{name}}, {{package}}.{{class}}", e);
}
{{/supportsEmbeddingV1}}
{{/supportsEmbeddingV2}}
{{/methodChannelPlugins}}
}
}
......@@ -366,12 +319,6 @@ List<Map<String, Object?>> _extractPlatformMaps(List<Plugin> plugins, String typ
return pluginConfigs;
}
/// Returns the version of the Android embedding that the current
/// [project] is using.
AndroidEmbeddingVersion _getAndroidEmbeddingVersion(FlutterProject project) {
return project.android.getEmbeddingVersion();
}
Future<void> _writeAndroidPluginRegistrant(FlutterProject project, List<Plugin> plugins) async {
final List<Plugin> methodChannelPlugins = _filterMethodChannelPlugins(plugins, AndroidPlugin.kConfigKey);
final List<Map<String, Object?>> androidPlugins = _extractPlatformMaps(methodChannelPlugins, AndroidPlugin.kConfigKey);
......@@ -393,65 +340,7 @@ Future<void> _writeAndroidPluginRegistrant(FlutterProject project, List<Plugin>
'plugins',
'GeneratedPluginRegistrant.java',
);
String templateContent;
final AndroidEmbeddingVersion appEmbeddingVersion = _getAndroidEmbeddingVersion(project);
switch (appEmbeddingVersion) {
case AndroidEmbeddingVersion.v2:
templateContext['needsShim'] = false;
// If a plugin is using an embedding version older than 2.0 and the app is using 2.0,
// then add shim for the old plugins.
final List<String> pluginsUsingV1 = <String>[];
for (final Map<String, Object?> plugin in androidPlugins) {
final bool supportsEmbeddingV1 = (plugin['supportsEmbeddingV1'] as bool?) ?? false;
final bool supportsEmbeddingV2 = (plugin['supportsEmbeddingV2'] as bool?) ?? false;
if (supportsEmbeddingV1 && !supportsEmbeddingV2) {
templateContext['needsShim'] = true;
if (plugin['name'] != null) {
pluginsUsingV1.add(plugin['name']! as String);
}
}
}
if (pluginsUsingV1.length > 1) {
globals.printWarning(
'The plugins `${pluginsUsingV1.join(', ')}` use a deprecated version of the Android embedding.\n'
'To avoid unexpected runtime failures, or future build failures, try to see if these plugins '
'support the Android V2 embedding. Otherwise, consider removing them since a future release '
'of Flutter will remove these deprecated APIs.\n'
'If you are plugin author, take a look at the docs for migrating the plugin to the V2 embedding: '
'https://flutter.dev/go/android-plugin-migration.'
);
} else if (pluginsUsingV1.isNotEmpty) {
globals.printWarning(
'The plugin `${pluginsUsingV1.first}` uses a deprecated version of the Android embedding.\n'
'To avoid unexpected runtime failures, or future build failures, try to see if this plugin '
'supports the Android V2 embedding. Otherwise, consider removing it since a future release '
'of Flutter will remove these deprecated APIs.\n'
'If you are plugin author, take a look at the docs for migrating the plugin to the V2 embedding: '
'https://flutter.dev/go/android-plugin-migration.'
);
}
templateContent = _androidPluginRegistryTemplateNewEmbedding;
case AndroidEmbeddingVersion.v1:
globals.printWarning(
'This app is using a deprecated version of the Android embedding.\n'
'To avoid unexpected runtime failures, or future build failures, try to migrate this '
'app to the V2 embedding.\n'
'Take a look at the docs for migrating an app: https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects'
);
for (final Map<String, Object?> plugin in androidPlugins) {
final bool supportsEmbeddingV1 = (plugin['supportsEmbeddingV1'] as bool?) ?? false;
final bool supportsEmbeddingV2 = (plugin['supportsEmbeddingV2'] as bool?) ?? false;
if (!supportsEmbeddingV1 && supportsEmbeddingV2) {
throwToolExit(
'The plugin `${plugin['name']}` requires your app to be migrated to '
'the Android embedding v2. Follow the steps on the migration doc above '
'and re-run this command.'
);
}
}
templateContent = _androidPluginRegistryTemplateOldEmbedding;
}
const String templateContent = _androidPluginRegistryTemplateNewEmbedding;
globals.printTrace('Generating $registryPath');
await _renderTemplateToFile(
templateContent,
......
......@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'package:meta/meta.dart';
import 'package:unified_analytics/unified_analytics.dart';
import 'package:xml/xml.dart';
import 'package:yaml/yaml.dart';
......@@ -24,7 +23,6 @@ import 'flutter_plugins.dart';
import 'globals.dart' as globals;
import 'platform_plugins.dart';
import 'project_validator_result.dart';
import 'reporting/reporting.dart';
import 'template.dart';
import 'xcode_project.dart';
......@@ -806,47 +804,23 @@ $javaGradleCompatUrl
if (result.version != AndroidEmbeddingVersion.v1) {
return;
}
globals.printStatus(
'''
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Warning
──────────────────────────────────────────────────────────────────────────────
Your Flutter application is created using an older version of the Android
embedding. It is being deprecated in favor of Android embedding v2. To migrate
your project, follow the steps at:
https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
The detected reason was:
${result.reason}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
''');
if (deprecationBehavior == DeprecationBehavior.ignore) {
BuildEvent('deprecated-v1-android-embedding-ignored', type: 'gradle', flutterUsage: globals.flutterUsage).send();
globals.analytics.send(
Event.flutterBuildInfo(
label: 'deprecated-v1-android-embedding-ignored',
buildType: 'gradle',
));
} else { // DeprecationBehavior.exit
globals.analytics.send(
Event.flutterBuildInfo(
label: 'deprecated-v1-android-embedding-failed',
buildType: 'gradle',
));
// The v1 android embedding has been deleted.
throwToolExit(
'Build failed due to use of deprecated Android v1 embedding.',
'Build failed due to use of deleted Android v1 embedding.',
exitCode: 1,
);
}
}
AndroidEmbeddingVersion getEmbeddingVersion() {
return computeEmbeddingVersion().version;
final AndroidEmbeddingVersion androidEmbeddingVersion = computeEmbeddingVersion().version;
if (androidEmbeddingVersion == AndroidEmbeddingVersion.v1) {
throwToolExit(
'Build failed due to use of deleted Android v1 embedding.',
exitCode: 1,
);
}
return androidEmbeddingVersion;
}
AndroidEmbeddingVersionResult computeEmbeddingVersion() {
......
......@@ -16,6 +16,17 @@ import 'package:test/fake.dart';
import '../../src/context.dart';
import '../../src/test_flutter_command_runner.dart';
const String minimalV2EmbeddingManifest = r'''
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:name="${applicationName}">
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
''';
void main() {
late FileSystem fileSystem;
late FakePub pub;
......@@ -48,6 +59,9 @@ void main() {
fileSystem.currentDirectory.childFile('pubspec.yaml').createSync();
fileSystem.currentDirectory.childFile('.flutter-plugins').createSync();
fileSystem.currentDirectory.childFile('.flutter-plugins-dependencies').createSync();
fileSystem.currentDirectory.childDirectory('android').childFile('AndroidManifest.xml')
..createSync(recursive: true)
..writeAsStringSync(minimalV2EmbeddingManifest);
final PackagesGetCommand command = PackagesGetCommand('get', '', PubContext.pubGet);
final CommandRunner<void> commandRunner = createTestCommandRunner(command);
......@@ -57,7 +71,7 @@ void main() {
expect(await command.usageValues, const CustomDimensions(
commandPackagesNumberPlugins: 0,
commandPackagesProjectModule: false,
commandPackagesAndroidEmbeddingVersion: 'v1',
commandPackagesAndroidEmbeddingVersion: 'v2',
));
}, overrides: <Type, Generator>{
Pub: () => pub,
......@@ -73,6 +87,9 @@ void main() {
fileSystem.currentDirectory.childFile('.dart_tool/package_config.json')
..createSync(recursive: true)
..writeAsBytesSync(<int>[0]);
fileSystem.currentDirectory.childDirectory('android').childFile('AndroidManifest.xml')
..createSync(recursive: true)
..writeAsStringSync(minimalV2EmbeddingManifest);
final PackagesGetCommand command = PackagesGetCommand('get', '', PubContext.pubGet);
final CommandRunner<void> commandRunner = createTestCommandRunner(command);
......@@ -82,7 +99,7 @@ void main() {
expect(await command.usageValues, const CustomDimensions(
commandPackagesNumberPlugins: 0,
commandPackagesProjectModule: false,
commandPackagesAndroidEmbeddingVersion: 'v1',
commandPackagesAndroidEmbeddingVersion: 'v2',
));
}, overrides: <Type, Generator>{
Pub: () => pub,
......@@ -137,6 +154,9 @@ void main() {
testUsingContext("pub get skips example directory if it doesn't contain a pubspec.yaml", () async {
fileSystem.currentDirectory.childFile('pubspec.yaml').createSync();
fileSystem.currentDirectory.childDirectory('example').createSync(recursive: true);
fileSystem.currentDirectory.childDirectory('android').childFile('AndroidManifest.xml')
..createSync(recursive: true)
..writeAsStringSync(minimalV2EmbeddingManifest);
final PackagesGetCommand command = PackagesGetCommand('get', '', PubContext.pubGet);
final CommandRunner<void> commandRunner = createTestCommandRunner(command);
......@@ -146,7 +166,7 @@ void main() {
expect(await command.usageValues, const CustomDimensions(
commandPackagesNumberPlugins: 0,
commandPackagesProjectModule: false,
commandPackagesAndroidEmbeddingVersion: 'v1',
commandPackagesAndroidEmbeddingVersion: 'v2',
));
}, overrides: <Type, Generator>{
Pub: () => pub,
......
......@@ -7,15 +7,12 @@ import 'dart:async';
import 'package:args/command_runner.dart';
import 'package:file/file.dart';
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/application_package.dart';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart';
......@@ -369,84 +366,6 @@ void main() {
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
});
testUsingContext('fails when v1 FlutterApplication is detected', () async {
fs.file('pubspec.yaml').createSync();
fs.file('android/AndroidManifest.xml')
..createSync(recursive: true)
..writeAsStringSync('''
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.v1">
<application
android:name="io.flutter.app.FlutterApplication">
</application>
</manifest>
''', flush: true);
fs.file('.packages').writeAsStringSync('\n');
fs.file('lib/main.dart').createSync(recursive: true);
final AndroidDevice device = AndroidDevice('1234',
modelID: 'TestModel',
logger: testLogger,
platform: FakePlatform(),
androidSdk: FakeAndroidSdk(),
fileSystem: fs,
processManager: FakeProcessManager.any(),
);
testDeviceManager.devices = <Device>[device];
final RunCommand command = RunCommand();
await expectLater(createTestCommandRunner(command).run(<String>[
'run',
'--pub',
]), throwsToolExit(message: 'Build failed due to use of deprecated Android v1 embedding.'));
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
DeviceManager: () => testDeviceManager,
Stdio: () => FakeStdio(),
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
});
testUsingContext('fails when v1 metadata is detected', () async {
fs.file('pubspec.yaml').createSync();
fs.file('android/AndroidManifest.xml')
..createSync(recursive: true)
..writeAsStringSync('''
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.v1">
<application >
<meta-data
android:name="flutterEmbedding"
android:value="1" />
</application>
</manifest>
''', flush: true);
fs.file('.packages').writeAsStringSync('\n');
fs.file('lib/main.dart').createSync(recursive: true);
final AndroidDevice device = AndroidDevice('1234',
modelID: 'TestModel',
logger: testLogger,
platform: FakePlatform(),
androidSdk: FakeAndroidSdk(),
fileSystem: fs,
processManager: FakeProcessManager.any(),
);
testDeviceManager.devices = <Device>[device];
final RunCommand command = RunCommand();
await expectLater(createTestCommandRunner(command).run(<String>[
'run',
'--pub',
]), throwsToolExit(message: 'Build failed due to use of deprecated Android v1 embedding.'));
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
DeviceManager: () => testDeviceManager,
Stdio: () => FakeStdio(),
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
});
testUsingContext('shows unsupported devices when no supported devices are found', () async {
final RunCommand command = RunCommand();
final FakeDevice mockDevice = FakeDevice(
......@@ -1288,11 +1207,6 @@ class TestDeviceManager extends DeviceManager {
}
}
class FakeAndroidSdk extends Fake implements AndroidSdk {
@override
String get adbPath => 'adb';
}
class FakeDevice extends Fake implements Device {
FakeDevice({
bool isLocalEmulator = false,
......
......@@ -457,42 +457,6 @@ flutter:
),
});
testUsingContext('indicate that Android project reports v1 in usage value', () async {
final String projectPath = await createProject(tempDir,
arguments: <String>['--no-pub']);
removeGeneratedFiles(projectPath);
final File androidManifest = globals.fs.file(globals.fs.path.join(
projectPath,
'android/app/src/main/AndroidManifest.xml',
));
final String updatedAndroidManifestString =
androidManifest.readAsStringSync().replaceAll('android:value="2"', 'android:value="1"');
androidManifest.writeAsStringSync(updatedAndroidManifestString);
final PackagesCommand command = await runCommandIn(projectPath, 'get');
final PackagesGetCommand getCommand = command.subcommands['get']! as PackagesGetCommand;
expect((await getCommand.usageValues).commandPackagesAndroidEmbeddingVersion, 'v1');
expect(
(await getCommand.unifiedAnalyticsUsageValues('pub/get'))
.eventData['packagesAndroidEmbeddingVersion'],
'v1',
);
}, overrides: <Type, Generator>{
Stdio: () => mockStdio,
Pub: () => Pub.test(
fileSystem: globals.fs,
logger: globals.logger,
processManager: globals.processManager,
usage: globals.flutterUsage,
botDetector: globals.botDetector,
platform: globals.platform,
stdio: mockStdio,
),
});
testUsingContext('indicate that Android project reports v2 in usage value', () async {
final String projectPath = await createProject(tempDir,
arguments: <String>['--no-pub']);
......
......@@ -194,28 +194,6 @@ void main() {
throwsToolExit(message: 'Please ensure that the android manifest is a valid XML document and try again.'),
);
});
_testInMemory('Android project not on v2 embedding shows a warning', () async {
final FlutterProject project = await someProject(includePubspec: true);
// The default someProject with an empty <manifest> already indicates
// v1 embedding, as opposed to having <meta-data
// android:name="flutterEmbedding" android:value="2" />.
project.checkForDeprecation(deprecationBehavior: DeprecationBehavior.ignore);
expect(testLogger.statusText, contains('https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects'));
});
_testInMemory('Android project not on v2 embedding exits', () async {
final FlutterProject project = await someProject(includePubspec: true);
// The default someProject with an empty <manifest> already indicates
// v1 embedding, as opposed to having <meta-data
// android:name="flutterEmbedding" android:value="2" />.
await expectToolExitLater(
Future<dynamic>.sync(() => project.checkForDeprecation(deprecationBehavior: DeprecationBehavior.exit)),
contains('Build failed due to use of deprecated Android v1 embedding.')
);
expect(testLogger.statusText, contains('https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects'));
expect(testLogger.statusText, contains('No `<meta-data android:name="flutterEmbedding" android:value="2"/>` in '));
});
_testInMemory('Project not on v2 embedding does not warn if deprecation status is irrelevant', () async {
final FlutterProject project = await someProject(includePubspec: true);
// The default someProject with an empty <manifest> already indicates
......@@ -226,15 +204,6 @@ void main() {
project.checkForDeprecation();
expect(testLogger.statusText, isEmpty);
});
_testInMemory('Android project not on v2 embedding ignore continues', () async {
final FlutterProject project = await someProject(includePubspec: true);
// The default someProject with an empty <manifest> already indicates
// v1 embedding, as opposed to having <meta-data
// android:name="flutterEmbedding" android:value="2" />.
project.checkForDeprecation(deprecationBehavior: DeprecationBehavior.ignore);
expect(testLogger.statusText, contains('https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects'));
});
_testInMemory('Android project no pubspec continues', () async {
final FlutterProject project = await someProject();
// The default someProject with an empty <manifest> already indicates
......
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