Use SurfaceSyncGroup to ensure resize transaction isn't dropped

This workaround is only applied on API 34, because the problem isn't
present on API 33 and it is fixed in the platform for API 35 onwards.

Issue: androidx/media#1237

#cherrypick

PiperOrigin-RevId: 644729909
This commit is contained in:
ibaker 2024-06-19 06:24:47 -07:00 committed by Copybara-Service
parent 6cc6444dd9
commit 968f72fec6
2 changed files with 61 additions and 0 deletions

View File

@ -24,6 +24,9 @@
connected, the session activity can be updated with
`MediaSession.setSessionActivity(ControllerInfo, PendingIntent)`.
* UI:
* Work around a platform bug causing stretched/cropped video when using
`SurfaceView` inside a Compose `AndroidView` on API 34
([#1237](https://github.com/androidx/media/issues/1237)).
* Downloads:
* OkHttp Extension:
* Cronet Extension:

View File

@ -31,6 +31,7 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
@ -39,9 +40,11 @@ import android.opengl.GLSurfaceView;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.view.AttachedSurfaceControl;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
@ -49,6 +52,7 @@ import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.window.SurfaceSyncGroup;
import androidx.annotation.ColorInt;
import androidx.annotation.DoNotInline;
import androidx.annotation.IntDef;
@ -293,6 +297,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
@Nullable private final View shutterView;
@Nullable private final View surfaceView;
private final boolean surfaceViewIgnoresVideoAspectRatio;
@Nullable private final SurfaceSyncGroupCompatV34 surfaceSyncGroupV34;
@Nullable private final ImageView imageView;
@Nullable private final ImageView artworkView;
@Nullable private final SubtitleView subtitleView;
@ -353,6 +358,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
shutterView = null;
surfaceView = null;
surfaceViewIgnoresVideoAspectRatio = false;
surfaceSyncGroupV34 = null;
imageView = null;
artworkView = null;
subtitleView = null;
@ -489,6 +495,7 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
surfaceView = null;
}
this.surfaceViewIgnoresVideoAspectRatio = surfaceViewIgnoresVideoAspectRatio;
this.surfaceSyncGroupV34 = Util.SDK_INT == 34 ? new SurfaceSyncGroupCompatV34() : null;
// Ad overlay frame layout.
adOverlayFrameLayout = findViewById(R.id.exo_ad_overlay);
@ -1773,6 +1780,14 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
contentFrame, surfaceViewIgnoresVideoAspectRatio ? 0 : videoAspectRatio);
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (Util.SDK_INT == 34) {
checkNotNull(surfaceSyncGroupV34).maybeMarkSyncReadyAndClear();
}
}
@RequiresApi(23)
private static void configureEditModeLogoV23(
Context context, Resources resources, ImageView logo) {
@ -1862,6 +1877,17 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
updateAspectRatio();
}
@Override
public void onSurfaceSizeChanged(int width, int height) {
if (Util.SDK_INT == 34 && surfaceView instanceof SurfaceView) {
// Register a SurfaceSyncGroup to work around https://github.com/androidx/media/issues/1237
// (only present on API 34, fixed on API 35).
checkNotNull(surfaceSyncGroupV34)
.postRegister(
mainLooperHandler, (SurfaceView) surfaceView, PlayerView.this::invalidate);
}
}
@Override
public void onRenderedFirstFrame() {
if (shutterView != null) {
@ -1981,4 +2007,36 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
surfaceView.setSurfaceLifecycle(SurfaceView.SURFACE_LIFECYCLE_FOLLOWS_ATTACHMENT);
}
}
@RequiresApi(34)
private static final class SurfaceSyncGroupCompatV34 {
@Nullable SurfaceSyncGroup surfaceSyncGroup;
@DoNotInline
public void postRegister(
Handler mainLooperHandler, SurfaceView surfaceView, Runnable invalidate) {
mainLooperHandler.post(
() -> {
@Nullable
AttachedSurfaceControl rootSurfaceControl = surfaceView.getRootSurfaceControl();
if (rootSurfaceControl == null) {
// The SurfaceView isn't attached to a window, so don't apply the workaround.
return;
}
surfaceSyncGroup = new SurfaceSyncGroup("exo-sync-b-334901521");
Assertions.checkState(surfaceSyncGroup.add(rootSurfaceControl, () -> {}));
invalidate.run();
rootSurfaceControl.applyTransactionOnDraw(new SurfaceControl.Transaction());
});
}
@DoNotInline
public void maybeMarkSyncReadyAndClear() {
if (surfaceSyncGroup != null) {
surfaceSyncGroup.markSyncReady();
surfaceSyncGroup = null;
}
}
}
}