Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Add SurfaceProducer#onSurfaceAvailable, deprecate onSurfaceCreated. #55418

Merged
merged 2 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,9 @@ public FlutterRenderer(@NonNull FlutterJNI flutterJNI) {
public void onResume(@NonNull LifecycleOwner owner) {
Log.v(TAG, "onResume called; notifying SurfaceProducers");
for (ImageReaderSurfaceProducer producer : imageReaderProducers) {
if (producer.callback != null) {
producer.callback.onSurfaceCreated();
if (producer.callback != null && producer.notifiedDestroy) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this check ensures that we don't fire the callback multiple times if the surface wasn't prev destroyed. Makes sense!

producer.notifiedDestroy = false;
producer.callback.onSurfaceAvailable();
}
}
}
Expand Down Expand Up @@ -462,6 +463,13 @@ final class ImageReaderSurfaceProducer
// will be produced at that size.
private boolean createNewReader = true;

/**
* Stores whether {@link Callback#onSurfaceDestroyed()} was previously invoked.
*
* <p>Used to avoid signaling {@link Callback#onSurfaceAvailable()} unnecessarily.
*/
private boolean notifiedDestroy = false;

// State held to track latency of various stages.
private long lastDequeueTime = 0;
private long lastQueueTime = 0;
Expand Down Expand Up @@ -689,6 +697,7 @@ public void onTrimMemory(int level) {
cleanup();
createNewReader = true;
if (this.callback != null) {
notifiedDestroy = true;
this.callback.onSurfaceDestroyed();
}
}
Expand Down
65 changes: 56 additions & 9 deletions shell/platform/android/io/flutter/view/TextureRegistry.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ interface SurfaceProducer extends TextureEntry {

/**
* Sets a callback that is notified when a previously created {@link Surface} returned by {@link
* SurfaceProducer#getSurface()} is no longer valid, either due to being destroyed or being
* changed.
* SurfaceProducer#getSurface()} is no longer valid due to being destroyed, or a new surface is
* now available (after the previous one was destroyed) for rendering.
*
* @param callback The callback to notify, or null to remove the callback.
*/
Expand All @@ -106,18 +106,65 @@ interface SurfaceProducer extends TextureEntry {
/** Callback invoked by {@link #setCallback(Callback)}. */
interface Callback {
/**
* Invoked when a previous surface is now invalid and a new surface is now available.
* An alias for {@link Callback#onSurfaceAvailable()} with a less accurate name.
*
* @deprecated Override and use {@link Callback#onSurfaceAvailable()} instead.
*/
@Deprecated(since = "Flutter 3.27", forRemoval = true)
default void onSurfaceCreated() {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

default? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically let folks who haven't used SurfaceProducer.Callback not have to define both methods.


/**
* Invoked when an Android application is resumed after {@link Callback#onSurfaceDestroyed()}.
*
* <p>Typically plugins will use this callback as a signal to redraw, such as due to the
* texture being resized, the format being changed, or the application being resumed after
* being suspended in the background.
* <p>Applications should now call {@link SurfaceProducer#getSurface()} to get a new
* {@link Surface}, as the previous one was destroyed and released as a result of a low memory
* event from the Android OS.
*
* <pre>
* {@code
* void example(SurfaceProducer producer) {
* producer.setCallback(new SurfaceProducer.Callback() {
* @override
* public void onSurfaceAvailable() {
* Surface surface = producer.getSurface();
* redrawOrUse(surface);
* }
*
* // ...
* });
* }
* }
* </pre>
*/
void onSurfaceCreated();
default void onSurfaceAvailable() {
this.onSurfaceCreated();
}

/**
* Invoked when a previous surface is now invalid.
* Invoked when a {@link Surface} returned by {@link SurfaceProducer#getSurface()} is invalid.
*
* <p>In a low memory environment, the Android OS will signal to Flutter to release resources,
* such as surfaces, that are not currently in use, such as when the application is in the
* background, and this method is subsequently called to notify a plugin author to stop
* using or rendering to the last surface.
*
* <p>Use {@link Callback#onSurfaceAvailable()} to be notified to resume rendering.
*
* <pre>
* {@code
* void example(SurfaceProducer producer) {
* producer.setCallback(new SurfaceProducer.Callback() {
* @override
* public void onSurfaceDestroyed() {
* // Store information about the last frame, if necessary.
* // Potentially release other dependent resources.
* }
*
* <p>Typically plugins will use this callback as a signal to release resources.
* // ...
* });
* }
* }
* </pre>
*/
void onSurfaceDestroyed();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,7 @@ public void ImageReaderSurfaceProducerIsCreatedOnLifecycleResume() throws Except
TextureRegistry.SurfaceProducer.Callback callback =
new TextureRegistry.SurfaceProducer.Callback() {
@Override
public void onSurfaceCreated() {
public void onSurfaceAvailable() {
latch.countDown();
}

Expand All @@ -771,6 +771,9 @@ public void onSurfaceDestroyed() {}
};
producer.setCallback(callback);

// Trim memory.
((FlutterRenderer.ImageReaderSurfaceProducer) producer).onTrimMemory(40);

// Trigger a resume.
((LifecycleRegistry) ProcessLifecycleOwner.get().getLifecycle())
.setCurrentState(Lifecycle.State.RESUMED);
Expand Down