Loading packages/SystemUI/res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -477,6 +477,9 @@ <!-- Allow PIP to resize to a slightly bigger state upon touch/showing the menu --> <bool name="config_pipEnableResizeForMenu">true</bool> <!-- Allow PIP to enable round corner, see also R.dimen.pip_corner_radius --> <bool name="config_pipEnableRoundCorner">false</bool> <!-- SystemUI Plugins that can be loaded on user builds. --> <string-array name="config_pluginWhitelist" translatable="false"> <item>com.android.systemui</item> Loading packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java +28 −29 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import javax.inject.Inject; /** * Controller class of PiP animations (both from and to PiP mode). */ Loading Loading @@ -62,12 +64,15 @@ public class PipAnimationController { @interface TransitionDirection {} private final Interpolator mFastOutSlowInInterpolator; private final PipSurfaceTransactionHelper mSurfaceTransactionHelper; private PipTransitionAnimator mCurrentAnimator; PipAnimationController(Context context) { @Inject PipAnimationController(Context context, PipSurfaceTransactionHelper helper) { mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, com.android.internal.R.interpolator.fast_out_slow_in); mSurfaceTransactionHelper = helper; } @SuppressWarnings("unchecked") Loading Loading @@ -110,6 +115,7 @@ public class PipAnimationController { } private PipTransitionAnimator setupPipTransitionAnimator(PipTransitionAnimator animator) { animator.setSurfaceTransactionHelper(mSurfaceTransactionHelper); animator.setInterpolator(mFastOutSlowInInterpolator); animator.setFloatValues(FRACTION_START, FRACTION_END); return animator; Loading Loading @@ -151,9 +157,10 @@ public class PipAnimationController { private T mEndValue; private T mCurrentValue; private PipAnimationCallback mPipAnimationCallback; private SurfaceControlTransactionFactory mSurfaceControlTransactionFactory; private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory mSurfaceControlTransactionFactory; private PipSurfaceTransactionHelper mSurfaceTransactionHelper; private @TransitionDirection int mTransitionDirection; private int mCornerRadius; private PipTransitionAnimator(SurfaceControl leash, @AnimationType int animationType, Rect destinationBounds, T startValue, T endValue) { Loading Loading @@ -242,15 +249,6 @@ public class PipAnimationController { mCurrentValue = value; } int getCornerRadius() { return mCornerRadius; } PipTransitionAnimator<T> setCornerRadius(int cornerRadius) { mCornerRadius = cornerRadius; return this; } boolean shouldApplyCornerRadius() { return mTransitionDirection != TRANSITION_DIRECTION_TO_FULLSCREEN; } Loading @@ -273,10 +271,19 @@ public class PipAnimationController { } @VisibleForTesting void setSurfaceControlTransactionFactory(SurfaceControlTransactionFactory factory) { void setSurfaceControlTransactionFactory( PipSurfaceTransactionHelper.SurfaceControlTransactionFactory factory) { mSurfaceControlTransactionFactory = factory; } PipSurfaceTransactionHelper getSurfaceTransactionHelper() { return mSurfaceTransactionHelper; } void setSurfaceTransactionHelper(PipSurfaceTransactionHelper helper) { mSurfaceTransactionHelper = helper; } abstract void applySurfaceControlTransaction(SurfaceControl leash, SurfaceControl.Transaction tx, float fraction); Loading @@ -289,14 +296,11 @@ public class PipAnimationController { SurfaceControl.Transaction tx, float fraction) { final float alpha = getStartValue() * (1 - fraction) + getEndValue() * fraction; setCurrentValue(alpha); tx.setAlpha(leash, alpha); getSurfaceTransactionHelper().alpha(tx, leash, alpha); if (Float.compare(fraction, FRACTION_START) == 0) { // Ensure the start condition final Rect bounds = getDestinationBounds(); tx.setPosition(leash, bounds.left, bounds.top) .setWindowCrop(leash, bounds.width(), bounds.height()); tx.setCornerRadius(leash, shouldApplyCornerRadius() ? getCornerRadius() : 0); getSurfaceTransactionHelper() .crop(tx, leash, getDestinationBounds()) .round(tx, leash, shouldApplyCornerRadius()); } tx.apply(); } Loading Loading @@ -325,21 +329,16 @@ public class PipAnimationController { getCastedFractionValue(start.right, end.right, fraction), getCastedFractionValue(start.bottom, end.bottom, fraction)); setCurrentValue(mTmpRect); tx.setPosition(leash, mTmpRect.left, mTmpRect.top) .setWindowCrop(leash, mTmpRect.width(), mTmpRect.height()); getSurfaceTransactionHelper().crop(tx, leash, mTmpRect); if (Float.compare(fraction, FRACTION_START) == 0) { // Ensure the start condition tx.setAlpha(leash, 1f); tx.setCornerRadius(leash, shouldApplyCornerRadius() ? getCornerRadius() : 0); getSurfaceTransactionHelper() .alpha(tx, leash, 1f) .round(tx, leash, shouldApplyCornerRadius()); } tx.apply(); } }; } } interface SurfaceControlTransactionFactory { SurfaceControl.Transaction getTransaction(); } } packages/SystemUI/src/com/android/systemui/pip/PipSurfaceTransactionHelper.java 0 → 100644 +81 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.systemui.pip; import android.content.Context; import android.content.res.Resources; import android.graphics.Rect; import android.view.SurfaceControl; import com.android.systemui.R; import javax.inject.Inject; import javax.inject.Singleton; /** * Abstracts the common operations on {@link SurfaceControl.Transaction} for PiP transition. */ @Singleton public class PipSurfaceTransactionHelper { private final boolean mEnableCornerRadius; private final int mCornerRadius; @Inject public PipSurfaceTransactionHelper(Context context) { final Resources res = context.getResources(); mEnableCornerRadius = res.getBoolean(R.bool.config_pipEnableRoundCorner); mCornerRadius = res.getDimensionPixelSize(R.dimen.pip_corner_radius); } /** * Operates the alpha on a given transaction and leash * @return same {@link PipSurfaceTransactionHelper} instance for method chaining */ PipSurfaceTransactionHelper alpha(SurfaceControl.Transaction tx, SurfaceControl leash, float alpha) { tx.setAlpha(leash, alpha); return this; } /** * Operates the crop (and position) on a given transaction and leash * @return same {@link PipSurfaceTransactionHelper} instance for method chaining */ PipSurfaceTransactionHelper crop(SurfaceControl.Transaction tx, SurfaceControl leash, Rect destinationBounds) { tx.setWindowCrop(leash, destinationBounds.width(), destinationBounds.height()) .setPosition(leash, destinationBounds.left, destinationBounds.top); return this; } /** * Operates the round corner radius on a given transaction and leash * @return same {@link PipSurfaceTransactionHelper} instance for method chaining */ PipSurfaceTransactionHelper round(SurfaceControl.Transaction tx, SurfaceControl leash, boolean applyCornerRadius) { if (mEnableCornerRadius) { tx.setCornerRadius(leash, applyCornerRadius ? mCornerRadius : 0); } return this; } interface SurfaceControlTransactionFactory { SurfaceControl.Transaction getTransaction(); } } packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +20 −29 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ import android.app.PictureInPictureParams; import android.content.Context; import android.graphics.Rect; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.util.Log; Loading @@ -46,9 +45,7 @@ import com.android.systemui.R; import com.android.systemui.pip.phone.PipUpdateThread; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.function.Consumer; Loading Loading @@ -78,9 +75,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { private final PipAnimationController mPipAnimationController; private final List<PipTransitionCallback> mPipTransitionCallbacks = new ArrayList<>(); private final Rect mLastReportedBounds = new Rect(); private final int mCornerRadius; private final Map<IBinder, Rect> mBoundsToRestore = new HashMap<>(); private final int mEnterExitAnimationDuration; private final PipSurfaceTransactionHelper mSurfaceTransactionHelper; // These callbacks are called on the update thread private final PipAnimationController.PipAnimationCallback mPipAnimationCallback = Loading Loading @@ -172,16 +168,20 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { private SurfaceControl mLeash; private boolean mInPip; private @PipAnimationController.AnimationType int mOneShotAnimationType = ANIM_TYPE_BOUNDS; private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory mSurfaceControlTransactionFactory; public PipTaskOrganizer(Context context, @NonNull PipBoundsHandler boundsHandler) { public PipTaskOrganizer(Context context, @NonNull PipBoundsHandler boundsHandler, @NonNull PipSurfaceTransactionHelper surfaceTransactionHelper) { mMainHandler = new Handler(Looper.getMainLooper()); mUpdateHandler = new Handler(PipUpdateThread.get().getLooper(), mUpdateCallbacks); mTaskOrganizerController = ActivityTaskManager.getTaskOrganizerController(); mPipBoundsHandler = boundsHandler; mPipAnimationController = new PipAnimationController(context); mCornerRadius = context.getResources().getDimensionPixelSize(R.dimen.pip_corner_radius); mEnterExitAnimationDuration = context.getResources() .getInteger(R.integer.config_pipResizeAnimationDuration); mSurfaceTransactionHelper = surfaceTransactionHelper; mPipAnimationController = new PipAnimationController(context, surfaceTransactionHelper); mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new; } public Handler getUpdateHandler() { Loading Loading @@ -234,7 +234,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { throw new RuntimeException("Unable to get leash", e); } final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds(); mBoundsToRestore.put(mToken.asBinder(), currentBounds); if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) { scheduleAnimateResizePip(currentBounds, destinationBounds, TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration, null); Loading @@ -242,7 +241,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { mUpdateHandler.post(() -> mPipAnimationController .getAnimator(mLeash, destinationBounds, 0f, 1f) .setTransitionDirection(TRANSITION_DIRECTION_TO_PIP) .setCornerRadius(mCornerRadius) .setPipAnimationCallback(mPipAnimationCallback) .setDuration(mEnterExitAnimationDuration) .start()); Loading @@ -260,8 +258,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { Log.wtf(TAG, "Unrecognized token: " + token); return; } final Rect boundsToRestore = mBoundsToRestore.remove(mToken.asBinder()); scheduleAnimateResizePip(mLastReportedBounds, boundsToRestore, scheduleAnimateResizePip(mLastReportedBounds, info.configuration.windowConfiguration.getBounds(), TRANSITION_DIRECTION_TO_FULLSCREEN, mEnterExitAnimationDuration, null); mInPip = false; } Loading Loading @@ -307,7 +305,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { private void scheduleAnimateResizePip(Rect currentBounds, Rect destinationBounds, @PipAnimationController.TransitionDirection int direction, int durationMs, Consumer<Rect> updateBoundsCallback) { Objects.requireNonNull(mToken, "Requires valid IWindowContainer"); if (!mInPip) { // Ignore animation when we are no longer in PIP return; Loading @@ -326,7 +323,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { * {@link WindowContainerTransaction} until {@link #scheduleFinishResizePip} is called. */ public void scheduleResizePip(Rect toBounds, Consumer<Rect> updateBoundsCallback) { Objects.requireNonNull(mToken, "Requires valid IWindowContainer"); SomeArgs args = SomeArgs.obtain(); args.arg1 = updateBoundsCallback; args.arg2 = toBounds; Loading @@ -334,22 +330,20 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { } /** * Finish a intermediate resize operation. This is expected to be called after * Finish an intermediate resize operation. This is expected to be called after * {@link #scheduleResizePip}. */ public void scheduleFinishResizePip(Rect destinationBounds) { Objects.requireNonNull(mToken, "Requires valid IWindowContainer"); SurfaceControl.Transaction tx = new SurfaceControl.Transaction() .setPosition(mLeash, destinationBounds.left, destinationBounds.top) .setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height()) .setCornerRadius(mLeash, mInPip ? mCornerRadius : 0); final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); mSurfaceTransactionHelper .crop(tx, mLeash, destinationBounds) .round(tx, mLeash, mInPip); scheduleFinishResizePip(tx, destinationBounds, TRANSITION_DIRECTION_NONE, null); } private void scheduleFinishResizePip(SurfaceControl.Transaction tx, Rect destinationBounds, @PipAnimationController.TransitionDirection int direction, Consumer<Rect> updateBoundsCallback) { Objects.requireNonNull(mToken, "Requires valid IWindowContainer"); SomeArgs args = SomeArgs.obtain(); args.arg1 = updateBoundsCallback; args.arg2 = tx; Loading @@ -367,7 +361,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { // Ignore offsets when we are no longer in PIP return; } Objects.requireNonNull(mToken, "Requires valid IWindowContainer"); SomeArgs args = SomeArgs.obtain(); args.arg1 = updateBoundsCallback; args.arg2 = originalBounds; Loading Loading @@ -396,17 +389,16 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { throw new RuntimeException("Callers should call scheduleResizePip() instead of this " + "directly"); } Objects.requireNonNull(mToken, "Requires valid IWindowContainer"); // Could happen when dismissPip if (mToken == null || mLeash == null) { Log.w(TAG, "Abort animation, invalid leash"); return; } new SurfaceControl.Transaction() .setPosition(mLeash, destinationBounds.left, destinationBounds.top) .setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height()) .setCornerRadius(mLeash, mInPip ? mCornerRadius : 0) .apply(); final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); mSurfaceTransactionHelper .crop(tx, mLeash, destinationBounds) .round(tx, mLeash, mInPip); tx.apply(); } private void finishResize(SurfaceControl.Transaction tx, Rect destinationBounds, Loading Loading @@ -449,7 +441,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { mUpdateHandler.post(() -> mPipAnimationController .getAnimator(mLeash, currentBounds, destinationBounds) .setTransitionDirection(direction) .setCornerRadius(mCornerRadius) .setPipAnimationCallback(mPipAnimationCallback) .setDuration(durationMs) .start()); Loading packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +5 −2 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.pip.BasePipManager; import com.android.systemui.pip.PipBoundsHandler; import com.android.systemui.pip.PipSnapAlgorithm; import com.android.systemui.pip.PipSurfaceTransactionHelper; import com.android.systemui.pip.PipTaskOrganizer; import com.android.systemui.shared.recents.IPinnedStackAnimationListener; import com.android.systemui.shared.system.ActivityManagerWrapper; Loading Loading @@ -210,7 +211,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio FloatingContentCoordinator floatingContentCoordinator, DeviceConfigProxy deviceConfig, PipBoundsHandler pipBoundsHandler, PipSnapAlgorithm pipSnapAlgorithm) { PipSnapAlgorithm pipSnapAlgorithm, PipSurfaceTransactionHelper surfaceTransactionHelper) { mContext = context; mActivityManager = ActivityManager.getService(); Loading @@ -224,7 +226,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio final IActivityTaskManager activityTaskManager = ActivityTaskManager.getService(); mPipBoundsHandler = pipBoundsHandler; mPipTaskOrganizer = new PipTaskOrganizer(mContext, mPipBoundsHandler); mPipTaskOrganizer = new PipTaskOrganizer(context, pipBoundsHandler, surfaceTransactionHelper); mPipTaskOrganizer.registerPipTransitionCallback(this); mInputConsumerController = InputConsumerController.getPipInputConsumer(); mMediaController = new PipMediaController(context, mActivityManager, broadcastDispatcher); Loading Loading
packages/SystemUI/res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -477,6 +477,9 @@ <!-- Allow PIP to resize to a slightly bigger state upon touch/showing the menu --> <bool name="config_pipEnableResizeForMenu">true</bool> <!-- Allow PIP to enable round corner, see also R.dimen.pip_corner_radius --> <bool name="config_pipEnableRoundCorner">false</bool> <!-- SystemUI Plugins that can be loaded on user builds. --> <string-array name="config_pluginWhitelist" translatable="false"> <item>com.android.systemui</item> Loading
packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java +28 −29 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import javax.inject.Inject; /** * Controller class of PiP animations (both from and to PiP mode). */ Loading Loading @@ -62,12 +64,15 @@ public class PipAnimationController { @interface TransitionDirection {} private final Interpolator mFastOutSlowInInterpolator; private final PipSurfaceTransactionHelper mSurfaceTransactionHelper; private PipTransitionAnimator mCurrentAnimator; PipAnimationController(Context context) { @Inject PipAnimationController(Context context, PipSurfaceTransactionHelper helper) { mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, com.android.internal.R.interpolator.fast_out_slow_in); mSurfaceTransactionHelper = helper; } @SuppressWarnings("unchecked") Loading Loading @@ -110,6 +115,7 @@ public class PipAnimationController { } private PipTransitionAnimator setupPipTransitionAnimator(PipTransitionAnimator animator) { animator.setSurfaceTransactionHelper(mSurfaceTransactionHelper); animator.setInterpolator(mFastOutSlowInInterpolator); animator.setFloatValues(FRACTION_START, FRACTION_END); return animator; Loading Loading @@ -151,9 +157,10 @@ public class PipAnimationController { private T mEndValue; private T mCurrentValue; private PipAnimationCallback mPipAnimationCallback; private SurfaceControlTransactionFactory mSurfaceControlTransactionFactory; private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory mSurfaceControlTransactionFactory; private PipSurfaceTransactionHelper mSurfaceTransactionHelper; private @TransitionDirection int mTransitionDirection; private int mCornerRadius; private PipTransitionAnimator(SurfaceControl leash, @AnimationType int animationType, Rect destinationBounds, T startValue, T endValue) { Loading Loading @@ -242,15 +249,6 @@ public class PipAnimationController { mCurrentValue = value; } int getCornerRadius() { return mCornerRadius; } PipTransitionAnimator<T> setCornerRadius(int cornerRadius) { mCornerRadius = cornerRadius; return this; } boolean shouldApplyCornerRadius() { return mTransitionDirection != TRANSITION_DIRECTION_TO_FULLSCREEN; } Loading @@ -273,10 +271,19 @@ public class PipAnimationController { } @VisibleForTesting void setSurfaceControlTransactionFactory(SurfaceControlTransactionFactory factory) { void setSurfaceControlTransactionFactory( PipSurfaceTransactionHelper.SurfaceControlTransactionFactory factory) { mSurfaceControlTransactionFactory = factory; } PipSurfaceTransactionHelper getSurfaceTransactionHelper() { return mSurfaceTransactionHelper; } void setSurfaceTransactionHelper(PipSurfaceTransactionHelper helper) { mSurfaceTransactionHelper = helper; } abstract void applySurfaceControlTransaction(SurfaceControl leash, SurfaceControl.Transaction tx, float fraction); Loading @@ -289,14 +296,11 @@ public class PipAnimationController { SurfaceControl.Transaction tx, float fraction) { final float alpha = getStartValue() * (1 - fraction) + getEndValue() * fraction; setCurrentValue(alpha); tx.setAlpha(leash, alpha); getSurfaceTransactionHelper().alpha(tx, leash, alpha); if (Float.compare(fraction, FRACTION_START) == 0) { // Ensure the start condition final Rect bounds = getDestinationBounds(); tx.setPosition(leash, bounds.left, bounds.top) .setWindowCrop(leash, bounds.width(), bounds.height()); tx.setCornerRadius(leash, shouldApplyCornerRadius() ? getCornerRadius() : 0); getSurfaceTransactionHelper() .crop(tx, leash, getDestinationBounds()) .round(tx, leash, shouldApplyCornerRadius()); } tx.apply(); } Loading Loading @@ -325,21 +329,16 @@ public class PipAnimationController { getCastedFractionValue(start.right, end.right, fraction), getCastedFractionValue(start.bottom, end.bottom, fraction)); setCurrentValue(mTmpRect); tx.setPosition(leash, mTmpRect.left, mTmpRect.top) .setWindowCrop(leash, mTmpRect.width(), mTmpRect.height()); getSurfaceTransactionHelper().crop(tx, leash, mTmpRect); if (Float.compare(fraction, FRACTION_START) == 0) { // Ensure the start condition tx.setAlpha(leash, 1f); tx.setCornerRadius(leash, shouldApplyCornerRadius() ? getCornerRadius() : 0); getSurfaceTransactionHelper() .alpha(tx, leash, 1f) .round(tx, leash, shouldApplyCornerRadius()); } tx.apply(); } }; } } interface SurfaceControlTransactionFactory { SurfaceControl.Transaction getTransaction(); } }
packages/SystemUI/src/com/android/systemui/pip/PipSurfaceTransactionHelper.java 0 → 100644 +81 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.systemui.pip; import android.content.Context; import android.content.res.Resources; import android.graphics.Rect; import android.view.SurfaceControl; import com.android.systemui.R; import javax.inject.Inject; import javax.inject.Singleton; /** * Abstracts the common operations on {@link SurfaceControl.Transaction} for PiP transition. */ @Singleton public class PipSurfaceTransactionHelper { private final boolean mEnableCornerRadius; private final int mCornerRadius; @Inject public PipSurfaceTransactionHelper(Context context) { final Resources res = context.getResources(); mEnableCornerRadius = res.getBoolean(R.bool.config_pipEnableRoundCorner); mCornerRadius = res.getDimensionPixelSize(R.dimen.pip_corner_radius); } /** * Operates the alpha on a given transaction and leash * @return same {@link PipSurfaceTransactionHelper} instance for method chaining */ PipSurfaceTransactionHelper alpha(SurfaceControl.Transaction tx, SurfaceControl leash, float alpha) { tx.setAlpha(leash, alpha); return this; } /** * Operates the crop (and position) on a given transaction and leash * @return same {@link PipSurfaceTransactionHelper} instance for method chaining */ PipSurfaceTransactionHelper crop(SurfaceControl.Transaction tx, SurfaceControl leash, Rect destinationBounds) { tx.setWindowCrop(leash, destinationBounds.width(), destinationBounds.height()) .setPosition(leash, destinationBounds.left, destinationBounds.top); return this; } /** * Operates the round corner radius on a given transaction and leash * @return same {@link PipSurfaceTransactionHelper} instance for method chaining */ PipSurfaceTransactionHelper round(SurfaceControl.Transaction tx, SurfaceControl leash, boolean applyCornerRadius) { if (mEnableCornerRadius) { tx.setCornerRadius(leash, applyCornerRadius ? mCornerRadius : 0); } return this; } interface SurfaceControlTransactionFactory { SurfaceControl.Transaction getTransaction(); } }
packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +20 −29 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ import android.app.PictureInPictureParams; import android.content.Context; import android.graphics.Rect; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.util.Log; Loading @@ -46,9 +45,7 @@ import com.android.systemui.R; import com.android.systemui.pip.phone.PipUpdateThread; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.function.Consumer; Loading Loading @@ -78,9 +75,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { private final PipAnimationController mPipAnimationController; private final List<PipTransitionCallback> mPipTransitionCallbacks = new ArrayList<>(); private final Rect mLastReportedBounds = new Rect(); private final int mCornerRadius; private final Map<IBinder, Rect> mBoundsToRestore = new HashMap<>(); private final int mEnterExitAnimationDuration; private final PipSurfaceTransactionHelper mSurfaceTransactionHelper; // These callbacks are called on the update thread private final PipAnimationController.PipAnimationCallback mPipAnimationCallback = Loading Loading @@ -172,16 +168,20 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { private SurfaceControl mLeash; private boolean mInPip; private @PipAnimationController.AnimationType int mOneShotAnimationType = ANIM_TYPE_BOUNDS; private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory mSurfaceControlTransactionFactory; public PipTaskOrganizer(Context context, @NonNull PipBoundsHandler boundsHandler) { public PipTaskOrganizer(Context context, @NonNull PipBoundsHandler boundsHandler, @NonNull PipSurfaceTransactionHelper surfaceTransactionHelper) { mMainHandler = new Handler(Looper.getMainLooper()); mUpdateHandler = new Handler(PipUpdateThread.get().getLooper(), mUpdateCallbacks); mTaskOrganizerController = ActivityTaskManager.getTaskOrganizerController(); mPipBoundsHandler = boundsHandler; mPipAnimationController = new PipAnimationController(context); mCornerRadius = context.getResources().getDimensionPixelSize(R.dimen.pip_corner_radius); mEnterExitAnimationDuration = context.getResources() .getInteger(R.integer.config_pipResizeAnimationDuration); mSurfaceTransactionHelper = surfaceTransactionHelper; mPipAnimationController = new PipAnimationController(context, surfaceTransactionHelper); mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new; } public Handler getUpdateHandler() { Loading Loading @@ -234,7 +234,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { throw new RuntimeException("Unable to get leash", e); } final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds(); mBoundsToRestore.put(mToken.asBinder(), currentBounds); if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) { scheduleAnimateResizePip(currentBounds, destinationBounds, TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration, null); Loading @@ -242,7 +241,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { mUpdateHandler.post(() -> mPipAnimationController .getAnimator(mLeash, destinationBounds, 0f, 1f) .setTransitionDirection(TRANSITION_DIRECTION_TO_PIP) .setCornerRadius(mCornerRadius) .setPipAnimationCallback(mPipAnimationCallback) .setDuration(mEnterExitAnimationDuration) .start()); Loading @@ -260,8 +258,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { Log.wtf(TAG, "Unrecognized token: " + token); return; } final Rect boundsToRestore = mBoundsToRestore.remove(mToken.asBinder()); scheduleAnimateResizePip(mLastReportedBounds, boundsToRestore, scheduleAnimateResizePip(mLastReportedBounds, info.configuration.windowConfiguration.getBounds(), TRANSITION_DIRECTION_TO_FULLSCREEN, mEnterExitAnimationDuration, null); mInPip = false; } Loading Loading @@ -307,7 +305,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { private void scheduleAnimateResizePip(Rect currentBounds, Rect destinationBounds, @PipAnimationController.TransitionDirection int direction, int durationMs, Consumer<Rect> updateBoundsCallback) { Objects.requireNonNull(mToken, "Requires valid IWindowContainer"); if (!mInPip) { // Ignore animation when we are no longer in PIP return; Loading @@ -326,7 +323,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { * {@link WindowContainerTransaction} until {@link #scheduleFinishResizePip} is called. */ public void scheduleResizePip(Rect toBounds, Consumer<Rect> updateBoundsCallback) { Objects.requireNonNull(mToken, "Requires valid IWindowContainer"); SomeArgs args = SomeArgs.obtain(); args.arg1 = updateBoundsCallback; args.arg2 = toBounds; Loading @@ -334,22 +330,20 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { } /** * Finish a intermediate resize operation. This is expected to be called after * Finish an intermediate resize operation. This is expected to be called after * {@link #scheduleResizePip}. */ public void scheduleFinishResizePip(Rect destinationBounds) { Objects.requireNonNull(mToken, "Requires valid IWindowContainer"); SurfaceControl.Transaction tx = new SurfaceControl.Transaction() .setPosition(mLeash, destinationBounds.left, destinationBounds.top) .setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height()) .setCornerRadius(mLeash, mInPip ? mCornerRadius : 0); final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); mSurfaceTransactionHelper .crop(tx, mLeash, destinationBounds) .round(tx, mLeash, mInPip); scheduleFinishResizePip(tx, destinationBounds, TRANSITION_DIRECTION_NONE, null); } private void scheduleFinishResizePip(SurfaceControl.Transaction tx, Rect destinationBounds, @PipAnimationController.TransitionDirection int direction, Consumer<Rect> updateBoundsCallback) { Objects.requireNonNull(mToken, "Requires valid IWindowContainer"); SomeArgs args = SomeArgs.obtain(); args.arg1 = updateBoundsCallback; args.arg2 = tx; Loading @@ -367,7 +361,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { // Ignore offsets when we are no longer in PIP return; } Objects.requireNonNull(mToken, "Requires valid IWindowContainer"); SomeArgs args = SomeArgs.obtain(); args.arg1 = updateBoundsCallback; args.arg2 = originalBounds; Loading Loading @@ -396,17 +389,16 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { throw new RuntimeException("Callers should call scheduleResizePip() instead of this " + "directly"); } Objects.requireNonNull(mToken, "Requires valid IWindowContainer"); // Could happen when dismissPip if (mToken == null || mLeash == null) { Log.w(TAG, "Abort animation, invalid leash"); return; } new SurfaceControl.Transaction() .setPosition(mLeash, destinationBounds.left, destinationBounds.top) .setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height()) .setCornerRadius(mLeash, mInPip ? mCornerRadius : 0) .apply(); final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); mSurfaceTransactionHelper .crop(tx, mLeash, destinationBounds) .round(tx, mLeash, mInPip); tx.apply(); } private void finishResize(SurfaceControl.Transaction tx, Rect destinationBounds, Loading Loading @@ -449,7 +441,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { mUpdateHandler.post(() -> mPipAnimationController .getAnimator(mLeash, currentBounds, destinationBounds) .setTransitionDirection(direction) .setCornerRadius(mCornerRadius) .setPipAnimationCallback(mPipAnimationCallback) .setDuration(durationMs) .start()); Loading
packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +5 −2 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.pip.BasePipManager; import com.android.systemui.pip.PipBoundsHandler; import com.android.systemui.pip.PipSnapAlgorithm; import com.android.systemui.pip.PipSurfaceTransactionHelper; import com.android.systemui.pip.PipTaskOrganizer; import com.android.systemui.shared.recents.IPinnedStackAnimationListener; import com.android.systemui.shared.system.ActivityManagerWrapper; Loading Loading @@ -210,7 +211,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio FloatingContentCoordinator floatingContentCoordinator, DeviceConfigProxy deviceConfig, PipBoundsHandler pipBoundsHandler, PipSnapAlgorithm pipSnapAlgorithm) { PipSnapAlgorithm pipSnapAlgorithm, PipSurfaceTransactionHelper surfaceTransactionHelper) { mContext = context; mActivityManager = ActivityManager.getService(); Loading @@ -224,7 +226,8 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio final IActivityTaskManager activityTaskManager = ActivityTaskManager.getService(); mPipBoundsHandler = pipBoundsHandler; mPipTaskOrganizer = new PipTaskOrganizer(mContext, mPipBoundsHandler); mPipTaskOrganizer = new PipTaskOrganizer(context, pipBoundsHandler, surfaceTransactionHelper); mPipTaskOrganizer.registerPipTransitionCallback(this); mInputConsumerController = InputConsumerController.getPipInputConsumer(); mMediaController = new PipMediaController(context, mActivityManager, broadcastDispatcher); Loading