未验证 提交 0c121d3d 编写于 作者: D Dan Field 提交者: GitHub

Revert "Use a Pbuffer surface when the onscreen surface is not available for...

Revert "Use a Pbuffer surface when the onscreen surface is not available for snapshotting on Android (#27141)" (#27607)

This reverts commit a1180b18.
上级 b678f434
......@@ -121,11 +121,6 @@ group("flutter") {
public_deps += [ "//flutter/testing/scenario_app" ]
}
if (is_android && flutter_runtime_mode == "profile" &&
current_cpu == "arm64") {
public_deps += [ "//flutter/testing/android_background_image" ]
}
# Compile all unittests targets if enabled.
if (enable_unittests) {
public_deps += [
......
......@@ -19,13 +19,13 @@ error_re = re.compile(r'[EF]/flutter.+')
def RunFirebaseTest(apk, results_dir):
try:
# game-loop tests are meant for OpenGL apps.
# This type of test will give the application a handle to a file, and
# we'll write the timeline JSON to that file.
# See https://firebase.google.com/docs/test-lab/android/game-loop
# Pixel 4. As of this commit, this is a highly available device in FTL.
process = subprocess.Popen(
[
subprocess.check_output([
'gcloud',
'--project', 'flutter-infra',
'firebase', 'test', 'android', 'run',
......@@ -35,12 +35,12 @@ def RunFirebaseTest(apk, results_dir):
'--results-bucket', bucket,
'--results-dir', results_dir,
'--device', 'model=flame,version=29',
],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
universal_newlines=True,
)
return process
])
except subprocess.CalledProcessError as ex:
print(ex.output)
# Recipe will retry return codes from firebase that indicate an infra
# failure.
sys.exit(ex.returncode)
def CheckLogcat(results_dir):
......@@ -87,25 +87,13 @@ def main():
git_revision = subprocess.check_output(
['git', 'rev-parse', 'HEAD'], cwd=script_dir).strip()
results = []
for apk in apks:
results_dir = '%s/%s/%s' % (os.path.basename(apk), git_revision, args.build_id)
process = RunFirebaseTest(apk, results_dir)
results.append((results_dir, process))
for results_dir, process in results:
for line in iter(process.stdout.readline, ""):
print(line.strip())
return_code = process.wait()
if return_code != 0:
print('Firebase test failed ' + returncode)
sys.exit(process.returncode)
print('Checking logcat for %s' % results_dir)
RunFirebaseTest(apk, results_dir)
CheckLogcat(results_dir)
# scenario_app produces a timeline, but the android image test does not.
if 'scenario' in apk:
print('Checking timeline for %s' % results_dir)
CheckTimeline(results_dir)
return 0
......
......@@ -725,7 +725,6 @@ FILE: ../../../flutter/shell/common/shell_unittests.cc
FILE: ../../../flutter/shell/common/skia_event_tracer_impl.cc
FILE: ../../../flutter/shell/common/skia_event_tracer_impl.h
FILE: ../../../flutter/shell/common/skp_shader_warmup_unittests.cc
FILE: ../../../flutter/shell/common/snapshot_surface_producer.h
FILE: ../../../flutter/shell/common/switches.cc
FILE: ../../../flutter/shell/common/switches.h
FILE: ../../../flutter/shell/common/thread_host.cc
......@@ -933,8 +932,6 @@ FILE: ../../../flutter/shell/platform/android/surface/android_surface.cc
FILE: ../../../flutter/shell/platform/android/surface/android_surface.h
FILE: ../../../flutter/shell/platform/android/surface/android_surface_mock.cc
FILE: ../../../flutter/shell/platform/android/surface/android_surface_mock.h
FILE: ../../../flutter/shell/platform/android/surface/snapshot_surface_producer.cc
FILE: ../../../flutter/shell/platform/android/surface/snapshot_surface_producer.h
FILE: ../../../flutter/shell/platform/android/vsync_waiter_android.cc
FILE: ../../../flutter/shell/platform/android/vsync_waiter_android.h
FILE: ../../../flutter/shell/platform/common/accessibility_bridge.cc
......
......@@ -89,7 +89,6 @@ source_set("common") {
"shell_io_manager.h",
"skia_event_tracer_impl.cc",
"skia_event_tracer_impl.h",
"snapshot_surface_producer.h",
"switches.cc",
"switches.h",
"thread_host.cc",
......
......@@ -67,6 +67,7 @@ void PlatformView::SetViewportMetrics(const ViewportMetrics& metrics) {
void PlatformView::NotifyCreated() {
std::unique_ptr<Surface> surface;
// Threading: We want to use the platform view on the non-platform thread.
// Using the weak pointer is illegal. But, we are going to introduce a latch
// so that the platform view is not collected till the surface is obtained.
......@@ -181,9 +182,4 @@ void PlatformView::UpdateAssetResolverByType(
delegate_.UpdateAssetResolverByType(std::move(updated_asset_resolver), type);
}
std::unique_ptr<SnapshotSurfaceProducer>
PlatformView::CreateSnapshotSurfaceProducer() {
return nullptr;
}
} // namespace flutter
......@@ -796,22 +796,6 @@ class PlatformView {
std::unique_ptr<AssetResolver> updated_asset_resolver,
AssetResolver::AssetResolverType type);
//--------------------------------------------------------------------------
/// @brief Creates an object that produces surfaces suitable for raster
/// snapshotting. The rasterizer will request this surface if no
/// on screen surface is currently available when an application
/// requests a snapshot, e.g. if `Scene.toImage` or
/// `Picture.toImage` are called while the application is in the
/// background.
///
/// Not all backends support this kind of surface usage, and the
/// default implementation returns nullptr. Platforms should
/// override this if they can support GPU operations in the
/// background and support GPU resource context usage.
///
virtual std::unique_ptr<SnapshotSurfaceProducer>
CreateSnapshotSurfaceProducer();
protected:
PlatformView::Delegate& delegate_;
const TaskRunners task_runners_;
......@@ -820,7 +804,8 @@ class PlatformView {
SkISize size_;
fml::WeakPtrFactory<PlatformView> weak_factory_;
// This is the only method called on the raster task runner.
// Unlike all other methods on the platform view, this is called on the
// raster task runner.
virtual std::unique_ptr<Surface> CreateRenderingSurface();
private:
......
......@@ -258,22 +258,11 @@ sk_sp<SkImage> Rasterizer::DoMakeRasterSnapshot(
sk_sp<SkImage> result;
SkImageInfo image_info = SkImageInfo::MakeN32Premul(
size.width(), size.height(), SkColorSpace::MakeSRGB());
std::unique_ptr<Surface> pbuffer_surface;
Surface* snapshot_surface = nullptr;
if (surface_ && surface_->GetContext()) {
snapshot_surface = surface_.get();
} else if (snapshot_surface_producer_) {
pbuffer_surface = snapshot_surface_producer_->CreateSnapshotSurface();
if (pbuffer_surface && pbuffer_surface->GetContext())
snapshot_surface = pbuffer_surface.get();
}
if (!snapshot_surface) {
if (surface_ == nullptr || surface_->GetContext() == nullptr) {
// Raster surface is fine if there is no on screen surface. This might
// happen in case of software rendering.
sk_sp<SkSurface> sk_surface = SkSurface::MakeRaster(image_info);
result = DrawSnapshot(sk_surface, draw_callback);
sk_sp<SkSurface> surface = SkSurface::MakeRaster(image_info);
result = DrawSnapshot(surface, draw_callback);
} else {
delegate_.GetIsGpuDisabledSyncSwitch()->Execute(
fml::SyncSwitch::Handlers()
......@@ -282,14 +271,12 @@ sk_sp<SkImage> Rasterizer::DoMakeRasterSnapshot(
result = DrawSnapshot(surface, draw_callback);
})
.SetIfFalse([&] {
FML_DCHECK(snapshot_surface);
auto context_switch =
snapshot_surface->MakeRenderContextCurrent();
auto context_switch = surface_->MakeRenderContextCurrent();
if (!context_switch->GetResult()) {
return;
}
GrRecordingContext* context = snapshot_surface->GetContext();
GrRecordingContext* context = surface_->GetContext();
auto max_size = context->maxRenderTargetSize();
double scale_factor = std::min(
1.0, static_cast<double>(max_size) /
......@@ -307,19 +294,19 @@ sk_sp<SkImage> Rasterizer::DoMakeRasterSnapshot(
// When there is an on screen surface, we need a render target
// SkSurface because we want to access texture backed images.
sk_sp<SkSurface> sk_surface =
sk_sp<SkSurface> surface =
SkSurface::MakeRenderTarget(context, // context
SkBudgeted::kNo, // budgeted
image_info // image info
);
if (!sk_surface) {
if (!surface) {
FML_LOG(ERROR)
<< "DoMakeRasterSnapshot can not create GPU render target";
return;
}
sk_surface->getCanvas()->scale(scale_factor, scale_factor);
result = DrawSnapshot(sk_surface, draw_callback);
surface->getCanvas()->scale(scale_factor, scale_factor);
result = DrawSnapshot(surface, draw_callback);
}));
}
......@@ -713,11 +700,6 @@ void Rasterizer::SetExternalViewEmbedder(
external_view_embedder_ = view_embedder;
}
void Rasterizer::SetSnapshotSurfaceProducer(
std::unique_ptr<SnapshotSurfaceProducer> producer) {
snapshot_surface_producer_ = std::move(producer);
}
void Rasterizer::FireNextFrameCallbackIfPresent() {
if (!next_frame_callback_) {
return;
......
......@@ -24,7 +24,6 @@
#include "flutter/fml/time/time_point.h"
#include "flutter/lib/ui/snapshot_delegate.h"
#include "flutter/shell/common/pipeline.h"
#include "flutter/shell/common/snapshot_surface_producer.h"
namespace flutter {
......@@ -350,17 +349,6 @@ class Rasterizer final : public SnapshotDelegate {
void SetExternalViewEmbedder(
const std::shared_ptr<ExternalViewEmbedder>& view_embedder);
//----------------------------------------------------------------------------
/// @brief Set the snapshot surface producer. This is done on shell
/// initialization. This is non-null on platforms that support taking
/// GPU accelerated raster snapshots in the background.
///
/// @param[in] producer A surface producer for raster snapshotting when the
/// onscreen surface is not available.
///
void SetSnapshotSurfaceProducer(
std::unique_ptr<SnapshotSurfaceProducer> producer);
//----------------------------------------------------------------------------
/// @brief Returns a pointer to the compositor context used by this
/// rasterizer. This pointer will never be `nullptr`.
......@@ -446,7 +434,6 @@ class Rasterizer final : public SnapshotDelegate {
private:
Delegate& delegate_;
std::unique_ptr<Surface> surface_;
std::unique_ptr<SnapshotSurfaceProducer> snapshot_surface_producer_;
std::unique_ptr<flutter::CompositorContext> compositor_context_;
// This is the last successfully rasterized layer tree.
std::unique_ptr<flutter::LayerTree> last_layer_tree_;
......
......@@ -30,7 +30,6 @@ class MockDelegate : public Rasterizer::Delegate {
MOCK_CONST_METHOD0(GetTaskRunners, const TaskRunners&());
MOCK_CONST_METHOD0(GetIsGpuDisabledSyncSwitch,
std::shared_ptr<const fml::SyncSwitch>());
MOCK_METHOD0(CreateSnapshotSurface, std::unique_ptr<Surface>());
};
class MockSurface : public Surface {
......
......@@ -634,8 +634,6 @@ bool Shell::Setup(std::unique_ptr<PlatformView> platform_view,
// Set the external view embedder for the rasterizer.
auto view_embedder = platform_view_->CreateExternalViewEmbedder();
rasterizer_->SetExternalViewEmbedder(view_embedder);
rasterizer_->SetSnapshotSurfaceProducer(
platform_view_->CreateSnapshotSurfaceProducer());
// The weak ptr must be generated in the platform thread which owns the unique
// ptr.
......
// Copyright 2013 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.
#ifndef SHELL_COMMON_SNAPSHOT_SURFACE_PRODUCER_H_
#define SHELL_COMMON_SNAPSHOT_SURFACE_PRODUCER_H_
#include <memory>
#include "flutter/flow/surface.h"
namespace flutter {
class SnapshotSurfaceProducer {
public:
virtual ~SnapshotSurfaceProducer() = default;
virtual std::unique_ptr<Surface> CreateSnapshotSurface() = 0;
};
} // namespace flutter
#endif // SHELL_COMMON_SNAPSHOT_SURFACE_PRODUCER_H_
......@@ -227,16 +227,6 @@ std::unique_ptr<AndroidEGLSurface> AndroidContextGL::CreateOffscreenSurface()
resource_context_);
}
std::unique_ptr<AndroidEGLSurface> AndroidContextGL::CreatePbufferSurface()
const {
EGLDisplay display = environment_->Display();
const EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
EGLSurface surface = eglCreatePbufferSurface(display, config_, attribs);
return std::make_unique<AndroidEGLSurface>(surface, display, context_);
}
fml::RefPtr<AndroidEnvironmentGL> AndroidContextGL::Environment() const {
return environment_;
}
......
......@@ -93,14 +93,6 @@ class AndroidContextGL : public AndroidContext {
///
std::unique_ptr<AndroidEGLSurface> CreateOffscreenSurface() const;
//----------------------------------------------------------------------------
/// @brief Allocates an 1x1 pbuffer surface that is used for making the
/// onscreen context current for snapshotting.
///
/// @return The pbuffer surface.
///
std::unique_ptr<AndroidEGLSurface> CreatePbufferSurface() const;
//----------------------------------------------------------------------------
/// @return The Android environment that contains a reference to the
/// display.
......
......@@ -175,16 +175,4 @@ AndroidContextGL* AndroidSurfaceGL::GLContextPtr() const {
return reinterpret_cast<AndroidContextGL*>(android_context_.get());
}
std::unique_ptr<Surface> AndroidSurfaceGL::CreatePbufferSurface() {
onscreen_surface_ = GLContextPtr()->CreatePbufferSurface();
sk_sp<GrDirectContext> main_skia_context =
GLContextPtr()->GetMainSkiaContext();
if (!main_skia_context) {
main_skia_context = GPUSurfaceGL::MakeGLContext(this);
GLContextPtr()->SetMainSkiaContext(main_skia_context);
}
return std::make_unique<GPUSurfaceGL>(main_skia_context, this, true);
}
} // namespace flutter
......@@ -48,9 +48,6 @@ class AndroidSurfaceGL final : public GPUSurfaceGLDelegate,
// |AndroidSurface|
bool SetNativeWindow(fml::RefPtr<AndroidNativeWindow> window) override;
// |AndroidSurface|
virtual std::unique_ptr<Surface> CreatePbufferSurface() override;
// |GPUSurfaceGLDelegate|
std::unique_ptr<GLContextResult> GLContextMakeCurrent() override;
......
......@@ -16,7 +16,6 @@
#include "flutter/shell/platform/android/android_surface_software.h"
#include "flutter/shell/platform/android/external_view_embedder/external_view_embedder.h"
#include "flutter/shell/platform/android/surface/android_surface.h"
#include "flutter/shell/platform/android/surface/snapshot_surface_producer.h"
#if SHELL_ENABLE_VULKAN
#include "flutter/shell/platform/android/android_surface_vulkan.h"
......@@ -317,15 +316,6 @@ PlatformViewAndroid::CreateExternalViewEmbedder() {
*android_context_, jni_facade_, surface_factory_);
}
// |PlatformView|
std::unique_ptr<SnapshotSurfaceProducer>
PlatformViewAndroid::CreateSnapshotSurfaceProducer() {
if (!android_surface_) {
return nullptr;
}
return std::make_unique<AndroidSnapshotSurfaceProducer>(*android_surface_);
}
// |PlatformView|
sk_sp<GrDirectContext> PlatformViewAndroid::CreateResourceContext() const {
if (!android_surface_) {
......
......@@ -15,7 +15,6 @@
#include "flutter/fml/platform/android/scoped_java_ref.h"
#include "flutter/lib/ui/window/platform_message.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/common/snapshot_surface_producer.h"
#include "flutter/shell/platform/android/context/android_context.h"
#include "flutter/shell/platform/android/jni/platform_view_android_jni.h"
#include "flutter/shell/platform/android/platform_view_android_delegate/platform_view_android_delegate.h"
......@@ -126,7 +125,6 @@ class PlatformViewAndroid final : public PlatformView {
PlatformViewAndroidDelegate platform_view_android_delegate_;
std::unique_ptr<AndroidSurface> android_surface_;
// We use id 0 to mean that no response is expected.
int next_response_id_ = 1;
std::unordered_map<int, fml::RefPtr<flutter::PlatformMessageResponse>>
......@@ -153,10 +151,6 @@ class PlatformViewAndroid final : public PlatformView {
// |PlatformView|
std::shared_ptr<ExternalViewEmbedder> CreateExternalViewEmbedder() override;
// |PlatformView|
std::unique_ptr<SnapshotSurfaceProducer> CreateSnapshotSurfaceProducer()
override;
// |PlatformView|
sk_sp<GrDirectContext> CreateResourceContext() const override;
......
......@@ -6,8 +6,6 @@ source_set("surface") {
sources = [
"android_surface.cc",
"android_surface.h",
"snapshot_surface_producer.cc",
"snapshot_surface_producer.h",
]
public_configs = [ "//flutter:config" ]
......@@ -16,7 +14,6 @@ source_set("surface") {
":native_window",
"//flutter/flow",
"//flutter/fml",
"//flutter/shell/common",
"//flutter/shell/platform/android/context",
"//flutter/shell/platform/android/jni",
"//third_party/skia",
......
......@@ -15,8 +15,4 @@ AndroidSurface::AndroidSurface(
AndroidSurface::~AndroidSurface() = default;
std::unique_ptr<Surface> AndroidSurface::CreatePbufferSurface() {
return nullptr;
}
} // namespace flutter
......@@ -37,8 +37,6 @@ class AndroidSurface {
virtual bool SetNativeWindow(fml::RefPtr<AndroidNativeWindow> window) = 0;
virtual std::unique_ptr<Surface> CreatePbufferSurface();
protected:
explicit AndroidSurface(
const std::shared_ptr<AndroidContext>& android_context);
......
// Copyright 2013 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.
#include "flutter/shell/platform/android/surface/snapshot_surface_producer.h"
namespace flutter {
AndroidSnapshotSurfaceProducer::AndroidSnapshotSurfaceProducer(
AndroidSurface& android_surface)
: android_surface_(android_surface) {}
std::unique_ptr<Surface>
AndroidSnapshotSurfaceProducer::CreateSnapshotSurface() {
return android_surface_.CreatePbufferSurface();
}
} // namespace flutter
// Copyright 2013 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.
#ifndef SHELL_PLATFORM_ANDROID_SURFACE_SNAPSHOT_SURFACE_PRODUCER_H_
#define SHELL_PLATFORM_ANDROID_SURFACE_SNAPSHOT_SURFACE_PRODUCER_H_
#include "flutter/flow/surface.h"
#include "flutter/shell/common/snapshot_surface_producer.h"
#include "flutter/shell/platform/android/surface/android_surface.h"
namespace flutter {
class AndroidSnapshotSurfaceProducer : public SnapshotSurfaceProducer {
public:
explicit AndroidSnapshotSurfaceProducer(AndroidSurface& android_surface);
// |SnapshotSurfaceProducer|
std::unique_ptr<Surface> CreateSnapshotSurface() override;
private:
AndroidSurface& android_surface_;
};
} // namespace flutter
#endif // SHELL_PLATFORM_ANDROID_SURFACE_SNAPSHOT_SURFACE_PRODUCER_H_
.packages
pubspec.lock # This only has local dependencies in it.
build/
ios/Scenarios/*.framework/
ios/Scenarios/*.xcframework/
android/app/libs/flutter.jar
android/app/src/main/jniLibs/arm64-v8a/libapp.so
android/gradle-home/.cache
!.vpython
# Copyright 2013 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("//flutter/build/dart/rules.gni")
import("//flutter/testing/rules/runtime_mode.gni")
assert(is_android)
dart_snapshot("android_background_image_snapshot") {
main_dart = "lib/main.dart"
package_config = ".dart_tool/package_config.json"
}
if (!is_aot) {
copy("copy_jit_assets") {
visibility = [ ":*" ]
sources = [
"$target_gen_dir/isolate_snapshot_data",
"$target_gen_dir/isolate_snapshot_instr",
"$target_gen_dir/kernel_blob.bin",
]
outputs = [ "$root_out_dir/android_background_image/app/assets/flutter_assets/{{source_file_part}}" ]
deps = [ ":android_background_image_snapshot" ]
}
}
group("android_background_image") {
deps = [
":android_background_image_snapshot",
"android",
]
if (!is_aot) {
deps += [ ":copy_jit_assets" ]
}
}
# Android Background Image
A test application that verifies Picture.toImage in the background on Android.
*.iml
.gradle
/local.properties
.settings
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cache
!gradlew
!gradlew.bat
!gradle/wrapper/**
# Copyright 2013 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("//flutter/testing/rules/android.gni")
_android_sources = [
"app/build.gradle",
"app/src/main/AndroidManifest.xml",
"app/src/main/java/dev/flutter/android_background_image/MainActivity.java",
"build.gradle",
]
gradle_task("android_lint") {
app_name = "android_background_image"
task = "lint"
gradlew_dir = rebase_path(".")
sources = _android_sources
outputs = [ "$root_out_dir/android_background_image/build/reports" ]
deps = [ "//flutter/testing/android_background_image:android_background_image_snapshot" ]
}
gradle_task("build_apk") {
app_name = "android_background_image"
task = "assembleDebug"
gradlew_dir = rebase_path(".")
sources = _android_sources
outputs = [ "$root_out_dir/android_background_image/app/outputs/apk/debug/app-debug.apk" ]
deps = [
":android_lint",
"//flutter/testing/android_background_image:android_background_image_snapshot",
]
}
copy("android") {
sources = get_target_outputs(":build_apk")
outputs = [ "$root_out_dir/firebase_apks/android_background_image.apk" ]
deps = [ ":build_apk" ]
}
apply plugin: 'com.android.application'
android {
lintOptions {
abortOnError true
checkAllWarnings true
showAll true
warningsAsErrors true
checkTestSources true
// UnpackedNativeCode can break stack unwinding - see b/193408481
// NewerVersionAvailable and GradleDependency need to be taken care of
// by a roller rather than as part of CI.
// The others are irrelevant for a test application.
disable 'UnpackedNativeCode','MissingApplicationIcon','GoogleAppIndexingApiWarning','GoogleAppIndexingWarning','GradleDependency','NewerVersionAvailable'
}
compileSdkVersion 30
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId 'dev.flutter.android_background_image'
minSdkVersion 16
targetSdkVersion 30
versionCode 1
versionName '1.0'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
sourceSets.main {
assets.srcDirs += "${project.buildDir}/assets"
if (project.hasProperty('libapp')) {
jni.srcDirs = []
jniLibs.srcDirs = [project.property('libapp')]
}
}
}
dependencies {
implementation files(project.property('flutter_jar'))
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.lifecycle:lifecycle-common-java8:2.2.0-alpha01'
}
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dev.flutter.android_background_image">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name="io.flutter.app.FlutterApplication"
android:allowBackup="false"
android:label="Background Image Tester"
android:supportsRtl="true">
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="com.google.intent.action.TEST_LOOP" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/javascript" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
// Copyright 2013 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 dev.flutter.android_background_image;
import android.content.Intent;
import android.util.Log;
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.BinaryMessenger;
import java.nio.ByteBuffer;
public class MainActivity extends FlutterActivity {
@NonNull
private final BinaryMessenger.BinaryMessageHandler finishHandler =
new BinaryMessenger.BinaryMessageHandler() {
@Override
public void onMessage(ByteBuffer message, final BinaryMessenger.BinaryReply callback) {
if (message != null) {
// Make CI see that there is an error in the logs from Flutter.
Log.e("flutter", "Images did not match.");
}
final Intent intent = new Intent(MainActivity.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
MainActivity.this.startActivity(intent);
MainActivity.this.finish();
}
};
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
flutterEngine.getDartExecutor().getBinaryMessenger().setMessageHandler("finish", finishHandler);
final boolean moved = moveTaskToBack(true);
if (!moved) {
Log.e("flutter", "Failed to move to back.");
finish();
}
}
}
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = project.hasProperty('out_dir')
? project.property('out_dir')
: '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
#
# "vpython" specification file for build
#
# Pillow is required by com.facebook.testing.screenshot.
python_version: "2.7"
wheel: <
name: "infra/python/wheels/pillow/${vpython_platform}"
version: "version:6.0.0"
>
#!/bin/bash
# This script is added to the PATH on LUCI when executing the junit tests.
# The Python scripts used to compare the screenshots are contained in a jar file.
# As a result, vpython cannot find the .vpython spec file because it's outside
# of the jar file.
set -e
SCRIPT_DIR="$( dirname "${BASH_SOURCE[0]}" )"
echo "Running from $SCRIPT_DIR/bin/python"
vpython -vpython-spec "$SCRIPT_DIR/../.vpython" "$@"
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true
#Mon Jul 22 20:16:02 PDT 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
// Copyright 2013 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:typed_data';
import 'dart:ui';
final Completer<bool> _completer = Completer<bool>();
Future<void> main() async {
channelBuffers.setListener('flutter/lifecycle', _lifecycle);
final bool success = await _completer.future;
final Uint8List? message = success ? null : Uint8List.fromList(const <int>[1]);
PlatformDispatcher.instance.sendPlatformMessage('finish', message?.buffer.asByteData(), null);
}
Future<void> _lifecycle(ByteData? data, PlatformMessageResponseCallback? callback) async {
final String lifecycleState = String.fromCharCodes(data!.buffer.asUint8List());
if (lifecycleState == AppLifecycleState.paused.toString()) {
await _testImage();
}
}
Future<void> _testImage() async {
// A single pixel image.
final Uint8List pixels = Uint8List.fromList(const <int>[0, 1, 2, 3]);
// As long as we're using the GL backend, this will go down a path that uses
// a cross context image.
final Completer<Image> imageCompleter = Completer<Image>();
decodeImageFromPixels(
pixels,
1,
1,
PixelFormat.rgba8888,
(Image image) {
imageCompleter.complete(image);
},
);
final Image image = await imageCompleter.future;
final PictureRecorder recorder = PictureRecorder();
final Canvas canvas = Canvas(recorder);
canvas.drawImage(image, Offset.zero, Paint());
final Picture picture = recorder.endRecording();
final Image newImage = await picture.toImage(1, 1);
final ByteData imageData = (await newImage.toByteData())!;
final Uint32List newPixels = imageData.buffer.asUint32List();
if (pixels.buffer.asUint32List()[0] != newPixels[0]) {
print('Pixels do not match');
print('original pixels: $pixels');
print('new pixels: ${newPixels.buffer.asUint8List()}');
_completer.complete(false);
} else {
print('Images are identical!');
_completer.complete(true);
}
}
# Copyright 2013 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.
name: android_background_image
publish_to: none
environment:
sdk: '>=2.12.0 <3.0.0'
# Do not add any dependencies that require more than what is provided in
# //third_party/dart/pkg, //third_party/dart/third_party/pkg, or
# //third_party/pkg. In particular, package:test is not usable here.
# If you do add packages here, make sure you can run `pub get --offline`, and
# check the .packages and .package_config to make sure all the paths are
# relative to this directory into //third_party/dart, or //third_party/pkg
dependencies:
sky_engine: any
dependency_overrides:
sky_engine:
path: ../../sky/packages/sky_engine
# Copyright 2013 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("//flutter/testing/rules/runtime_mode.gni")
template("gradle_task") {
action(target_name) {
assert(defined(invoker.task), "task is a required parmaeter")
assert(defined(invoker.outputs), "outputs is a required parameter")
assert(defined(invoker.sources), "sources is a required parameter")
assert(defined(invoker.gradlew_dir),
"gradlew_dir is required (normally: rebase_path(\".\"")
assert(defined(invoker.app_name), "app_name is a required parameter")
script = "//flutter/testing/rules/run_gradle.py"
inputs = [ "$root_out_dir/flutter.jar" ]
sources = invoker.sources
outputs = invoker.outputs
out_dir = rebase_path("$root_out_dir/${invoker.app_name}")
args = [
invoker.gradlew_dir,
invoker.task,
"--no-daemon",
"-Pflutter_jar=" + rebase_path("$root_out_dir/flutter.jar"),
"-Pout_dir=$out_dir",
"--project-cache-dir=$out_dir/.gradle",
"--gradle-user-home=$out_dir/.gradle",
]
if (is_aot) {
args += [ "-Plibapp=" + rebase_path("$target_gen_dir/libs") ]
inputs += [ "$target_gen_dir/libs/$android_app_abi/libapp.so" ]
}
deps = [ "//flutter/shell/platform/android:android_jar" ]
if (defined(invoker.deps)) {
deps += invoker.deps
}
}
}
......@@ -3,7 +3,7 @@
# found in the LICENSE file.
import("//flutter/build/dart/rules.gni")
import("//flutter/testing/rules/runtime_mode.gni")
import("//flutter/testing/scenario_app/runtime_mode.gni")
dart_snapshot("scenario_app_snapshot") {
main_dart = "lib/main.dart"
......
......@@ -13,7 +13,3 @@
/captures
.externalNativeBuild
.cache
!gradlew
!gradlew.bat
!gradle/wrapper/**
......@@ -2,9 +2,17 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//flutter/testing/rules/android.gni")
import("//flutter/testing/scenario_app/runtime_mode.gni")
_android_sources = [
template("gradle_task") {
action(target_name) {
assert(defined(invoker.task), "task is a required parmaeter")
assert(defined(invoker.outputs), "outputs is a required parameter")
script = "run_gradle.py"
inputs = [ "$root_out_dir/flutter.jar" ]
sources = [
"app/build.gradle",
"app/src/androidTest/java/dev/flutter/TestRunner.java",
"app/src/androidTest/java/dev/flutter/scenarios/EngineLaunchE2ETest.java",
......@@ -23,28 +31,45 @@ _android_sources = [
"app/src/main/java/dev/flutter/scenarios/TextPlatformViewActivity.java",
"app/src/main/java/dev/flutter/scenarios/TextPlatformViewFactory.java",
"build.gradle",
]
]
outputs = invoker.outputs
args = [
invoker.task,
"--no-daemon",
"-Pflutter_jar=" + rebase_path("$root_out_dir/flutter.jar"),
"-Pout_dir=" + rebase_path("$root_out_dir/scenario_app"),
]
if (is_aot) {
args += [ "-Plibapp=" + rebase_path("$target_gen_dir/libs") ]
inputs += [ "$target_gen_dir/libs/$android_app_abi/libapp.so" ]
}
deps = [
"//flutter/shell/platform/android:android_jar",
"//flutter/testing/scenario_app:scenario_app_snapshot",
]
if (defined(invoker.deps)) {
deps += invoker.deps
}
}
}
gradle_task("android_lint") {
app_name = "scenario_app"
task = "lint"
gradlew_dir = rebase_path(".")
sources = _android_sources
outputs = [ "$root_out_dir/scenario_app/build/reports" ]
deps = [ "//flutter/testing/scenario_app:scenario_app_snapshot" ]
outputs = [
"$root_out_dir/scenario_app/build/reports/lint-results.html",
"$root_out_dir/scenario_app/build/reports/lint-results.xml",
]
}
gradle_task("build_apk") {
app_name = "scenario_app"
task = "assembleDebug"
gradlew_dir = rebase_path(".")
sources = _android_sources
outputs = [ "$root_out_dir/scenario_app/app/outputs/apk/debug/app-debug.apk" ]
deps = [
":android_lint",
"//flutter/testing/scenario_app:scenario_app_snapshot",
]
deps = [ ":android_lint" ]
}
copy("android") {
......
......@@ -19,7 +19,7 @@ android {
// NewerVersionAvailable and GradleDependency need to be taken care of
// by a roller rather than as part of CI.
// The others are irrelevant for a test application.
disable 'UnpackedNativeCode','MissingApplicationIcon','GoogleAppIndexingApiWarning','GoogleAppIndexingWarning','GradleDependency','NewerVersionAvailable','Registered'
disable 'UnpackedNativeCode','MissingApplicationIcon','GoogleAppIndexingApiWarning','GoogleAppIndexingWarning','GradleDependency','NewerVersionAvailable'
}
compileSdkVersion 30
compileOptions {
......
......@@ -6,7 +6,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.0'
classpath 'com.android.tools.build:gradle:4.1.0'
classpath 'com.facebook.testing.screenshot:plugin:0.12.0'
// NOTE: Do not place your application dependencies here; they belong
......
......@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
......@@ -12,7 +12,7 @@ import sys
import subprocess
SCRIPT_PATH = os.path.dirname(os.path.realpath(__file__))
ANDROID_HOME = os.path.join(SCRIPT_PATH, '..', '..', '..', 'third_party',
ANDROID_HOME = os.path.join(SCRIPT_PATH, '..', '..', '..', '..', 'third_party',
'android_tools', 'sdk')
def main():
......@@ -20,10 +20,10 @@ def main():
raise Exception('%s (ANDROID_HOME) is not a directory' % ANDROID_HOME)
BAT = '.bat' if sys.platform.startswith(('cygwin', 'win')) else ''
android_dir = sys.argv[1]
android_dir = os.path.abspath(os.path.dirname(__file__))
gradle_bin = os.path.join('.', 'gradlew%s' % BAT)
result = subprocess.check_output(
args=[gradle_bin] + sys.argv[2:],
args=[gradle_bin] + sys.argv[1:],
cwd=android_dir,
env=dict(os.environ, ANDROID_HOME=ANDROID_HOME),
)
......
......@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//flutter/testing/rules/runtime_mode.gni")
import("//flutter/testing/scenario_app/runtime_mode.gni")
import("//third_party/dart/build/dart/copy_tree.gni")
_app_framework_dir = "$root_out_dir/scenario_app/Scenarios/App.framework"
......
......@@ -20,7 +20,6 @@ ALL_PACKAGES = [
os.path.join("src", "flutter", "testing", "benchmark"),
os.path.join("src", "flutter", "testing", "dart"),
os.path.join("src", "flutter", "testing", "litetest"),
os.path.join("src", "flutter", "testing", "android_background_image"),
os.path.join("src", "flutter", "testing", "scenario_app"),
os.path.join("src", "flutter", "testing", "smoke_test_failure"),
os.path.join("src", "flutter", "testing", "symbols"),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册