diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 2242168453..63646d0282 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -1514,10 +1514,12 @@ public abstract class AbsSwipeUpHandler, if (mIsSwipingPipToHome && mSwipePipToHomeAnimator != null) { SystemUiProxy.INSTANCE.get(mContext).stopSwipePipToHome( mSwipePipToHomeAnimator.getComponentName(), - mSwipePipToHomeAnimator.getDestinationBounds()); + mSwipePipToHomeAnimator.getDestinationBounds(), + mSwipePipToHomeAnimator.getContentOverlay()); mRecentsAnimationController.setFinishTaskTransaction( mSwipePipToHomeAnimator.getTaskId(), - mSwipePipToHomeAnimator.getFinishTransaction()); + mSwipePipToHomeAnimator.getFinishTransaction(), + mSwipePipToHomeAnimator.getContentOverlay()); mIsSwipingPipToHome = false; } } diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java index 78da311971..f2bd916e11 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java @@ -19,6 +19,7 @@ import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.THREAD_POOL_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; +import android.view.SurfaceControl; import android.window.PictureInPictureSurfaceTransaction; import androidx.annotation.NonNull; @@ -159,12 +160,15 @@ public class RecentsAnimationController { * that animating Activity to PiP has completed and the associated task surface should be * updated accordingly. This should be called before `finish` * @param taskId for which the leash should be updated - * @param finishTransaction leash operations for the final transform. + * @param finishTransaction the transaction to transfer to the task surface control after the + * leash is removed + * @param overlay the surface control for an overlay being shown above the pip (can be null) */ public void setFinishTaskTransaction(int taskId, - PictureInPictureSurfaceTransaction finishTransaction) { + PictureInPictureSurfaceTransaction finishTransaction, + SurfaceControl overlay) { UI_HELPER_EXECUTOR.execute( - () -> mController.setFinishTaskTransaction(taskId, finishTransaction)); + () -> mController.setFinishTaskTransaction(taskId, finishTransaction, overlay)); } /** diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index 39d8888c72..6fb938ad32 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -33,6 +33,7 @@ import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; import android.view.MotionEvent; +import android.view.SurfaceControl; import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.SplitConfigurationOptions; @@ -427,10 +428,11 @@ public class SystemUiProxy implements ISystemUiProxy, return null; } - public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) { + public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds, + SurfaceControl overlay) { if (mPip != null) { try { - mPip.stopSwipePipToHome(componentName, destinationBounds); + mPip.stopSwipePipToHome(componentName, destinationBounds, overlay); } catch (RemoteException e) { Log.w(TAG, "Failed call stopSwipePipToHome"); } diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java index b5570a7445..36311302bf 100644 --- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java +++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java @@ -22,19 +22,24 @@ import android.animation.Animator; import android.animation.RectEvaluator; import android.animation.ValueAnimator; import android.content.ComponentName; +import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.RectF; import android.util.Log; import android.view.Surface; import android.view.SurfaceControl; +import android.view.SurfaceSession; import android.view.View; import android.window.PictureInPictureSurfaceTransaction; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimationSuccessListener; +import com.android.launcher3.anim.Interpolators; +import com.android.launcher3.util.Themes; import com.android.systemui.shared.pip.PipSurfaceTransactionHelper; import com.android.systemui.shared.system.InteractionJankMonitorWrapper; @@ -78,6 +83,12 @@ public class SwipePipToHomeAnimator extends ValueAnimator { */ private boolean mHasAnimationEnded; + /** + * An overlay used to mask changes in content when entering PiP for apps that aren't seamless. + */ + @Nullable + private SurfaceControl mContentOverlay; + /** * @param taskId Task id associated with this animator, see also {@link #getTaskId()} * @param componentName Component associated with this animator, @@ -112,6 +123,33 @@ public class SwipePipToHomeAnimator extends ValueAnimator { if (sourceRectHint == null) { mSourceHintRectInsets = null; + + // Create a new overlay layer + SurfaceSession session = new SurfaceSession(); + mContentOverlay = new SurfaceControl.Builder(session) + .setCallsite("SwipePipToHomeAnimator") + .setName("PipContentOverlay") + .setColorLayer() + .build(); + SurfaceControl.Transaction t = new SurfaceControl.Transaction(); + t.show(mContentOverlay); + t.setLayer(mContentOverlay, Integer.MAX_VALUE); + int color = Themes.getColorBackground(view.getContext()); + float[] bgColor = new float[] {Color.red(color) / 255f, Color.green(color) / 255f, + Color.blue(color) / 255f}; + t.setColor(mContentOverlay, bgColor); + t.setAlpha(mContentOverlay, 0f); + t.reparent(mContentOverlay, mLeash); + t.apply(); + + addUpdateListener(valueAnimator -> { + float alpha = valueAnimator.getAnimatedFraction() < 0.5f + ? 0 + : Utilities.mapToRange(valueAnimator.getAnimatedFraction(), 0.5f, 1f, + 0f, 1f, Interpolators.FAST_OUT_SLOW_IN); + t.setAlpha(mContentOverlay, alpha); + t.apply(); + }); } else { mSourceHintRectInsets = new Rect(sourceRectHint.left - appBounds.left, sourceRectHint.top - appBounds.top, @@ -234,6 +272,11 @@ public class SwipePipToHomeAnimator extends ValueAnimator { return mDestinationBounds; } + @Nullable + public SurfaceControl getContentOverlay() { + return mContentOverlay; + } + /** @return {@link PictureInPictureSurfaceTransaction} for the final leash transaction. */ public PictureInPictureSurfaceTransaction getFinishTransaction() { // get the final leash operations but do not apply to the leash. diff --git a/src/com/android/launcher3/util/Themes.java b/src/com/android/launcher3/util/Themes.java index 06cac08aec..8243dd480b 100644 --- a/src/com/android/launcher3/util/Themes.java +++ b/src/com/android/launcher3/util/Themes.java @@ -92,7 +92,7 @@ public class Themes { return getAttrColor(context, android.R.attr.colorAccent); } - /** Returns the floating background color attribute. */ + /** Returns the background color attribute. */ public static int getColorBackground(Context context) { return getAttrColor(context, android.R.attr.colorBackground); }