From dcc2c91471923b31b6b3fbfc848e87c9077839a0 Mon Sep 17 00:00:00 2001 From: John McCutchan Date: Tue, 2 Jan 2024 17:17:08 -0800 Subject: [PATCH] Verified input test take 2 (#140836) This is a reland of https://github.com/flutter/flutter/pull/140806 which had an issue with package versions. --- .../tasks/android_verified_input_test.dart | 10 +++ .../tasks/android_verified_input_test.dart | 60 ++++++++++++++ .../android_verified_input/.gitignore | 43 ++++++++++ .../android_verified_input/.metadata | 45 ++++++++++ .../android_verified_input/README.md | 4 + .../android_verified_input/android/.gitignore | 13 +++ .../android/app/build.gradle | 71 ++++++++++++++++ .../android/app/src/debug/AndroidManifest.xml | 12 +++ .../android/app/src/main/AndroidManifest.xml | 49 +++++++++++ .../android_verified_input/MainActivity.java | 28 +++++++ .../VerifiedInputView.java | 68 +++++++++++++++ .../VerifiedInputViewFactory.java | 27 ++++++ .../res/drawable-v21/launch_background.xml | 16 ++++ .../main/res/drawable/launch_background.xml | 16 ++++ .../app/src/main/res/values-night/styles.xml | 22 +++++ .../app/src/main/res/values/colors.xml | 11 +++ .../app/src/main/res/values/styles.xml | 22 +++++ .../app/src/profile/AndroidManifest.xml | 12 +++ .../android/build.gradle | 22 +++++ .../android/gradle.properties | 3 + .../gradle/wrapper/gradle-wrapper.properties | 5 ++ .../android/settings.gradle | 30 +++++++ .../android_verified_input/lib/main.dart | 68 +++++++++++++++ .../android_verified_input/pubspec.yaml | 82 +++++++++++++++++++ .../test_driver/main_test.dart | 45 ++++++++++ 25 files changed, 784 insertions(+) create mode 100644 dev/devicelab/bin/tasks/android_verified_input_test.dart create mode 100644 dev/devicelab/lib/tasks/android_verified_input_test.dart create mode 100644 dev/integration_tests/android_verified_input/.gitignore create mode 100644 dev/integration_tests/android_verified_input/.metadata create mode 100644 dev/integration_tests/android_verified_input/README.md create mode 100644 dev/integration_tests/android_verified_input/android/.gitignore create mode 100644 dev/integration_tests/android_verified_input/android/app/build.gradle create mode 100644 dev/integration_tests/android_verified_input/android/app/src/debug/AndroidManifest.xml create mode 100644 dev/integration_tests/android_verified_input/android/app/src/main/AndroidManifest.xml create mode 100644 dev/integration_tests/android_verified_input/android/app/src/main/java/io/flutter/integration/android_verified_input/MainActivity.java create mode 100644 dev/integration_tests/android_verified_input/android/app/src/main/java/io/flutter/integration/android_verified_input/VerifiedInputView.java create mode 100644 dev/integration_tests/android_verified_input/android/app/src/main/java/io/flutter/integration/android_verified_input/VerifiedInputViewFactory.java create mode 100644 dev/integration_tests/android_verified_input/android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 dev/integration_tests/android_verified_input/android/app/src/main/res/drawable/launch_background.xml create mode 100644 dev/integration_tests/android_verified_input/android/app/src/main/res/values-night/styles.xml create mode 100644 dev/integration_tests/android_verified_input/android/app/src/main/res/values/colors.xml create mode 100644 dev/integration_tests/android_verified_input/android/app/src/main/res/values/styles.xml create mode 100644 dev/integration_tests/android_verified_input/android/app/src/profile/AndroidManifest.xml create mode 100644 dev/integration_tests/android_verified_input/android/build.gradle create mode 100644 dev/integration_tests/android_verified_input/android/gradle.properties create mode 100644 dev/integration_tests/android_verified_input/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 dev/integration_tests/android_verified_input/android/settings.gradle create mode 100644 dev/integration_tests/android_verified_input/lib/main.dart create mode 100644 dev/integration_tests/android_verified_input/pubspec.yaml create mode 100644 dev/integration_tests/android_verified_input/test_driver/main_test.dart diff --git a/dev/devicelab/bin/tasks/android_verified_input_test.dart b/dev/devicelab/bin/tasks/android_verified_input_test.dart new file mode 100644 index 0000000000..c6835df840 --- /dev/null +++ b/dev/devicelab/bin/tasks/android_verified_input_test.dart @@ -0,0 +1,10 @@ +// 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 'package:flutter_devicelab/framework/framework.dart'; +import 'package:flutter_devicelab/tasks/android_verified_input_test.dart'; + +Future main() async { + await task(androidVerifiedInputTest()); +} diff --git a/dev/devicelab/lib/tasks/android_verified_input_test.dart b/dev/devicelab/lib/tasks/android_verified_input_test.dart new file mode 100644 index 0000000000..ec084110a5 --- /dev/null +++ b/dev/devicelab/lib/tasks/android_verified_input_test.dart @@ -0,0 +1,60 @@ +// 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 '../framework/devices.dart'; +import '../framework/framework.dart'; +import '../framework/task_result.dart'; +import '../framework/utils.dart'; + +TaskFunction androidVerifiedInputTest({Map? environment}) { + return DriverTest( + '${flutterDirectory.path}/dev/integration_tests/android_verified_input', + 'test_driver/main_test.dart', + environment: environment, + ).call; +} + +class DriverTest { + DriverTest( + this.testDirectory, + this.testTarget, { + this.extraOptions = const [], + this.deviceIdOverride, + this.environment, + } + ); + + final String testDirectory; + final String testTarget; + final List extraOptions; + final String? deviceIdOverride; + final Map? environment; + + Future call() { + return inDirectory(testDirectory, () async { + String deviceId; + if (deviceIdOverride != null) { + deviceId = deviceIdOverride!; + } else { + final Device device = await devices.workingDevice; + await device.unlock(); + deviceId = device.deviceId; + } + await flutter('packages', options: ['get']); + + final List options = [ + '--no-android-gradle-daemon', + '-v', + '-t', + testTarget, + '-d', + deviceId, + ...extraOptions, + ]; + await flutter('drive', options: options, environment: environment); + + return TaskResult.success(null); + }); + } +} diff --git a/dev/integration_tests/android_verified_input/.gitignore b/dev/integration_tests/android_verified_input/.gitignore new file mode 100644 index 0000000000..29a3a5017f --- /dev/null +++ b/dev/integration_tests/android_verified_input/.gitignore @@ -0,0 +1,43 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/dev/integration_tests/android_verified_input/.metadata b/dev/integration_tests/android_verified_input/.metadata new file mode 100644 index 0000000000..3c9762180e --- /dev/null +++ b/dev/integration_tests/android_verified_input/.metadata @@ -0,0 +1,45 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "7b7aa6a9a38b1c68cef406a457bcfdc202ab5168" + channel: "main" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 7b7aa6a9a38b1c68cef406a457bcfdc202ab5168 + base_revision: 7b7aa6a9a38b1c68cef406a457bcfdc202ab5168 + - platform: android + create_revision: 7b7aa6a9a38b1c68cef406a457bcfdc202ab5168 + base_revision: 7b7aa6a9a38b1c68cef406a457bcfdc202ab5168 + - platform: ios + create_revision: 7b7aa6a9a38b1c68cef406a457bcfdc202ab5168 + base_revision: 7b7aa6a9a38b1c68cef406a457bcfdc202ab5168 + - platform: linux + create_revision: 7b7aa6a9a38b1c68cef406a457bcfdc202ab5168 + base_revision: 7b7aa6a9a38b1c68cef406a457bcfdc202ab5168 + - platform: macos + create_revision: 7b7aa6a9a38b1c68cef406a457bcfdc202ab5168 + base_revision: 7b7aa6a9a38b1c68cef406a457bcfdc202ab5168 + - platform: web + create_revision: 7b7aa6a9a38b1c68cef406a457bcfdc202ab5168 + base_revision: 7b7aa6a9a38b1c68cef406a457bcfdc202ab5168 + - platform: windows + create_revision: 7b7aa6a9a38b1c68cef406a457bcfdc202ab5168 + base_revision: 7b7aa6a9a38b1c68cef406a457bcfdc202ab5168 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/dev/integration_tests/android_verified_input/README.md b/dev/integration_tests/android_verified_input/README.md new file mode 100644 index 0000000000..aeccfc6fbe --- /dev/null +++ b/dev/integration_tests/android_verified_input/README.md @@ -0,0 +1,4 @@ +# android\_verified\_input + +Integration test that confirms that MotionEvents delivered to platform views +are verifid. diff --git a/dev/integration_tests/android_verified_input/android/.gitignore b/dev/integration_tests/android_verified_input/android/.gitignore new file mode 100644 index 0000000000..6f568019d3 --- /dev/null +++ b/dev/integration_tests/android_verified_input/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/dev/integration_tests/android_verified_input/android/app/build.gradle b/dev/integration_tests/android_verified_input/android/app/build.gradle new file mode 100644 index 0000000000..995fb86b32 --- /dev/null +++ b/dev/integration_tests/android_verified_input/android/app/build.gradle @@ -0,0 +1,71 @@ +// 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. + +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +android { + namespace "io.flutter.integration.android_verified_input" + compileSdk flutter.compileSdkVersion + ndkVersion flutter.ndkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "io.flutter.integration.android_verified_input" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. + minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies {} diff --git a/dev/integration_tests/android_verified_input/android/app/src/debug/AndroidManifest.xml b/dev/integration_tests/android_verified_input/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000000..f0f1bf580e --- /dev/null +++ b/dev/integration_tests/android_verified_input/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/dev/integration_tests/android_verified_input/android/app/src/main/AndroidManifest.xml b/dev/integration_tests/android_verified_input/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..d80b8b5333 --- /dev/null +++ b/dev/integration_tests/android_verified_input/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/integration_tests/android_verified_input/android/app/src/main/java/io/flutter/integration/android_verified_input/MainActivity.java b/dev/integration_tests/android_verified_input/android/app/src/main/java/io/flutter/integration/android_verified_input/MainActivity.java new file mode 100644 index 0000000000..99730ad01b --- /dev/null +++ b/dev/integration_tests/android_verified_input/android/app/src/main/java/io/flutter/integration/android_verified_input/MainActivity.java @@ -0,0 +1,28 @@ +// 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. + +package io.flutter.integration.android_verified_input; + +import androidx.annotation.NonNull; +import io.flutter.embedding.android.FlutterActivity; +import io.flutter.embedding.engine.FlutterEngine; +import io.flutter.plugin.common.MethodChannel; +import io.flutter.embedding.engine.dart.DartExecutor; + +public class MainActivity extends FlutterActivity { + public static MethodChannel mMethodChannel; + + @Override + public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { + DartExecutor executor = flutterEngine.getDartExecutor(); + + // Configuring AdView to call adservices APIs + flutterEngine + .getPlatformViewsController() + .getRegistry() + .registerViewFactory("verified-input-view", new VerifiedInputViewFactory()); + + mMethodChannel = new MethodChannel(executor, "verified_input_test"); + } +} diff --git a/dev/integration_tests/android_verified_input/android/app/src/main/java/io/flutter/integration/android_verified_input/VerifiedInputView.java b/dev/integration_tests/android_verified_input/android/app/src/main/java/io/flutter/integration/android_verified_input/VerifiedInputView.java new file mode 100644 index 0000000000..1bb41cb641 --- /dev/null +++ b/dev/integration_tests/android_verified_input/android/app/src/main/java/io/flutter/integration/android_verified_input/VerifiedInputView.java @@ -0,0 +1,68 @@ +// 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. + +package io.flutter.integration.android_verified_input; + +import android.content.Context; +import android.hardware.input.InputManager; +import android.os.Build; +import android.view.MotionEvent; +import android.view.VerifiedInputEvent; +import android.view.View; +import android.widget.Button; + +import androidx.annotation.NonNull; + +import java.util.Map; + +import io.flutter.Log; +import io.flutter.plugin.platform.PlatformView; + +class VerifiedInputView implements PlatformView { + private static final String TAG = "VerifiedInputView"; + @NonNull + private final Button mButton; + + VerifiedInputView(@NonNull Context context, @NonNull Map creationParams) { + mButton = new Button(context); + + mButton.setText("click me"); + + mButton.setOnTouchListener( + (view, event) -> { + if (MotionEvent.ACTION_DOWN == event.getAction()) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + InputManager inputManager = context.getSystemService(InputManager.class); + VerifiedInputEvent verify = inputManager.verifyInputEvent(event); + // If verifyInputEvent returns an object, the input event was verified + final boolean verified = (verify != null); + Log.i(TAG, "VerifiedInputEvent is verified : " + verified); + // Notify the test harness whether or not the input event was verified. + MainActivity.mMethodChannel.invokeMethod("notify_verified_input", verified); + if (verified) { + mButton.setBackgroundColor(context.getColor(R.color.green)); + mButton.setText("click me (verified)"); + } else { + mButton.setBackgroundColor(context.getColor(R.color.red)); + mButton.setText("click me (verification failed)"); + } + + } + return true; + } + return false; + }); + } + + @NonNull + @Override + public View getView() { + return mButton; + } + + @Override + public void dispose() { + } + +} diff --git a/dev/integration_tests/android_verified_input/android/app/src/main/java/io/flutter/integration/android_verified_input/VerifiedInputViewFactory.java b/dev/integration_tests/android_verified_input/android/app/src/main/java/io/flutter/integration/android_verified_input/VerifiedInputViewFactory.java new file mode 100644 index 0000000000..798efbc336 --- /dev/null +++ b/dev/integration_tests/android_verified_input/android/app/src/main/java/io/flutter/integration/android_verified_input/VerifiedInputViewFactory.java @@ -0,0 +1,27 @@ +// 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. + +package io.flutter.integration.android_verified_input; + +import android.content.Context; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import io.flutter.plugin.common.StandardMessageCodec; +import io.flutter.plugin.platform.PlatformView; +import io.flutter.plugin.platform.PlatformViewFactory; +import java.util.Map; + +public class VerifiedInputViewFactory extends PlatformViewFactory { + + VerifiedInputViewFactory() { + super(StandardMessageCodec.INSTANCE); + } + + @NonNull + @Override + public PlatformView create(@NonNull Context context, int id, @Nullable Object args) { + final Map creationParams = (Map) args; + return new VerifiedInputView(context, creationParams); + } +} diff --git a/dev/integration_tests/android_verified_input/android/app/src/main/res/drawable-v21/launch_background.xml b/dev/integration_tests/android_verified_input/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000000..9f19e2f904 --- /dev/null +++ b/dev/integration_tests/android_verified_input/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/dev/integration_tests/android_verified_input/android/app/src/main/res/drawable/launch_background.xml b/dev/integration_tests/android_verified_input/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000000..3727f9e00a --- /dev/null +++ b/dev/integration_tests/android_verified_input/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/dev/integration_tests/android_verified_input/android/app/src/main/res/values-night/styles.xml b/dev/integration_tests/android_verified_input/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000000..f3ab3e83cd --- /dev/null +++ b/dev/integration_tests/android_verified_input/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,22 @@ + + + + + + + + + diff --git a/dev/integration_tests/android_verified_input/android/app/src/main/res/values/colors.xml b/dev/integration_tests/android_verified_input/android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000000..ae905237d7 --- /dev/null +++ b/dev/integration_tests/android_verified_input/android/app/src/main/res/values/colors.xml @@ -0,0 +1,11 @@ + + + + + + #FFFFFF + #FF0000 + #008000 + diff --git a/dev/integration_tests/android_verified_input/android/app/src/main/res/values/styles.xml b/dev/integration_tests/android_verified_input/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000000..9a0ead3c04 --- /dev/null +++ b/dev/integration_tests/android_verified_input/android/app/src/main/res/values/styles.xml @@ -0,0 +1,22 @@ + + + + + + + + + diff --git a/dev/integration_tests/android_verified_input/android/app/src/profile/AndroidManifest.xml b/dev/integration_tests/android_verified_input/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000000..f0f1bf580e --- /dev/null +++ b/dev/integration_tests/android_verified_input/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/dev/integration_tests/android_verified_input/android/build.gradle b/dev/integration_tests/android_verified_input/android/build.gradle new file mode 100644 index 0000000000..6cd585ceee --- /dev/null +++ b/dev/integration_tests/android_verified_input/android/build.gradle @@ -0,0 +1,22 @@ +// 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. + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/dev/integration_tests/android_verified_input/android/gradle.properties b/dev/integration_tests/android_verified_input/android/gradle.properties new file mode 100644 index 0000000000..598d13fee4 --- /dev/null +++ b/dev/integration_tests/android_verified_input/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx4G +android.useAndroidX=true +android.enableJetifier=true diff --git a/dev/integration_tests/android_verified_input/android/gradle/wrapper/gradle-wrapper.properties b/dev/integration_tests/android_verified_input/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..e1ca574ef0 --- /dev/null +++ b/dev/integration_tests/android_verified_input/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip diff --git a/dev/integration_tests/android_verified_input/android/settings.gradle b/dev/integration_tests/android_verified_input/android/settings.gradle new file mode 100644 index 0000000000..97b9e7934e --- /dev/null +++ b/dev/integration_tests/android_verified_input/android/settings.gradle @@ -0,0 +1,30 @@ +// 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. + +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + } + settings.ext.flutterSdkPath = flutterSdkPath() + + includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "7.3.0" apply false + id "org.jetbrains.kotlin.android" version "1.7.10" apply false +} + +include ":app" diff --git a/dev/integration_tests/android_verified_input/lib/main.dart b/dev/integration_tests/android_verified_input/lib/main.dart new file mode 100644 index 0000000000..923d504790 --- /dev/null +++ b/dev/integration_tests/android_verified_input/lib/main.dart @@ -0,0 +1,68 @@ +// 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 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_driver/driver_extension.dart'; + + +class FutureDataHandler { + final Completer handlerCompleter = Completer(); + + Future handleMessage(String? message) async { + final DataHandler handler = await handlerCompleter.future; + return handler(message); + } +} +FutureDataHandler driverDataHandler = FutureDataHandler(); + +MethodChannel channel = const MethodChannel('verified_input_test'); + +Future onMethodChannelCall(MethodCall call) { + switch (call.method) { + // Android side is notifying us of the result of verifying the input + // event. + case 'notify_verified_input': + final bool result = call.arguments as bool; + // FlutterDriver handler, note that this captures the notification + // value delivered via the method channel. + Future handler(String? message) async { + switch (message) { + case 'input_was_verified': + return '$result'; + } + return 'unknown message: "$message"'; + } + // Install the handler now. + driverDataHandler.handlerCompleter.complete(handler); + } + return Future.value(); + } + +void main() { + enableFlutterDriverExtension(handler: driverDataHandler.handleMessage); + channel.setMethodCallHandler(onMethodChannelCall); + runApp(MaterialApp(home: _Home())); +} + +class _Home extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Verified Input Integration Test'), + centerTitle: true, + backgroundColor: Colors.black45, + ), + body: Container( + padding: const EdgeInsets.all(30.0), + color: Colors.black26, + child: const AndroidView( + key: Key('PlatformView'), + viewType: 'verified-input-view', + ) + )); + } +} diff --git a/dev/integration_tests/android_verified_input/pubspec.yaml b/dev/integration_tests/android_verified_input/pubspec.yaml new file mode 100644 index 0000000000..8f94edff13 --- /dev/null +++ b/dev/integration_tests/android_verified_input/pubspec.yaml @@ -0,0 +1,82 @@ +name: android_verified_input +description: "An integration test for verified MotionEvents." +publish_to: 'none' # Remove this line if you wish to publish to pub.dev +version: 1.0.0+1 +environment: + sdk: '>=3.2.0-0 <4.0.0' + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + flutter_driver: + sdk: flutter + + async: 2.11.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + boolean_selector: 2.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + characters: 1.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + collection: 1.18.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + file: 7.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + matcher: 0.12.16+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + material_color_utilities: 0.8.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + meta: 1.11.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + path: 1.9.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + source_span: 1.10.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + stack_trace: 1.11.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + stream_channel: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + string_scanner: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + sync_http: 0.3.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + term_glyph: 1.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + test_api: 0.6.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vector_math: 2.1.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + vm_service: 13.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webdriver: 3.0.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + +dev_dependencies: + flutter_test: + sdk: flutter + test: 1.24.9 + + _fe_analyzer_shared: 65.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + analyzer: 6.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + args: 2.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + clock: 1.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + convert: 3.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + coverage: 1.7.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + crypto: 3.0.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + fake_async: 1.3.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + frontend_server_client: 3.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + glob: 2.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + http_multi_server: 3.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + http_parser: 4.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + io: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + js: 0.6.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + leak_tracker: 10.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + leak_tracker_flutter_testing: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + leak_tracker_testing: 2.0.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + logging: 1.2.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + mime: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + node_preamble: 2.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + package_config: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + pool: 1.5.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + pub_semver: 2.1.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + shelf: 1.4.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + shelf_packages_handler: 3.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + shelf_static: 1.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + shelf_web_socket: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + source_map_stack_trace: 2.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + source_maps: 0.10.12 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + test_core: 0.5.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + typed_data: 1.3.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + watcher: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + web: 0.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + web_socket_channel: 2.4.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + webkit_inspection_protocol: 1.2.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + yaml: 3.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade" + +# PUBSPEC CHECKSUM: 6020 diff --git a/dev/integration_tests/android_verified_input/test_driver/main_test.dart b/dev/integration_tests/android_verified_input/test_driver/main_test.dart new file mode 100644 index 0000000000..ecf3061dfb --- /dev/null +++ b/dev/integration_tests/android_verified_input/test_driver/main_test.dart @@ -0,0 +1,45 @@ +// 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 'dart:io'; +import 'package:flutter_driver/flutter_driver.dart'; +import 'package:test/test.dart'; + + +Future main() async { + late FlutterDriver driver; + + setUpAll(() async { + driver = await FlutterDriver.connect(); + }); + + tearDownAll(() { + driver.close(); + }); + + test('verified input', () async { + // Wait for the PlatformView to show up. + await driver.waitFor(find.byValueKey('PlatformView')); + final DriverOffset offset = await driver.getCenter(find.byValueKey('PlatformView')); + + // This future will complete when the input event is verified or fails + // to be verified. + final Future inputEventWasVerified = driver.requestData('input_was_verified'); + + // Keep issueing taps until we get the requested data. The actual setup + // of the platform view is asynchronous so we might have to tap more than + // once to get a response. + bool stop = false; + inputEventWasVerified.whenComplete(() => stop = true); + while (!stop) { + // We must use the Android input tool to get verified input events. + final ProcessResult result = + await Process.run('adb', ['shell', 'input', 'tap', '${offset.dx}', '${offset.dy}']); + expect(result.exitCode, equals(0)); + } + // Input + expect(await inputEventWasVerified, equals('true')); + }, timeout: Timeout.none); +}