Loading core/java/android/app/TaskInfo.java +0 −17 Original line number Diff line number Diff line Loading @@ -34,10 +34,7 @@ import android.graphics.Rect; import android.os.Build; import android.os.IBinder; import android.os.Parcel; import android.os.RemoteException; import android.util.Log; import android.view.DisplayCutout; import android.window.TaskSnapshot; import android.window.WindowContainerToken; import java.lang.annotation.Retention; Loading Loading @@ -355,20 +352,6 @@ public class TaskInfo { return isVisible; } /** * @param isLowResolution * @return * @hide */ public TaskSnapshot getTaskSnapshot(boolean isLowResolution) { try { return ActivityTaskManager.getService().getTaskSnapshot(taskId, isLowResolution); } catch (RemoteException e) { Log.e(TAG, "Failed to get task snapshot, taskId=" + taskId, e); return null; } } /** @hide */ @NonNull @TestApi Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java +19 −35 Original line number Diff line number Diff line Loading @@ -27,13 +27,11 @@ import android.animation.ValueAnimator; import android.annotation.IntDef; import android.app.TaskInfo; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.Rect; import android.view.Choreographer; import android.view.Surface; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.window.TaskSnapshot; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.SfVsyncFrameCallbackProvider; Loading Loading @@ -257,7 +255,7 @@ public class PipAnimationController { mSurfaceControlTransactionFactory; private PipSurfaceTransactionHelper mSurfaceTransactionHelper; private @TransitionDirection int mTransitionDirection; protected SurfaceControl mContentOverlay; protected PipContentOverlay mContentOverlay; private PipTransitionAnimator(TaskInfo taskInfo, SurfaceControl leash, @AnimationType int animationType, Loading Loading @@ -335,43 +333,26 @@ public class PipAnimationController { return false; } SurfaceControl getContentOverlay() { return mContentOverlay; SurfaceControl getContentOverlayLeash() { return mContentOverlay == null ? null : mContentOverlay.mLeash; } PipTransitionAnimator<T> setUseContentOverlay(Context context) { void setColorContentOverlay(Context context) { final SurfaceControl.Transaction tx = newSurfaceControlTransaction(); if (mContentOverlay != null) { // remove existing content overlay if there is any. tx.remove(mContentOverlay); tx.apply(); mContentOverlay.detach(tx); } mContentOverlay = new SurfaceControl.Builder(new SurfaceSession()) .setCallsite("PipAnimation") .setName("PipContentOverlay") .setColorLayer() .build(); tx.show(mContentOverlay); tx.setLayer(mContentOverlay, Integer.MAX_VALUE); tx.setColor(mContentOverlay, getContentOverlayColor(context)); tx.setAlpha(mContentOverlay, 0f); tx.reparent(mContentOverlay, mLeash); tx.apply(); return this; mContentOverlay = new PipContentOverlay.PipColorOverlay(context); mContentOverlay.attach(tx, mLeash); } private float[] getContentOverlayColor(Context context) { final TypedArray ta = context.obtainStyledAttributes(new int[] { android.R.attr.colorBackground }); try { int colorAccent = ta.getColor(0, 0); return new float[] { Color.red(colorAccent) / 255f, Color.green(colorAccent) / 255f, Color.blue(colorAccent) / 255f }; } finally { ta.recycle(); void setSnapshotContentOverlay(TaskSnapshot snapshot, Rect sourceRectHint) { final SurfaceControl.Transaction tx = newSurfaceControlTransaction(); if (mContentOverlay != null) { mContentOverlay.detach(tx); } mContentOverlay = new PipContentOverlay.PipSnapshotOverlay(snapshot, sourceRectHint); mContentOverlay.attach(tx, mLeash); } /** Loading Loading @@ -575,7 +556,7 @@ public class PipAnimationController { final Rect start = getStartValue(); final Rect end = getEndValue(); if (mContentOverlay != null) { tx.setAlpha(mContentOverlay, fraction < 0.5f ? 0 : (fraction - 0.5f) * 2); mContentOverlay.onAnimationUpdate(tx, fraction); } if (rotatedEndRect != null) { // Animate the bounds in a different orientation. It only happens when Loading Loading @@ -680,7 +661,7 @@ public class PipAnimationController { .round(tx, leash, shouldApplyCornerRadius()) .shadow(tx, leash, shouldApplyShadowRadius()); // TODO(b/178632364): this is a work around for the black background when // entering PiP in buttion navigation mode. // entering PiP in button navigation mode. if (isInPipDirection(direction)) { tx.setWindowCrop(leash, getStartValue()); } Loading @@ -704,6 +685,9 @@ public class PipAnimationController { } else { getSurfaceTransactionHelper().crop(tx, leash, destBounds); } if (mContentOverlay != null) { mContentOverlay.onAnimationEnd(tx, destBounds); } } @Override Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipContentOverlay.java 0 → 100644 +164 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.pip; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.Rect; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.window.TaskSnapshot; /** * Represents the content overlay used during the entering PiP animation. */ public abstract class PipContentOverlay { protected SurfaceControl mLeash; /** Attaches the internal {@link #mLeash} to the given parent leash. */ public abstract void attach(SurfaceControl.Transaction tx, SurfaceControl parentLeash); /** Detaches the internal {@link #mLeash} from its parent by removing itself. */ public void detach(SurfaceControl.Transaction tx) { if (mLeash != null && mLeash.isValid()) { tx.remove(mLeash); tx.apply(); } } /** * Animates the internal {@link #mLeash} by a given fraction. * @param atomicTx {@link SurfaceControl.Transaction} to operate, you should not explicitly * call apply on this transaction, it should be applied on the caller side. * @param fraction progress of the animation ranged from 0f to 1f. */ public abstract void onAnimationUpdate(SurfaceControl.Transaction atomicTx, float fraction); /** * Callback when reaches the end of animation on the internal {@link #mLeash}. * @param atomicTx {@link SurfaceControl.Transaction} to operate, you should not explicitly * call apply on this transaction, it should be applied on the caller side. * @param destinationBounds {@link Rect} of the final bounds. */ public abstract void onAnimationEnd(SurfaceControl.Transaction atomicTx, Rect destinationBounds); /** A {@link PipContentOverlay} uses solid color. */ public static final class PipColorOverlay extends PipContentOverlay { private final Context mContext; public PipColorOverlay(Context context) { mContext = context; mLeash = new SurfaceControl.Builder(new SurfaceSession()) .setCallsite("PipAnimation") .setName(PipColorOverlay.class.getSimpleName()) .setColorLayer() .build(); } @Override public void attach(SurfaceControl.Transaction tx, SurfaceControl parentLeash) { tx.show(mLeash); tx.setLayer(mLeash, Integer.MAX_VALUE); tx.setColor(mLeash, getContentOverlayColor(mContext)); tx.setAlpha(mLeash, 0f); tx.reparent(mLeash, parentLeash); tx.apply(); } @Override public void onAnimationUpdate(SurfaceControl.Transaction atomicTx, float fraction) { atomicTx.setAlpha(mLeash, fraction < 0.5f ? 0 : (fraction - 0.5f) * 2); } @Override public void onAnimationEnd(SurfaceControl.Transaction atomicTx, Rect destinationBounds) { // Do nothing. Color overlay should be fully opaque by now. } private float[] getContentOverlayColor(Context context) { final TypedArray ta = context.obtainStyledAttributes(new int[] { android.R.attr.colorBackground }); try { int colorAccent = ta.getColor(0, 0); return new float[] { Color.red(colorAccent) / 255f, Color.green(colorAccent) / 255f, Color.blue(colorAccent) / 255f }; } finally { ta.recycle(); } } } /** A {@link PipContentOverlay} uses {@link TaskSnapshot}. */ public static final class PipSnapshotOverlay extends PipContentOverlay { private final TaskSnapshot mSnapshot; private final Rect mSourceRectHint; private float mTaskSnapshotScaleX; private float mTaskSnapshotScaleY; public PipSnapshotOverlay(TaskSnapshot snapshot, Rect sourceRectHint) { mSnapshot = snapshot; mSourceRectHint = new Rect(sourceRectHint); mLeash = new SurfaceControl.Builder(new SurfaceSession()) .setCallsite("PipAnimation") .setName(PipSnapshotOverlay.class.getSimpleName()) .build(); } @Override public void attach(SurfaceControl.Transaction tx, SurfaceControl parentLeash) { mTaskSnapshotScaleX = (float) mSnapshot.getTaskSize().x / mSnapshot.getHardwareBuffer().getWidth(); mTaskSnapshotScaleY = (float) mSnapshot.getTaskSize().y / mSnapshot.getHardwareBuffer().getHeight(); tx.show(mLeash); tx.setLayer(mLeash, Integer.MAX_VALUE); tx.setBuffer(mLeash, mSnapshot.getHardwareBuffer()); tx.setCrop(mLeash, mSourceRectHint); tx.setScale(mLeash, mTaskSnapshotScaleX, mTaskSnapshotScaleY); tx.reparent(mLeash, parentLeash); tx.apply(); } @Override public void onAnimationUpdate(SurfaceControl.Transaction atomicTx, float fraction) { // Do nothing. Keep the snapshot till animation ends. } @Override public void onAnimationEnd(SurfaceControl.Transaction atomicTx, Rect destinationBounds) { // Work around to make sure the snapshot overlay is aligned with PiP window before // the atomicTx is committed along with the final WindowContainerTransaction. final SurfaceControl.Transaction nonAtomicTx = new SurfaceControl.Transaction(); final float scaleX = (float) destinationBounds.width() / mSnapshot.getHardwareBuffer().getWidth(); final float scaleY = (float) destinationBounds.height() / mSnapshot.getHardwareBuffer().getHeight(); final float scale = Math.max(scaleX, scaleY); nonAtomicTx.setScale(mLeash, scale, scale); nonAtomicTx.setPosition(mLeash, -scale * mSourceRectHint.left / mTaskSnapshotScaleX, -scale * mSourceRectHint.top / mTaskSnapshotScaleY); nonAtomicTx.apply(); atomicTx.remove(mLeash); } } } libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +20 −8 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ import android.view.Display; import android.view.Surface; import android.view.SurfaceControl; import android.window.TaskOrganizer; import android.window.TaskSnapshot; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; Loading Loading @@ -152,8 +153,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, final int direction = animator.getTransitionDirection(); final int animationType = animator.getAnimationType(); final Rect destinationBounds = animator.getDestinationBounds(); if (isInPipDirection(direction) && animator.getContentOverlay() != null) { fadeOutAndRemoveOverlay(animator.getContentOverlay(), if (isInPipDirection(direction) && animator.getContentOverlayLeash() != null) { fadeOutAndRemoveOverlay(animator.getContentOverlayLeash(), animator::clearContentOverlay, true /* withStartDelay*/); } if (mWaitForFixedRotation && animationType == ANIM_TYPE_BOUNDS Loading Loading @@ -186,8 +187,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, public void onPipAnimationCancel(TaskInfo taskInfo, PipAnimationController.PipTransitionAnimator animator) { final int direction = animator.getTransitionDirection(); if (isInPipDirection(direction) && animator.getContentOverlay() != null) { fadeOutAndRemoveOverlay(animator.getContentOverlay(), if (isInPipDirection(direction) && animator.getContentOverlayLeash() != null) { fadeOutAndRemoveOverlay(animator.getContentOverlayLeash(), animator::clearContentOverlay, true /* withStartDelay */); } sendOnPipTransitionCancelled(direction); Loading Loading @@ -803,8 +804,9 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, final PipAnimationController.PipTransitionAnimator<?> animator = mPipAnimationController.getCurrentAnimator(); if (animator != null) { if (animator.getContentOverlay() != null) { removeContentOverlay(animator.getContentOverlay(), animator::clearContentOverlay); if (animator.getContentOverlayLeash() != null) { removeContentOverlay(animator.getContentOverlayLeash(), animator::clearContentOverlay); } animator.removeAllUpdateListeners(); animator.removeAllListeners(); Loading Loading @@ -1491,7 +1493,17 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, if (isInPipDirection(direction)) { // Similar to auto-enter-pip transition, we use content overlay when there is no // source rect hint to enter PiP use bounds animation. if (sourceHintRect == null) animator.setUseContentOverlay(mContext); if (sourceHintRect == null) { animator.setColorContentOverlay(mContext); } else { final TaskSnapshot snapshot = PipUtils.getTaskSnapshot( mTaskInfo.launchIntoPipHostTaskId, false /* isLowResolution */); if (snapshot != null) { // use the task snapshot during the animation, this is for // launch-into-pip aka. content-pip use case. animator.setSnapshotContentOverlay(snapshot, sourceHintRect); } } // The destination bounds are used for the end rect of animation and the final bounds // after animation finishes. So after the animation is started, the destination bounds // can be updated to new rotation (computeRotatedBounds has changed the DisplayLayout Loading Loading @@ -1555,7 +1567,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, */ void fadeOutAndRemoveOverlay(SurfaceControl surface, Runnable callback, boolean withStartDelay) { if (surface == null) { if (surface == null || !surface.isValid()) { return; } Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java +1 −1 Original line number Diff line number Diff line Loading @@ -709,7 +709,7 @@ public class PipTransition extends PipTransitionController { if (sourceHintRect == null) { // We use content overlay when there is no source rect hint to enter PiP use bounds // animation. animator.setUseContentOverlay(mContext); animator.setColorContentOverlay(mContext); } } else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) { startTransaction.setAlpha(leash, 0f); Loading Loading
core/java/android/app/TaskInfo.java +0 −17 Original line number Diff line number Diff line Loading @@ -34,10 +34,7 @@ import android.graphics.Rect; import android.os.Build; import android.os.IBinder; import android.os.Parcel; import android.os.RemoteException; import android.util.Log; import android.view.DisplayCutout; import android.window.TaskSnapshot; import android.window.WindowContainerToken; import java.lang.annotation.Retention; Loading Loading @@ -355,20 +352,6 @@ public class TaskInfo { return isVisible; } /** * @param isLowResolution * @return * @hide */ public TaskSnapshot getTaskSnapshot(boolean isLowResolution) { try { return ActivityTaskManager.getService().getTaskSnapshot(taskId, isLowResolution); } catch (RemoteException e) { Log.e(TAG, "Failed to get task snapshot, taskId=" + taskId, e); return null; } } /** @hide */ @NonNull @TestApi Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java +19 −35 Original line number Diff line number Diff line Loading @@ -27,13 +27,11 @@ import android.animation.ValueAnimator; import android.annotation.IntDef; import android.app.TaskInfo; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.Rect; import android.view.Choreographer; import android.view.Surface; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.window.TaskSnapshot; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.SfVsyncFrameCallbackProvider; Loading Loading @@ -257,7 +255,7 @@ public class PipAnimationController { mSurfaceControlTransactionFactory; private PipSurfaceTransactionHelper mSurfaceTransactionHelper; private @TransitionDirection int mTransitionDirection; protected SurfaceControl mContentOverlay; protected PipContentOverlay mContentOverlay; private PipTransitionAnimator(TaskInfo taskInfo, SurfaceControl leash, @AnimationType int animationType, Loading Loading @@ -335,43 +333,26 @@ public class PipAnimationController { return false; } SurfaceControl getContentOverlay() { return mContentOverlay; SurfaceControl getContentOverlayLeash() { return mContentOverlay == null ? null : mContentOverlay.mLeash; } PipTransitionAnimator<T> setUseContentOverlay(Context context) { void setColorContentOverlay(Context context) { final SurfaceControl.Transaction tx = newSurfaceControlTransaction(); if (mContentOverlay != null) { // remove existing content overlay if there is any. tx.remove(mContentOverlay); tx.apply(); mContentOverlay.detach(tx); } mContentOverlay = new SurfaceControl.Builder(new SurfaceSession()) .setCallsite("PipAnimation") .setName("PipContentOverlay") .setColorLayer() .build(); tx.show(mContentOverlay); tx.setLayer(mContentOverlay, Integer.MAX_VALUE); tx.setColor(mContentOverlay, getContentOverlayColor(context)); tx.setAlpha(mContentOverlay, 0f); tx.reparent(mContentOverlay, mLeash); tx.apply(); return this; mContentOverlay = new PipContentOverlay.PipColorOverlay(context); mContentOverlay.attach(tx, mLeash); } private float[] getContentOverlayColor(Context context) { final TypedArray ta = context.obtainStyledAttributes(new int[] { android.R.attr.colorBackground }); try { int colorAccent = ta.getColor(0, 0); return new float[] { Color.red(colorAccent) / 255f, Color.green(colorAccent) / 255f, Color.blue(colorAccent) / 255f }; } finally { ta.recycle(); void setSnapshotContentOverlay(TaskSnapshot snapshot, Rect sourceRectHint) { final SurfaceControl.Transaction tx = newSurfaceControlTransaction(); if (mContentOverlay != null) { mContentOverlay.detach(tx); } mContentOverlay = new PipContentOverlay.PipSnapshotOverlay(snapshot, sourceRectHint); mContentOverlay.attach(tx, mLeash); } /** Loading Loading @@ -575,7 +556,7 @@ public class PipAnimationController { final Rect start = getStartValue(); final Rect end = getEndValue(); if (mContentOverlay != null) { tx.setAlpha(mContentOverlay, fraction < 0.5f ? 0 : (fraction - 0.5f) * 2); mContentOverlay.onAnimationUpdate(tx, fraction); } if (rotatedEndRect != null) { // Animate the bounds in a different orientation. It only happens when Loading Loading @@ -680,7 +661,7 @@ public class PipAnimationController { .round(tx, leash, shouldApplyCornerRadius()) .shadow(tx, leash, shouldApplyShadowRadius()); // TODO(b/178632364): this is a work around for the black background when // entering PiP in buttion navigation mode. // entering PiP in button navigation mode. if (isInPipDirection(direction)) { tx.setWindowCrop(leash, getStartValue()); } Loading @@ -704,6 +685,9 @@ public class PipAnimationController { } else { getSurfaceTransactionHelper().crop(tx, leash, destBounds); } if (mContentOverlay != null) { mContentOverlay.onAnimationEnd(tx, destBounds); } } @Override Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipContentOverlay.java 0 → 100644 +164 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.pip; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.Rect; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.window.TaskSnapshot; /** * Represents the content overlay used during the entering PiP animation. */ public abstract class PipContentOverlay { protected SurfaceControl mLeash; /** Attaches the internal {@link #mLeash} to the given parent leash. */ public abstract void attach(SurfaceControl.Transaction tx, SurfaceControl parentLeash); /** Detaches the internal {@link #mLeash} from its parent by removing itself. */ public void detach(SurfaceControl.Transaction tx) { if (mLeash != null && mLeash.isValid()) { tx.remove(mLeash); tx.apply(); } } /** * Animates the internal {@link #mLeash} by a given fraction. * @param atomicTx {@link SurfaceControl.Transaction} to operate, you should not explicitly * call apply on this transaction, it should be applied on the caller side. * @param fraction progress of the animation ranged from 0f to 1f. */ public abstract void onAnimationUpdate(SurfaceControl.Transaction atomicTx, float fraction); /** * Callback when reaches the end of animation on the internal {@link #mLeash}. * @param atomicTx {@link SurfaceControl.Transaction} to operate, you should not explicitly * call apply on this transaction, it should be applied on the caller side. * @param destinationBounds {@link Rect} of the final bounds. */ public abstract void onAnimationEnd(SurfaceControl.Transaction atomicTx, Rect destinationBounds); /** A {@link PipContentOverlay} uses solid color. */ public static final class PipColorOverlay extends PipContentOverlay { private final Context mContext; public PipColorOverlay(Context context) { mContext = context; mLeash = new SurfaceControl.Builder(new SurfaceSession()) .setCallsite("PipAnimation") .setName(PipColorOverlay.class.getSimpleName()) .setColorLayer() .build(); } @Override public void attach(SurfaceControl.Transaction tx, SurfaceControl parentLeash) { tx.show(mLeash); tx.setLayer(mLeash, Integer.MAX_VALUE); tx.setColor(mLeash, getContentOverlayColor(mContext)); tx.setAlpha(mLeash, 0f); tx.reparent(mLeash, parentLeash); tx.apply(); } @Override public void onAnimationUpdate(SurfaceControl.Transaction atomicTx, float fraction) { atomicTx.setAlpha(mLeash, fraction < 0.5f ? 0 : (fraction - 0.5f) * 2); } @Override public void onAnimationEnd(SurfaceControl.Transaction atomicTx, Rect destinationBounds) { // Do nothing. Color overlay should be fully opaque by now. } private float[] getContentOverlayColor(Context context) { final TypedArray ta = context.obtainStyledAttributes(new int[] { android.R.attr.colorBackground }); try { int colorAccent = ta.getColor(0, 0); return new float[] { Color.red(colorAccent) / 255f, Color.green(colorAccent) / 255f, Color.blue(colorAccent) / 255f }; } finally { ta.recycle(); } } } /** A {@link PipContentOverlay} uses {@link TaskSnapshot}. */ public static final class PipSnapshotOverlay extends PipContentOverlay { private final TaskSnapshot mSnapshot; private final Rect mSourceRectHint; private float mTaskSnapshotScaleX; private float mTaskSnapshotScaleY; public PipSnapshotOverlay(TaskSnapshot snapshot, Rect sourceRectHint) { mSnapshot = snapshot; mSourceRectHint = new Rect(sourceRectHint); mLeash = new SurfaceControl.Builder(new SurfaceSession()) .setCallsite("PipAnimation") .setName(PipSnapshotOverlay.class.getSimpleName()) .build(); } @Override public void attach(SurfaceControl.Transaction tx, SurfaceControl parentLeash) { mTaskSnapshotScaleX = (float) mSnapshot.getTaskSize().x / mSnapshot.getHardwareBuffer().getWidth(); mTaskSnapshotScaleY = (float) mSnapshot.getTaskSize().y / mSnapshot.getHardwareBuffer().getHeight(); tx.show(mLeash); tx.setLayer(mLeash, Integer.MAX_VALUE); tx.setBuffer(mLeash, mSnapshot.getHardwareBuffer()); tx.setCrop(mLeash, mSourceRectHint); tx.setScale(mLeash, mTaskSnapshotScaleX, mTaskSnapshotScaleY); tx.reparent(mLeash, parentLeash); tx.apply(); } @Override public void onAnimationUpdate(SurfaceControl.Transaction atomicTx, float fraction) { // Do nothing. Keep the snapshot till animation ends. } @Override public void onAnimationEnd(SurfaceControl.Transaction atomicTx, Rect destinationBounds) { // Work around to make sure the snapshot overlay is aligned with PiP window before // the atomicTx is committed along with the final WindowContainerTransaction. final SurfaceControl.Transaction nonAtomicTx = new SurfaceControl.Transaction(); final float scaleX = (float) destinationBounds.width() / mSnapshot.getHardwareBuffer().getWidth(); final float scaleY = (float) destinationBounds.height() / mSnapshot.getHardwareBuffer().getHeight(); final float scale = Math.max(scaleX, scaleY); nonAtomicTx.setScale(mLeash, scale, scale); nonAtomicTx.setPosition(mLeash, -scale * mSourceRectHint.left / mTaskSnapshotScaleX, -scale * mSourceRectHint.top / mTaskSnapshotScaleY); nonAtomicTx.apply(); atomicTx.remove(mLeash); } } }
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +20 −8 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ import android.view.Display; import android.view.Surface; import android.view.SurfaceControl; import android.window.TaskOrganizer; import android.window.TaskSnapshot; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; Loading Loading @@ -152,8 +153,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, final int direction = animator.getTransitionDirection(); final int animationType = animator.getAnimationType(); final Rect destinationBounds = animator.getDestinationBounds(); if (isInPipDirection(direction) && animator.getContentOverlay() != null) { fadeOutAndRemoveOverlay(animator.getContentOverlay(), if (isInPipDirection(direction) && animator.getContentOverlayLeash() != null) { fadeOutAndRemoveOverlay(animator.getContentOverlayLeash(), animator::clearContentOverlay, true /* withStartDelay*/); } if (mWaitForFixedRotation && animationType == ANIM_TYPE_BOUNDS Loading Loading @@ -186,8 +187,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, public void onPipAnimationCancel(TaskInfo taskInfo, PipAnimationController.PipTransitionAnimator animator) { final int direction = animator.getTransitionDirection(); if (isInPipDirection(direction) && animator.getContentOverlay() != null) { fadeOutAndRemoveOverlay(animator.getContentOverlay(), if (isInPipDirection(direction) && animator.getContentOverlayLeash() != null) { fadeOutAndRemoveOverlay(animator.getContentOverlayLeash(), animator::clearContentOverlay, true /* withStartDelay */); } sendOnPipTransitionCancelled(direction); Loading Loading @@ -803,8 +804,9 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, final PipAnimationController.PipTransitionAnimator<?> animator = mPipAnimationController.getCurrentAnimator(); if (animator != null) { if (animator.getContentOverlay() != null) { removeContentOverlay(animator.getContentOverlay(), animator::clearContentOverlay); if (animator.getContentOverlayLeash() != null) { removeContentOverlay(animator.getContentOverlayLeash(), animator::clearContentOverlay); } animator.removeAllUpdateListeners(); animator.removeAllListeners(); Loading Loading @@ -1491,7 +1493,17 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, if (isInPipDirection(direction)) { // Similar to auto-enter-pip transition, we use content overlay when there is no // source rect hint to enter PiP use bounds animation. if (sourceHintRect == null) animator.setUseContentOverlay(mContext); if (sourceHintRect == null) { animator.setColorContentOverlay(mContext); } else { final TaskSnapshot snapshot = PipUtils.getTaskSnapshot( mTaskInfo.launchIntoPipHostTaskId, false /* isLowResolution */); if (snapshot != null) { // use the task snapshot during the animation, this is for // launch-into-pip aka. content-pip use case. animator.setSnapshotContentOverlay(snapshot, sourceHintRect); } } // The destination bounds are used for the end rect of animation and the final bounds // after animation finishes. So after the animation is started, the destination bounds // can be updated to new rotation (computeRotatedBounds has changed the DisplayLayout Loading Loading @@ -1555,7 +1567,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, */ void fadeOutAndRemoveOverlay(SurfaceControl surface, Runnable callback, boolean withStartDelay) { if (surface == null) { if (surface == null || !surface.isValid()) { return; } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java +1 −1 Original line number Diff line number Diff line Loading @@ -709,7 +709,7 @@ public class PipTransition extends PipTransitionController { if (sourceHintRect == null) { // We use content overlay when there is no source rect hint to enter PiP use bounds // animation. animator.setUseContentOverlay(mContext); animator.setColorContentOverlay(mContext); } } else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) { startTransaction.setAlpha(leash, 0f); Loading