From 18eec9cf40469b7b688562ea1cd4b7bc65fd591a Mon Sep 17 00:00:00 2001 From: Shan Huang Date: Wed, 23 Mar 2022 06:35:08 +0000 Subject: [PATCH] Migrate MediaController to use OnBackInvokedDispatcher The OnBackInvokedCallback will be called when an app is requesting the new back dispatch behavior. Otherwise we keep dispatching KEYCODE_BACK to MediaController. Test: In BackTestApp, try dismissing media controller by swiping back, both in new and legacy back dispatch. Change-Id: I9ad3c199277838639c875c78a3a8dfb0963b3ca4 --- core/java/android/widget/MediaController.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java index 9c9baf35949bd..f1dc5e7050fb6 100644 --- a/core/java/android/widget/MediaController.java +++ b/core/java/android/widget/MediaController.java @@ -16,6 +16,7 @@ package android.widget; +import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Resources; @@ -30,10 +31,14 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.ViewRootImpl; import android.view.Window; import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; import android.widget.SeekBar.OnSeekBarChangeListener; +import android.window.OnBackInvokedCallback; +import android.window.OnBackInvokedDispatcher; +import android.window.WindowOnBackInvokedDispatcher; import com.android.internal.policy.PhoneWindow; @@ -115,6 +120,27 @@ public class MediaController extends FrameLayout { private CharSequence mPlayDescription; private CharSequence mPauseDescription; private final AccessibilityManager mAccessibilityManager; + private boolean mBackCallbackRegistered; + /** Handles back invocation */ + private final OnBackInvokedCallback mBackCallback = new OnBackInvokedCallback() { + @Override + public void onBackInvoked() { + hide(); + } + }; + /** Handles decor view attach state change */ + private final OnAttachStateChangeListener mAttachStateListener = + new OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(@NonNull View v) { + registerOnBackInvokedCallback(); + } + + @Override + public void onViewDetachedFromWindow(@NonNull View v) { + unregisterOnBackInvokedCallback(); + } + }; public MediaController(Context context, AttributeSet attrs) { super(context, attrs); @@ -151,6 +177,7 @@ public class MediaController extends FrameLayout { mWindow.requestFeature(Window.FEATURE_NO_TITLE); mDecor = mWindow.getDecorView(); mDecor.setOnTouchListener(mTouchListener); + mDecor.addOnAttachStateChangeListener(mAttachStateListener); mWindow.setContentView(this); mWindow.setBackgroundDrawableResource(android.R.color.transparent); @@ -395,6 +422,7 @@ public class MediaController extends FrameLayout { removeCallbacks(mFadeOut); postDelayed(mFadeOut, timeout); } + registerOnBackInvokedCallback(); } public boolean isShowing() { @@ -416,6 +444,7 @@ public class MediaController extends FrameLayout { Log.w("MediaController", "already removed"); } mShowing = false; + unregisterOnBackInvokedCallback(); } } @@ -718,6 +747,35 @@ public class MediaController extends FrameLayout { } } + private void unregisterOnBackInvokedCallback() { + if (!mBackCallbackRegistered) { + return; + } + ViewRootImpl viewRootImpl = mDecor.getViewRootImpl(); + if (viewRootImpl != null + && WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled( + viewRootImpl.mContext)) { + viewRootImpl.getOnBackInvokedDispatcher() + .unregisterOnBackInvokedCallback(mBackCallback); + } + mBackCallbackRegistered = false; + } + + private void registerOnBackInvokedCallback() { + if (mBackCallbackRegistered) { + return; + } + + ViewRootImpl viewRootImpl = mDecor.getViewRootImpl(); + if (viewRootImpl != null + && WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled( + viewRootImpl.mContext)) { + viewRootImpl.getOnBackInvokedDispatcher().registerOnBackInvokedCallback( + OnBackInvokedDispatcher.PRIORITY_DEFAULT, mBackCallback); + mBackCallbackRegistered = true; + } + } + public interface MediaPlayerControl { void start(); void pause();