forked from firka/flutter
[android] only release background image readers on Android 14. (#165942)
Fixes https://github.com/flutter/flutter/issues/163561 Fixes https://github.com/flutter/flutter/issues/156488 Fixes https://github.com/flutter/flutter/issues/156489 Fixes https://github.com/flutter/flutter/issues/163520 Forked from https://github.com/flutter/flutter/pull/163692 Only release background image readers on Android 14. I believe reader disposal is the ultimate cause of https://github.com/flutter/flutter/issues/162147 , where older android devices don't seem to handle backgrounding the same way we expect on newer devices. The result of this is a crash in HWUI, which is unexpected. Since we only ever did the background release to work around an ANdroid 14 bug, and because it breaks other functionality like background playback - we should remove it for all targets besides 14.
This commit is contained in:
@@ -16,10 +16,12 @@ namespace flutter {
|
||||
ImageExternalTexture::ImageExternalTexture(
|
||||
int64_t id,
|
||||
const fml::jni::ScopedJavaGlobalRef<jobject>& image_texture_entry,
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade)
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
|
||||
ImageLifecycle lifecycle)
|
||||
: Texture(id),
|
||||
image_texture_entry_(image_texture_entry),
|
||||
jni_facade_(jni_facade) {}
|
||||
jni_facade_(jni_facade),
|
||||
texture_lifecycle_(lifecycle) {}
|
||||
|
||||
ImageExternalTexture::~ImageExternalTexture() = default;
|
||||
|
||||
@@ -66,8 +68,19 @@ void ImageExternalTexture::OnGrContextCreated() {
|
||||
// Implementing flutter::ContextListener.
|
||||
void ImageExternalTexture::OnGrContextDestroyed() {
|
||||
if (state_ == AttachmentState::kAttached) {
|
||||
dl_image_.reset();
|
||||
image_lru_.Clear();
|
||||
switch (texture_lifecycle_) {
|
||||
case ImageLifecycle::kReset: {
|
||||
dl_image_.reset();
|
||||
image_lru_.Clear();
|
||||
} break;
|
||||
case ImageLifecycle::kKeepAlive:
|
||||
// Intentionally do nothing.
|
||||
///
|
||||
// If we reset the image, we are not able to re-acquire it, but the
|
||||
// producer of the image will not know to reproduce it, resulting in a
|
||||
// blank image. See https://github.com/flutter/flutter/issues/163561.
|
||||
break;
|
||||
}
|
||||
Detach();
|
||||
}
|
||||
state_ = AttachmentState::kDetached;
|
||||
|
||||
@@ -35,10 +35,14 @@ namespace flutter {
|
||||
///
|
||||
class ImageExternalTexture : public flutter::Texture {
|
||||
public:
|
||||
/// Whether the last image should be reset when the context is destroyed.
|
||||
enum class ImageLifecycle { kReset, kKeepAlive };
|
||||
|
||||
explicit ImageExternalTexture(
|
||||
int64_t id,
|
||||
const fml::jni::ScopedJavaGlobalRef<jobject>& image_texture_entry,
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade);
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
|
||||
ImageLifecycle lifecycle);
|
||||
|
||||
// |flutter::Texture|
|
||||
virtual ~ImageExternalTexture();
|
||||
@@ -100,6 +104,7 @@ class ImageExternalTexture : public flutter::Texture {
|
||||
// |flutter::ContextListener|
|
||||
void OnGrContextDestroyed() override;
|
||||
|
||||
const ImageLifecycle texture_lifecycle_;
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(ImageExternalTexture);
|
||||
};
|
||||
|
||||
|
||||
@@ -24,8 +24,9 @@ namespace flutter {
|
||||
ImageExternalTextureGL::ImageExternalTextureGL(
|
||||
int64_t id,
|
||||
const fml::jni::ScopedJavaGlobalRef<jobject>& image_texture_entry,
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade)
|
||||
: ImageExternalTexture(id, image_texture_entry, jni_facade) {}
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
|
||||
ImageExternalTexture::ImageLifecycle lifecycle)
|
||||
: ImageExternalTexture(id, image_texture_entry, jni_facade, lifecycle) {}
|
||||
|
||||
void ImageExternalTextureGL::Attach(PaintContext& context) {
|
||||
if (state_ == AttachmentState::kUninitialized) {
|
||||
|
||||
@@ -20,7 +20,8 @@ class ImageExternalTextureGL : public ImageExternalTexture {
|
||||
ImageExternalTextureGL(
|
||||
int64_t id,
|
||||
const fml::jni::ScopedJavaGlobalRef<jobject>& image_textury_entry,
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade);
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
|
||||
ImageExternalTexture::ImageLifecycle lifecycle);
|
||||
|
||||
protected:
|
||||
// |ImageExternalTexture|
|
||||
|
||||
@@ -13,8 +13,9 @@ ImageExternalTextureGLImpeller::ImageExternalTextureGLImpeller(
|
||||
const std::shared_ptr<impeller::ContextGLES>& context,
|
||||
int64_t id,
|
||||
const fml::jni::ScopedJavaGlobalRef<jobject>& image_textury_entry,
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade)
|
||||
: ImageExternalTextureGL(id, image_textury_entry, jni_facade),
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
|
||||
ImageExternalTexture::ImageLifecycle lifecycle)
|
||||
: ImageExternalTextureGL(id, image_textury_entry, jni_facade, lifecycle),
|
||||
impeller_context_(context) {}
|
||||
|
||||
void ImageExternalTextureGLImpeller::Detach() {}
|
||||
|
||||
@@ -22,7 +22,8 @@ class ImageExternalTextureGLImpeller : public ImageExternalTextureGL {
|
||||
int64_t id,
|
||||
const fml::jni::ScopedJavaGlobalRef<jobject>&
|
||||
hardware_buffer_texture_entry,
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade);
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
|
||||
ImageExternalTexture::ImageLifecycle lifecycle);
|
||||
|
||||
private:
|
||||
// |ImageExternalTexture|
|
||||
|
||||
@@ -13,8 +13,9 @@ ImageExternalTextureGLSkia::ImageExternalTextureGLSkia(
|
||||
const std::shared_ptr<AndroidContextGLSkia>& context,
|
||||
int64_t id,
|
||||
const fml::jni::ScopedJavaGlobalRef<jobject>& image_texture_entry,
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade)
|
||||
: ImageExternalTextureGL(id, image_texture_entry, jni_facade) {}
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
|
||||
ImageExternalTexture::ImageLifecycle lifecycle)
|
||||
: ImageExternalTextureGL(id, image_texture_entry, jni_facade, lifecycle) {}
|
||||
|
||||
void ImageExternalTextureGLSkia::Attach(PaintContext& context) {
|
||||
if (state_ == AttachmentState::kUninitialized) {
|
||||
|
||||
@@ -19,7 +19,8 @@ class ImageExternalTextureGLSkia : public ImageExternalTextureGL {
|
||||
const std::shared_ptr<AndroidContextGLSkia>& context,
|
||||
int64_t id,
|
||||
const fml::jni::ScopedJavaGlobalRef<jobject>& image_textury_entry,
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade);
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
|
||||
ImageExternalTexture::ImageLifecycle lifecycle);
|
||||
|
||||
private:
|
||||
// |ImageExternalTexture|
|
||||
|
||||
@@ -20,8 +20,9 @@ ImageExternalTextureVKImpeller::ImageExternalTextureVKImpeller(
|
||||
const std::shared_ptr<impeller::ContextVK>& impeller_context,
|
||||
int64_t id,
|
||||
const fml::jni::ScopedJavaGlobalRef<jobject>& image_texture_entry,
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade)
|
||||
: ImageExternalTexture(id, image_texture_entry, jni_facade),
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
|
||||
ImageExternalTexture::ImageLifecycle lifecycle)
|
||||
: ImageExternalTexture(id, image_texture_entry, jni_facade, lifecycle),
|
||||
impeller_context_(impeller_context) {}
|
||||
|
||||
ImageExternalTextureVKImpeller::~ImageExternalTextureVKImpeller() {}
|
||||
|
||||
@@ -23,7 +23,8 @@ class ImageExternalTextureVKImpeller : public ImageExternalTexture {
|
||||
int64_t id,
|
||||
const fml::jni::ScopedJavaGlobalRef<jobject>&
|
||||
hardware_buffer_texture_entry,
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade);
|
||||
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
|
||||
ImageExternalTexture::ImageLifecycle lifecycle);
|
||||
|
||||
~ImageExternalTextureVKImpeller() override;
|
||||
|
||||
|
||||
@@ -938,19 +938,23 @@ public class FlutterJNI {
|
||||
*/
|
||||
@UiThread
|
||||
public void registerImageTexture(
|
||||
long textureId, @NonNull TextureRegistry.ImageConsumer imageTexture) {
|
||||
long textureId,
|
||||
@NonNull TextureRegistry.ImageConsumer imageTexture,
|
||||
boolean resetOnBackground) {
|
||||
ensureRunningOnMainThread();
|
||||
ensureAttachedToNative();
|
||||
nativeRegisterImageTexture(
|
||||
nativeShellHolderId,
|
||||
textureId,
|
||||
new WeakReference<TextureRegistry.ImageConsumer>(imageTexture));
|
||||
new WeakReference<TextureRegistry.ImageConsumer>(imageTexture),
|
||||
resetOnBackground);
|
||||
}
|
||||
|
||||
private native void nativeRegisterImageTexture(
|
||||
long nativeShellHolderId,
|
||||
long textureId,
|
||||
@NonNull WeakReference<TextureRegistry.ImageConsumer> imageTexture);
|
||||
@NonNull WeakReference<TextureRegistry.ImageConsumer> imageTexture,
|
||||
boolean resetOnBackground);
|
||||
|
||||
/**
|
||||
* Call this method to inform Flutter that a texture previously registered with {@link
|
||||
|
||||
@@ -186,37 +186,16 @@ public class FlutterRenderer implements TextureRegistry {
|
||||
*/
|
||||
@NonNull
|
||||
@Override
|
||||
public SurfaceProducer createSurfaceProducer() {
|
||||
// Prior to Impeller, Flutter on Android *only* ran on OpenGLES (via Skia). That
|
||||
// meant that
|
||||
// plugins (i.e. end-users) either explicitly created a SurfaceTexture (via
|
||||
// createX/registerX) or an ImageTexture (via createX/registerX).
|
||||
//
|
||||
// In an Impeller world, which for the first time uses (if available) a Vulkan
|
||||
// rendering
|
||||
// backend, it is no longer possible (at least not trivially) to render an
|
||||
// OpenGLES-provided
|
||||
// texture (SurfaceTexture) in a Vulkan context.
|
||||
//
|
||||
// This function picks the "best" rendering surface based on the Android
|
||||
// runtime, and
|
||||
// provides a consumer-agnostic SurfaceProducer (which in turn vends a Surface),
|
||||
// and has
|
||||
// plugins (i.e. end-users) use the Surface instead, letting us "hide" the
|
||||
// consumer-side
|
||||
// of the implementation.
|
||||
//
|
||||
// tl;dr: If ImageTexture is available, we use it, otherwise we use a
|
||||
// SurfaceTexture.
|
||||
// Coincidentally, if ImageTexture is available, we are also on an Android
|
||||
// version that is
|
||||
// running Vulkan, so we don't have to worry about it not being supported.
|
||||
public SurfaceProducer createSurfaceProducer(SurfaceLifecycle lifecycle) {
|
||||
final SurfaceProducer entry;
|
||||
if (!debugForceSurfaceProducerGlTextures && Build.VERSION.SDK_INT >= API_LEVELS.API_29) {
|
||||
final long id = nextTextureId.getAndIncrement();
|
||||
final ImageReaderSurfaceProducer producer = new ImageReaderSurfaceProducer(id);
|
||||
registerImageTexture(id, producer);
|
||||
addOnTrimMemoryListener(producer);
|
||||
boolean reset = lifecycle == SurfaceLifecycle.resetInBackground;
|
||||
registerImageTexture(id, producer, reset);
|
||||
if (reset) {
|
||||
addOnTrimMemoryListener(producer);
|
||||
}
|
||||
imageReaderProducers.add(producer);
|
||||
Log.v(TAG, "New ImageReaderSurfaceProducer ID: " + id);
|
||||
entry = producer;
|
||||
@@ -282,7 +261,7 @@ public class FlutterRenderer implements TextureRegistry {
|
||||
final ImageTextureRegistryEntry entry =
|
||||
new ImageTextureRegistryEntry(nextTextureId.getAndIncrement());
|
||||
Log.v(TAG, "New ImageTextureEntry ID: " + entry.id());
|
||||
registerImageTexture(entry.id(), entry);
|
||||
registerImageTexture(entry.id(), entry, /*resetOnBackground=*/ false);
|
||||
return entry;
|
||||
}
|
||||
|
||||
@@ -1279,25 +1258,23 @@ public class FlutterRenderer implements TextureRegistry {
|
||||
displayFeaturesState);
|
||||
}
|
||||
|
||||
// TODO(mattcarroll): describe the native behavior that this invokes
|
||||
// TODO(mattcarroll): determine if this is nullable or nonnull
|
||||
public Bitmap getBitmap() {
|
||||
return flutterJNI.getBitmap();
|
||||
}
|
||||
|
||||
// TODO(mattcarroll): describe the native behavior that this invokes
|
||||
public void dispatchPointerDataPacket(@NonNull ByteBuffer buffer, int position) {
|
||||
flutterJNI.dispatchPointerDataPacket(buffer, position);
|
||||
}
|
||||
|
||||
// TODO(mattcarroll): describe the native behavior that this invokes
|
||||
private void registerTexture(long textureId, @NonNull SurfaceTextureWrapper textureWrapper) {
|
||||
flutterJNI.registerTexture(textureId, textureWrapper);
|
||||
}
|
||||
|
||||
private void registerImageTexture(
|
||||
long textureId, @NonNull TextureRegistry.ImageConsumer imageTexture) {
|
||||
flutterJNI.registerImageTexture(textureId, imageTexture);
|
||||
long textureId,
|
||||
@NonNull TextureRegistry.ImageConsumer imageTexture,
|
||||
boolean resetOnBackground) {
|
||||
flutterJNI.registerImageTexture(textureId, imageTexture, resetOnBackground);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -1305,27 +1282,22 @@ public class FlutterRenderer implements TextureRegistry {
|
||||
flutterJNI.scheduleFrame();
|
||||
}
|
||||
|
||||
// TODO(mattcarroll): describe the native behavior that this invokes
|
||||
private void unregisterTexture(long textureId) {
|
||||
flutterJNI.unregisterTexture(textureId);
|
||||
}
|
||||
|
||||
// TODO(mattcarroll): describe the native behavior that this invokes
|
||||
public boolean isSoftwareRenderingEnabled() {
|
||||
return flutterJNI.getIsSoftwareRenderingEnabled();
|
||||
}
|
||||
|
||||
// TODO(mattcarroll): describe the native behavior that this invokes
|
||||
public void setAccessibilityFeatures(int flags) {
|
||||
flutterJNI.setAccessibilityFeatures(flags);
|
||||
}
|
||||
|
||||
// TODO(mattcarroll): describe the native behavior that this invokes
|
||||
public void setSemanticsEnabled(boolean enabled) {
|
||||
flutterJNI.setSemanticsEnabled(enabled);
|
||||
}
|
||||
|
||||
// TODO(mattcarroll): describe the native behavior that this invokes
|
||||
public void dispatchSemanticsAction(
|
||||
int nodeId, int action, @Nullable ByteBuffer args, int argsPosition) {
|
||||
flutterJNI.dispatchSemanticsAction(nodeId, action, args, argsPosition);
|
||||
|
||||
@@ -977,7 +977,12 @@ public class PlatformViewsController implements PlatformViewsAccessibilityDelega
|
||||
private static PlatformViewRenderTarget makePlatformViewRenderTarget(
|
||||
TextureRegistry textureRegistry) {
|
||||
if (enableSurfaceProducerRenderTarget && Build.VERSION.SDK_INT >= API_LEVELS.API_29) {
|
||||
final TextureRegistry.SurfaceProducer textureEntry = textureRegistry.createSurfaceProducer();
|
||||
TextureRegistry.SurfaceLifecycle lifecycle =
|
||||
Build.VERSION.SDK_INT == API_LEVELS.API_34
|
||||
? TextureRegistry.SurfaceLifecycle.resetInBackground
|
||||
: TextureRegistry.SurfaceLifecycle.manual;
|
||||
final TextureRegistry.SurfaceProducer textureEntry =
|
||||
textureRegistry.createSurfaceProducer(lifecycle);
|
||||
Log.i(TAG, "PlatformView is using SurfaceProducer backend");
|
||||
return new SurfaceProducerPlatformViewRenderTarget(textureEntry);
|
||||
}
|
||||
|
||||
@@ -18,12 +18,57 @@ import androidx.annotation.Nullable;
|
||||
*/
|
||||
public interface TextureRegistry {
|
||||
/**
|
||||
* Creates and registers a SurfaceProducer texture managed by the Flutter engine.
|
||||
* Creates and registers a {@link SurfaceProducer}, or a Flutter-managed {@link Surface}.
|
||||
*
|
||||
* <p>Uses the {@link SurfaceLifecycle#manual} lifecycle implicitly.
|
||||
*
|
||||
* @return A SurfaceProducer.
|
||||
*/
|
||||
@NonNull
|
||||
SurfaceProducer createSurfaceProducer();
|
||||
default SurfaceProducer createSurfaceProducer() {
|
||||
return createSurfaceProducer(SurfaceLifecycle.manual);
|
||||
}
|
||||
/**
|
||||
* How a {@link SurfaceProducer} created by {@link #createSurfaceProducer()} manages the lifecycle
|
||||
* of the created surface.
|
||||
*/
|
||||
enum SurfaceLifecycle {
|
||||
/**
|
||||
* The surface and latest image should be kept, even if the app enters the background.
|
||||
*
|
||||
* <p>The application, or calling code, can choose to (manually) reset the surface at the
|
||||
* appropriate time (such as to lower memory pressure, or cleanup an unused surface), but by
|
||||
* default the surface will never be reset, and as a result, new images do not have to be drawn
|
||||
* to the surface.
|
||||
*
|
||||
* <p>This is an appropriate lifecycle for external textures, as it is not guaranteed that new
|
||||
* images will be drawn to the surface, and whether the image should be kept when the app is
|
||||
* backgrounded.
|
||||
*/
|
||||
manual,
|
||||
|
||||
/**
|
||||
* The surface will be reset if the app enters the background.
|
||||
*
|
||||
* <p>While the application can choose to manually reset the surface, Flutter may automatically
|
||||
* reset the surface when the app enters the background. If the surface is reset, and no new
|
||||
* images are drawn to the surface, the texture will appear blank.
|
||||
*
|
||||
* <p>This is an appropriate lifecycle for platform views, as the platform implementation will
|
||||
* request a new surface, and draw to, as appropriate when resuming from the background, and
|
||||
* producing a new image when coming back to the foreground.
|
||||
*/
|
||||
resetInBackground
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and a {@link SurfaceProducer}, or a Flutter-managed {@link Surface}.
|
||||
*
|
||||
* @param lifecycle Whether to automatically reset the last image and release the surface.
|
||||
* @return A SurfaceProducer.
|
||||
*/
|
||||
@NonNull
|
||||
SurfaceProducer createSurfaceProducer(SurfaceLifecycle lifecycle);
|
||||
|
||||
/**
|
||||
* Creates and registers a SurfaceTexture managed by the Flutter engine.
|
||||
|
||||
@@ -348,26 +348,27 @@ void PlatformViewAndroid::RegisterExternalTexture(
|
||||
|
||||
void PlatformViewAndroid::RegisterImageTexture(
|
||||
int64_t texture_id,
|
||||
const fml::jni::ScopedJavaGlobalRef<jobject>& image_texture_entry) {
|
||||
const fml::jni::ScopedJavaGlobalRef<jobject>& image_texture_entry,
|
||||
ImageExternalTexture::ImageLifecycle lifecycle) {
|
||||
switch (android_context_->RenderingApi()) {
|
||||
case AndroidRenderingAPI::kImpellerOpenGLES:
|
||||
// Impeller GLES.
|
||||
RegisterTexture(std::make_shared<ImageExternalTextureGLImpeller>(
|
||||
std::static_pointer_cast<impeller::ContextGLES>(
|
||||
android_context_->GetImpellerContext()),
|
||||
texture_id, image_texture_entry, jni_facade_));
|
||||
texture_id, image_texture_entry, jni_facade_, lifecycle));
|
||||
break;
|
||||
case AndroidRenderingAPI::kSkiaOpenGLES:
|
||||
// Legacy GL.
|
||||
RegisterTexture(std::make_shared<ImageExternalTextureGLSkia>(
|
||||
std::static_pointer_cast<AndroidContextGLSkia>(android_context_),
|
||||
texture_id, image_texture_entry, jni_facade_));
|
||||
texture_id, image_texture_entry, jni_facade_, lifecycle));
|
||||
break;
|
||||
case AndroidRenderingAPI::kImpellerVulkan:
|
||||
RegisterTexture(std::make_shared<ImageExternalTextureVKImpeller>(
|
||||
std::static_pointer_cast<impeller::ContextVK>(
|
||||
android_context_->GetImpellerContext()),
|
||||
texture_id, image_texture_entry, jni_facade_));
|
||||
texture_id, image_texture_entry, jni_facade_, lifecycle));
|
||||
break;
|
||||
case AndroidRenderingAPI::kSoftware:
|
||||
FML_LOG(INFO) << "Software rendering does not support external textures.";
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "flutter/shell/platform/android/platform_view_android_delegate/platform_view_android_delegate.h"
|
||||
#include "flutter/shell/platform/android/surface/android_native_window.h"
|
||||
#include "flutter/shell/platform/android/surface/android_surface.h"
|
||||
#include "shell/platform/android/image_external_texture.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
@@ -93,7 +94,8 @@ class PlatformViewAndroid final : public PlatformView {
|
||||
|
||||
void RegisterImageTexture(
|
||||
int64_t texture_id,
|
||||
const fml::jni::ScopedJavaGlobalRef<jobject>& image_texture_entry);
|
||||
const fml::jni::ScopedJavaGlobalRef<jobject>& image_texture_entry,
|
||||
ImageExternalTexture::ImageLifecycle lifecycle);
|
||||
|
||||
// |PlatformView|
|
||||
void LoadDartDeferredLibrary(
|
||||
|
||||
@@ -530,10 +530,16 @@ static void RegisterImageTexture(JNIEnv* env,
|
||||
jobject jcaller,
|
||||
jlong shell_holder,
|
||||
jlong texture_id,
|
||||
jobject image_texture_entry) {
|
||||
jobject image_texture_entry,
|
||||
jboolean reset_on_background) {
|
||||
ImageExternalTexture::ImageLifecycle lifecycle =
|
||||
reset_on_background ? ImageExternalTexture::ImageLifecycle::kReset
|
||||
: ImageExternalTexture::ImageLifecycle::kKeepAlive;
|
||||
|
||||
ANDROID_SHELL_HOLDER->GetPlatformView()->RegisterImageTexture(
|
||||
static_cast<int64_t>(texture_id), //
|
||||
fml::jni::ScopedJavaGlobalRef<jobject>(env, image_texture_entry) //
|
||||
static_cast<int64_t>(texture_id), //
|
||||
fml::jni::ScopedJavaGlobalRef<jobject>(env, image_texture_entry), //
|
||||
lifecycle //
|
||||
);
|
||||
}
|
||||
|
||||
@@ -811,7 +817,7 @@ bool RegisterApi(JNIEnv* env) {
|
||||
{
|
||||
.name = "nativeRegisterImageTexture",
|
||||
.signature = "(JJLjava/lang/ref/"
|
||||
"WeakReference;)V",
|
||||
"WeakReference;Z)V",
|
||||
.fnPtr = reinterpret_cast<void*>(&RegisterImageTexture),
|
||||
},
|
||||
{
|
||||
|
||||
@@ -829,7 +829,8 @@ public class FlutterRendererTest {
|
||||
@SuppressWarnings({"deprecation", "removal"})
|
||||
public void ImageReaderSurfaceProducerIsCleanedUpOnTrimMemory() {
|
||||
FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
|
||||
TextureRegistry.SurfaceProducer producer = flutterRenderer.createSurfaceProducer();
|
||||
TextureRegistry.SurfaceProducer producer =
|
||||
flutterRenderer.createSurfaceProducer(TextureRegistry.SurfaceLifecycle.resetInBackground);
|
||||
|
||||
// Create and set a mock callback.
|
||||
TextureRegistry.SurfaceProducer.Callback callback =
|
||||
@@ -851,7 +852,8 @@ public class FlutterRendererTest {
|
||||
public void ImageReaderSurfaceProducerSignalsCleanupBeforeDestroying() throws Exception {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/160933.
|
||||
FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
|
||||
TextureRegistry.SurfaceProducer producer = flutterRenderer.createSurfaceProducer();
|
||||
TextureRegistry.SurfaceProducer producer =
|
||||
flutterRenderer.createSurfaceProducer(TextureRegistry.SurfaceLifecycle.resetInBackground);
|
||||
|
||||
// Ensure the callbacks were actually called.
|
||||
// Note this needs to be an object in order to be accessed in the callback.
|
||||
@@ -902,7 +904,8 @@ public class FlutterRendererTest {
|
||||
public void ImageReaderSurfaceProducerUnsubscribesWhenReleased() {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/156434.
|
||||
FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
|
||||
TextureRegistry.SurfaceProducer producer = flutterRenderer.createSurfaceProducer();
|
||||
TextureRegistry.SurfaceProducer producer =
|
||||
flutterRenderer.createSurfaceProducer(TextureRegistry.SurfaceLifecycle.resetInBackground);
|
||||
|
||||
// Create and set a mock callback.
|
||||
TextureRegistry.SurfaceProducer.Callback callback =
|
||||
@@ -924,7 +927,8 @@ public class FlutterRendererTest {
|
||||
@SuppressWarnings({"deprecation", "removal"})
|
||||
public void ImageReaderSurfaceProducerIsCreatedOnLifecycleResume() throws Exception {
|
||||
FlutterRenderer flutterRenderer = engineRule.getFlutterEngine().getRenderer();
|
||||
TextureRegistry.SurfaceProducer producer = flutterRenderer.createSurfaceProducer();
|
||||
TextureRegistry.SurfaceProducer producer =
|
||||
flutterRenderer.createSurfaceProducer(TextureRegistry.SurfaceLifecycle.resetInBackground);
|
||||
|
||||
// Create a callback.
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
@@ -1621,7 +1621,7 @@ public class PlatformViewsControllerTest {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public SurfaceProducer createSurfaceProducer() {
|
||||
public SurfaceProducer createSurfaceProducer(SurfaceLifecycle lifecycle) {
|
||||
return new SurfaceProducer() {
|
||||
@Override
|
||||
public void setCallback(SurfaceProducer.Callback cb) {}
|
||||
|
||||
Reference in New Issue
Block a user