Merge "Update config ordering when entering/leaving pip" into rvc-dev am: d8fb783389

Change-Id: Iac736f444b9330784a0b84c49a40e226b8c4eec9
This commit is contained in:
Winson Chung
2020-05-14 20:26:46 +00:00
committed by Automerger Merge Worker
12 changed files with 199 additions and 88 deletions

View File

@@ -65,6 +65,10 @@ public class PipAnimationController {
@Retention(RetentionPolicy.SOURCE)
public @interface TransitionDirection {}
public static boolean isInPipDirection(@TransitionDirection int direction) {
return direction == TRANSITION_DIRECTION_TO_PIP;
}
public static boolean isOutPipDirection(@TransitionDirection int direction) {
return direction == TRANSITION_DIRECTION_TO_FULLSCREEN
|| direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN;
@@ -104,6 +108,12 @@ public class PipAnimationController {
if (mCurrentAnimator == null) {
mCurrentAnimator = setupPipTransitionAnimator(
PipTransitionAnimator.ofBounds(leash, startBounds, endBounds));
} else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_ALPHA
&& mCurrentAnimator.isRunning()) {
// If we are still animating the fade into pip, then just move the surface and ensure
// we update with the new destination bounds, but don't interrupt the existing animation
// with a new bounds
mCurrentAnimator.setDestinationBounds(endBounds);
} else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_BOUNDS
&& mCurrentAnimator.isRunning()) {
mCurrentAnimator.setDestinationBounds(endBounds);
@@ -265,8 +275,7 @@ public class PipAnimationController {
boolean inScaleTransition() {
if (mAnimationType != ANIM_TYPE_BOUNDS) return false;
final int direction = getTransitionDirection();
return !isOutPipDirection(direction) && direction != TRANSITION_DIRECTION_TO_PIP;
return !isInPipDirection(getTransitionDirection());
}
/**
@@ -354,7 +363,11 @@ public class PipAnimationController {
getCastedFractionValue(start.bottom, end.bottom, fraction));
setCurrentValue(mTmpRect);
if (inScaleTransition()) {
getSurfaceTransactionHelper().scale(tx, leash, start, mTmpRect);
if (isOutPipDirection(getTransitionDirection())) {
getSurfaceTransactionHelper().scale(tx, leash, end, mTmpRect);
} else {
getSurfaceTransactionHelper().scale(tx, leash, start, mTmpRect);
}
} else {
getSurfaceTransactionHelper().crop(tx, leash, mTmpRect);
}

View File

@@ -209,6 +209,10 @@ public class PipBoundsHandler {
return new Rect(0, 0, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
}
public int getDisplayRotation() {
return mDisplayInfo.rotation;
}
/**
* Responds to IPinnedStackListener on {@link DisplayInfo} change.
* It will normally follow up with a

View File

@@ -16,6 +16,9 @@
package com.android.systemui.pip;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_ALPHA;
@@ -25,25 +28,30 @@ import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTI
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_FULLSCREEN;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_SPLIT_SCREEN;
import static com.android.systemui.pip.PipAnimationController.isInPipDirection;
import static com.android.systemui.pip.PipAnimationController.isOutPipDirection;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.PictureInPictureParams;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
import android.util.Size;
import android.view.SurfaceControl;
import android.window.TaskOrganizer;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import android.window.WindowContainerTransactionCallback;
import android.window.WindowOrganizer;
import com.android.internal.os.SomeArgs;
@@ -51,6 +59,7 @@ import com.android.systemui.R;
import com.android.systemui.pip.phone.PipUpdateThread;
import com.android.systemui.stackdivider.Divider;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -90,7 +99,7 @@ public class PipTaskOrganizer extends TaskOrganizer {
private final Rect mLastReportedBounds = new Rect();
private final int mEnterExitAnimationDuration;
private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
private final Map<IBinder, Rect> mBoundsToRestore = new HashMap<>();
private final Map<IBinder, Configuration> mInitialState = new HashMap<>();
private final Divider mSplitDivider;
// These callbacks are called on the update thread
@@ -110,7 +119,8 @@ public class PipTaskOrganizer extends TaskOrganizer {
@Override
public void onPipAnimationEnd(SurfaceControl.Transaction tx,
PipAnimationController.PipTransitionAnimator animator) {
finishResize(tx, animator.getDestinationBounds(), animator.getTransitionDirection());
finishResize(tx, animator.getDestinationBounds(), animator.getTransitionDirection(),
animator.getAnimationType());
mMainHandler.post(() -> {
for (int i = mPipTransitionCallbacks.size() - 1; i >= 0; i--) {
final PipTransitionCallback callback = mPipTransitionCallbacks.get(i);
@@ -170,7 +180,7 @@ public class PipTaskOrganizer extends TaskOrganizer {
case MSG_FINISH_RESIZE: {
SurfaceControl.Transaction tx = (SurfaceControl.Transaction) args.arg2;
Rect toBounds = (Rect) args.arg3;
finishResize(tx, toBounds, args.argi1 /* direction */);
finishResize(tx, toBounds, args.argi1 /* direction */, -1);
if (updateBoundsCallback != null) {
updateBoundsCallback.accept(toBounds);
}
@@ -240,28 +250,76 @@ public class PipTaskOrganizer extends TaskOrganizer {
}
/**
* Dismiss PiP, this is done in two phases using {@link WindowContainerTransaction}
* - setActivityWindowingMode to undefined at beginning of the transaction. without changing
* the windowing mode of the Task itself. This makes sure the activity render it's final
* configuration while the Task is still in PiP.
* Expands PiP to the previous bounds, this is done in two phases using
* {@link WindowContainerTransaction}
* - setActivityWindowingMode to either fullscreen or split-secondary at beginning of the
* transaction. without changing the windowing mode of the Task itself. This makes sure the
* activity render it's final configuration while the Task is still in PiP.
* - setWindowingMode to undefined at the end of transition
* @param animationDurationMs duration in millisecond for the exiting PiP transition
*/
public void dismissPip(int animationDurationMs) {
public void exitPip(int animationDurationMs) {
if (!mInPip || mToken == null) {
Log.wtf(TAG, "Not allowed to dismissPip in current state"
Log.wtf(TAG, "Not allowed to exitPip in current state"
+ " mInPip=" + mInPip + " mToken=" + mToken);
return;
}
final Configuration initialConfig = mInitialState.remove(mToken.asBinder());
final boolean orientationDiffers = initialConfig.windowConfiguration.getRotation()
!= mPipBoundsHandler.getDisplayRotation();
final WindowContainerTransaction wct = new WindowContainerTransaction();
wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
WindowOrganizer.applyTransaction(wct);
final Rect destinationBounds = mBoundsToRestore.remove(mToken.asBinder());
final int direction = syncWithSplitScreenBounds(destinationBounds)
? TRANSITION_DIRECTION_TO_SPLIT_SCREEN : TRANSITION_DIRECTION_TO_FULLSCREEN;
scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
direction, animationDurationMs, null /* updateBoundsCallback */);
mInPip = false;
if (orientationDiffers) {
// Don't bother doing an animation if the display rotation differs or if it's in
// a non-supported windowing mode
wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
WindowOrganizer.applyTransaction(wct);
mInPip = false;
} else {
final Rect destinationBounds = initialConfig.windowConfiguration.getBounds();
final int direction = syncWithSplitScreenBounds(destinationBounds)
? TRANSITION_DIRECTION_TO_SPLIT_SCREEN
: TRANSITION_DIRECTION_TO_FULLSCREEN;
final SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
mSurfaceTransactionHelper.scale(tx, mLeash, destinationBounds,
mLastReportedBounds);
tx.setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height());
wct.setActivityWindowingMode(mToken, direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN
? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
: WINDOWING_MODE_FULLSCREEN);
wct.setBounds(mToken, destinationBounds);
wct.setBoundsChangeTransaction(mToken, tx);
applySyncTransaction(wct, new WindowContainerTransactionCallback() {
@Override
public void onTransactionReady(int id, SurfaceControl.Transaction t) {
t.apply();
scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
direction, animationDurationMs, null /* updateBoundsCallback */);
mInPip = false;
}
});
}
}
/**
* Removes PiP immediately.
*/
public void removePip() {
if (!mInPip || mToken == null) {
Log.wtf(TAG, "Not allowed to removePip in current state"
+ " mInPip=" + mInPip + " mToken=" + mToken);
return;
}
getUpdateHandler().post(() -> {
try {
ActivityTaskManager.getService().removeStacksInWindowingModes(
new int[]{ WINDOWING_MODE_PINNED });
} catch (RemoteException e) {
Log.e(TAG, "Failed to remove PiP", e);
}
});
mInitialState.remove(mToken.asBinder());
}
@Override
@@ -277,19 +335,37 @@ public class PipTaskOrganizer extends TaskOrganizer {
mInPip = true;
mLeash = leash;
// TODO: Skip enter animation when entering pip from another orientation
final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
mBoundsToRestore.put(mToken.asBinder(), currentBounds);
mInitialState.put(mToken.asBinder(), new Configuration(mTaskInfo.configuration));
if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
scheduleAnimateResizePip(currentBounds, destinationBounds,
TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
null /* updateBoundsCallback */);
} else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
mUpdateHandler.post(() -> mPipAnimationController
.getAnimator(mLeash, destinationBounds, 0f, 1f)
.setTransitionDirection(TRANSITION_DIRECTION_TO_PIP)
.setPipAnimationCallback(mPipAnimationCallback)
.setDuration(mEnterExitAnimationDuration)
.start());
// If we are fading the PIP in, then we should move the pip to the final location as
// soon as possible, but set the alpha immediately since the transaction can take a
// while to process
final SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
tx.setAlpha(mLeash, 0f);
tx.apply();
final WindowContainerTransaction wct = new WindowContainerTransaction();
wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
wct.setBounds(mToken, destinationBounds);
wct.scheduleFinishEnterPip(mToken, destinationBounds);
applySyncTransaction(wct, new WindowContainerTransactionCallback() {
@Override
public void onTransactionReady(int id, SurfaceControl.Transaction t) {
t.apply();
mUpdateHandler.post(() -> mPipAnimationController
.getAnimator(mLeash, destinationBounds, 0f, 1f)
.setTransitionDirection(TRANSITION_DIRECTION_TO_PIP)
.setPipAnimationCallback(mPipAnimationCallback)
.setDuration(mEnterExitAnimationDuration)
.start());
}
});
mOneShotAnimationType = ANIM_TYPE_BOUNDS;
} else {
throw new RuntimeException("Unrecognized animation type: " + mOneShotAnimationType);
@@ -297,7 +373,7 @@ public class PipTaskOrganizer extends TaskOrganizer {
}
/**
* Note that dismissing PiP is now originated from SystemUI, see {@link #dismissPip(int)}.
* Note that dismissing PiP is now originated from SystemUI, see {@link #exitPip(int)}.
* Meanwhile this callback is invoked whenever the task is removed. For instance:
* - as a result of removeStacksInWindowingModes from WM
* - activity itself is died
@@ -411,6 +487,7 @@ public class PipTaskOrganizer extends TaskOrganizer {
// can be initiated in other component, ignore if we are no longer in PIP
return;
}
SomeArgs args = SomeArgs.obtain();
args.arg1 = updateBoundsCallback;
args.arg2 = currentBounds;
@@ -518,7 +595,7 @@ public class PipTaskOrganizer extends TaskOrganizer {
throw new RuntimeException("Callers should call scheduleResizePip() instead of this "
+ "directly");
}
// Could happen when dismissPip
// Could happen when exitPip
if (mToken == null || mLeash == null) {
Log.w(TAG, "Abort animation, invalid leash");
return;
@@ -535,7 +612,7 @@ public class PipTaskOrganizer extends TaskOrganizer {
throw new RuntimeException("Callers should call scheduleUserResizePip() instead of "
+ "this directly");
}
// Could happen when dismissPip
// Could happen when exitPip
if (mToken == null || mLeash == null) {
Log.w(TAG, "Abort animation, invalid leash");
return;
@@ -546,32 +623,43 @@ public class PipTaskOrganizer extends TaskOrganizer {
}
private void finishResize(SurfaceControl.Transaction tx, Rect destinationBounds,
@PipAnimationController.TransitionDirection int direction) {
@PipAnimationController.TransitionDirection int direction,
@PipAnimationController.AnimationType int type) {
if (Looper.myLooper() != mUpdateHandler.getLooper()) {
throw new RuntimeException("Callers should call scheduleResizePip() instead of this "
+ "directly");
}
mLastReportedBounds.set(destinationBounds);
if (isInPipDirection(direction) && type == ANIM_TYPE_ALPHA) {
return;
}
final WindowContainerTransaction wct = new WindowContainerTransaction();
final Rect taskBounds;
if (isOutPipDirection(direction)) {
if (isInPipDirection(direction)) {
// If we are animating from fullscreen using a bounds animation, then reset the
// activity windowing mode set by WM, and set the task bounds to the final bounds
taskBounds = destinationBounds;
wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
wct.scheduleFinishEnterPip(mToken, destinationBounds);
} else if (isOutPipDirection(direction)) {
// If we are animating to fullscreen, then we need to reset the override bounds
// on the task to ensure that the task "matches" the parent's bounds.
taskBounds = (direction == TRANSITION_DIRECTION_TO_FULLSCREEN)
? null : destinationBounds;
// As for the final windowing mode, simply reset it to undefined.
// As for the final windowing mode, simply reset it to undefined and reset the activity
// mode set prior to the animation running
wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
if (mSplitDivider != null && direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN) {
wct.reparent(mToken, mSplitDivider.getSecondaryRoot(), true /* onTop */);
}
} else {
// Just a resize in PIP
taskBounds = destinationBounds;
}
if (direction == TRANSITION_DIRECTION_TO_PIP) {
wct.scheduleFinishEnterPip(mToken, taskBounds);
} else {
wct.setBounds(mToken, taskBounds);
}
wct.setBounds(mToken, taskBounds);
wct.setBoundsChangeTransaction(mToken, tx);
WindowOrganizer.applyTransaction(wct);
}
@@ -582,17 +670,17 @@ public class PipTaskOrganizer extends TaskOrganizer {
throw new RuntimeException("Callers should call scheduleAnimateResizePip() instead of "
+ "this directly");
}
// Could happen when dismissPip
// Could happen when exitPip
if (mToken == null || mLeash == null) {
Log.w(TAG, "Abort animation, invalid leash");
return;
}
mUpdateHandler.post(() -> mPipAnimationController
mPipAnimationController
.getAnimator(mLeash, currentBounds, destinationBounds)
.setTransitionDirection(direction)
.setPipAnimationCallback(mPipAnimationCallback)
.setDuration(durationMs)
.start());
.start();
}
private Size getMinimalSize(ActivityInfo activityInfo) {
@@ -632,6 +720,27 @@ public class PipTaskOrganizer extends TaskOrganizer {
return true;
}
/**
* Dumps internal states.
*/
public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
pw.println(prefix + TAG);
pw.println(innerPrefix + "mTaskInfo=" + mTaskInfo);
pw.println(innerPrefix + "mToken=" + mToken
+ " binder=" + (mToken != null ? mToken.asBinder() : null));
pw.println(innerPrefix + "mLeash=" + mLeash);
pw.println(innerPrefix + "mInPip=" + mInPip);
pw.println(innerPrefix + "mOneShotAnimationType=" + mOneShotAnimationType);
pw.println(innerPrefix + "mPictureInPictureParams=" + mPictureInPictureParams);
pw.println(innerPrefix + "mLastReportedBounds=" + mLastReportedBounds);
pw.println(innerPrefix + "mInitialState:");
for (Map.Entry<IBinder, Configuration> e : mInitialState.entrySet()) {
pw.println(innerPrefix + " binder=" + e.getKey()
+ " winConfig=" + e.getValue().windowConfiguration);
}
}
/**
* Callback interface for PiP transitions (both from and to PiP mode)
*/

View File

@@ -101,7 +101,7 @@ public class PipAccessibilityInteractionConnection
result = true;
break;
case AccessibilityNodeInfo.ACTION_EXPAND:
mMotionHelper.expandPip();
mMotionHelper.expandPipToFullscreen();
result = true;
break;
default:

View File

@@ -25,7 +25,6 @@ import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.IActivityManager;
import android.app.IActivityTaskManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ParceledListSlice;
@@ -140,7 +139,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
!= WINDOWING_MODE_PINNED) {
return;
}
mTouchHandler.getMotionHelper().expandPip(clearedTask /* skipAnimation */);
mTouchHandler.getMotionHelper().expandPipToFullscreen(clearedTask /* skipAnimation */);
}
};
@@ -214,7 +213,6 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
}
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
final IActivityTaskManager activityTaskManager = ActivityTaskManager.getService();
mPipBoundsHandler = pipBoundsHandler;
mPipTaskOrganizer = pipTaskOrganizer;
mPipTaskOrganizer.registerPipTransitionCallback(this);
@@ -222,7 +220,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
mMediaController = new PipMediaController(context, mActivityManager, broadcastDispatcher);
mMenuController = new PipMenuActivityController(context, mMediaController,
mInputConsumerController);
mTouchHandler = new PipTouchHandler(context, mActivityManager, activityTaskManager,
mTouchHandler = new PipTouchHandler(context, mActivityManager,
mMenuController, mInputConsumerController, mPipBoundsHandler, mPipTaskOrganizer,
floatingContentCoordinator, deviceConfig, pipSnapAlgorithm);
mAppOpsListener = new PipAppOpsListener(context, mActivityManager,
@@ -237,7 +235,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
try {
mPipTaskOrganizer.registerOrganizer(WINDOWING_MODE_PINNED);
ActivityManager.StackInfo stackInfo = activityTaskManager.getStackInfo(
ActivityManager.StackInfo stackInfo = ActivityTaskManager.getService().getStackInfo(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
if (stackInfo != null) {
// If SystemUI restart, and it already existed a pinned stack,
@@ -261,7 +259,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
*/
@Override
public void expandPip() {
mTouchHandler.getMotionHelper().expandPip(false /* skipAnimation */);
mTouchHandler.getMotionHelper().expandPipToFullscreen(false /* skipAnimation */);
}
/**
@@ -378,5 +376,6 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
mMenuController.dump(pw, innerPrefix);
mTouchHandler.dump(pw, innerPrefix);
mPipBoundsHandler.dump(pw, innerPrefix);
mPipTaskOrganizer.dump(pw, innerPrefix);
}
}

View File

@@ -16,16 +16,12 @@
package com.android.systemui.pip.phone;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.IActivityTaskManager;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Rect;
import android.os.Debug;
import android.os.RemoteException;
import android.util.Log;
import androidx.dynamicanimation.animation.SpringForce;
@@ -33,7 +29,6 @@ import androidx.dynamicanimation.animation.SpringForce;
import com.android.systemui.pip.PipSnapAlgorithm;
import com.android.systemui.pip.PipTaskOrganizer;
import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.util.FloatingContentCoordinator;
import com.android.systemui.util.animation.FloatProperties;
import com.android.systemui.util.animation.PhysicsAnimator;
@@ -60,12 +55,10 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
private static final float DEFAULT_FRICTION = 2f;
private final Context mContext;
private final IActivityTaskManager mActivityTaskManager;
private final PipTaskOrganizer mPipTaskOrganizer;
private PipMenuActivityController mMenuController;
private PipSnapAlgorithm mSnapAlgorithm;
private FlingAnimationUtils mFlingAnimationUtils;
private final Rect mStableInsets = new Rect();
@@ -147,16 +140,13 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
public void onPipTransitionCanceled(ComponentName activity, int direction) {}
};
public PipMotionHelper(Context context, IActivityTaskManager activityTaskManager,
PipTaskOrganizer pipTaskOrganizer, PipMenuActivityController menuController,
PipSnapAlgorithm snapAlgorithm, FlingAnimationUtils flingAnimationUtils,
public PipMotionHelper(Context context, PipTaskOrganizer pipTaskOrganizer,
PipMenuActivityController menuController, PipSnapAlgorithm snapAlgorithm,
FloatingContentCoordinator floatingContentCoordinator) {
mContext = context;
mActivityTaskManager = activityTaskManager;
mPipTaskOrganizer = pipTaskOrganizer;
mMenuController = menuController;
mSnapAlgorithm = snapAlgorithm;
mFlingAnimationUtils = flingAnimationUtils;
mFloatingContentCoordinator = floatingContentCoordinator;
onConfigurationChanged();
mPipTaskOrganizer.registerPipTransitionCallback(mPipTransitionCallback);
@@ -267,22 +257,24 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
/**
* Resizes the pinned stack back to fullscreen.
*/
void expandPip() {
expandPip(false /* skipAnimation */);
void expandPipToFullscreen() {
expandPipToFullscreen(false /* skipAnimation */);
}
/**
* Resizes the pinned stack back to fullscreen.
*/
void expandPip(boolean skipAnimation) {
void expandPipToFullscreen(boolean skipAnimation) {
if (DEBUG) {
Log.d(TAG, "expandPip: skipAnimation=" + skipAnimation
Log.d(TAG, "exitPip: skipAnimation=" + skipAnimation
+ " callers=\n" + Debug.getCallers(5, " "));
}
cancelAnimations();
mMenuController.hideMenuWithoutResize();
mPipTaskOrganizer.getUpdateHandler().post(() -> {
mPipTaskOrganizer.dismissPip(skipAnimation ? 0 : EXPAND_STACK_TO_FULLSCREEN_DURATION);
mPipTaskOrganizer.exitPip(skipAnimation
? 0
: EXPAND_STACK_TO_FULLSCREEN_DURATION);
});
}
@@ -292,18 +284,11 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
@Override
public void dismissPip() {
if (DEBUG) {
Log.d(TAG, "dismissPip: callers=\n" + Debug.getCallers(5, " "));
Log.d(TAG, "removePip: callers=\n" + Debug.getCallers(5, " "));
}
cancelAnimations();
mMenuController.hideMenuWithoutResize();
mPipTaskOrganizer.getUpdateHandler().post(() -> {
try {
mActivityTaskManager.removeStacksInWindowingModes(
new int[]{ WINDOWING_MODE_PINNED });
} catch (RemoteException e) {
Log.e(TAG, "Failed to remove PiP", e);
}
});
mPipTaskOrganizer.removePip();
}
/** Sets the movement bounds to use to constrain PIP position animations. */

View File

@@ -23,7 +23,6 @@ import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STAT
import android.annotation.SuppressLint;
import android.app.IActivityManager;
import android.app.IActivityTaskManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
@@ -188,7 +187,7 @@ public class PipTouchHandler {
@Override
public void onPipExpand() {
mMotionHelper.expandPip();
mMotionHelper.expandPipToFullscreen();
}
@Override
@@ -210,7 +209,7 @@ public class PipTouchHandler {
@SuppressLint("InflateParams")
public PipTouchHandler(Context context, IActivityManager activityManager,
IActivityTaskManager activityTaskManager, PipMenuActivityController menuController,
PipMenuActivityController menuController,
InputConsumerController inputConsumerController,
PipBoundsHandler pipBoundsHandler,
PipTaskOrganizer pipTaskOrganizer,
@@ -228,8 +227,8 @@ public class PipTouchHandler {
mFlingAnimationUtils = new FlingAnimationUtils(context.getResources().getDisplayMetrics(),
2.5f);
mGesture = new DefaultPipTouchGesture();
mMotionHelper = new PipMotionHelper(mContext, activityTaskManager, pipTaskOrganizer,
mMenuController, mSnapAlgorithm, mFlingAnimationUtils, floatingContentCoordinator);
mMotionHelper = new PipMotionHelper(mContext, pipTaskOrganizer, mMenuController,
mSnapAlgorithm, floatingContentCoordinator);
mPipResizeGestureHandler =
new PipResizeGestureHandler(context, pipBoundsHandler, mMotionHelper,
deviceConfig, pipTaskOrganizer, this::getMovementBounds,
@@ -908,7 +907,7 @@ public class PipTouchHandler {
// Expand to fullscreen if this is a double tap
// the PiP should be frozen until the transition ends
setTouchEnabled(false);
mMotionHelper.expandPip();
mMotionHelper.expandPipToFullscreen();
} else if (mMenuState != MENU_STATE_FULL) {
if (!mTouchState.isWaitingForDoubleTap()) {
// User has stalled long enough for this not to be a drag or a double tap, just

View File

@@ -468,7 +468,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
mPipTaskOrganizer.scheduleAnimateResizePip(mCurrentPipBounds, mResizeAnimationDuration,
null);
} else {
mPipTaskOrganizer.dismissPip(mResizeAnimationDuration);
mPipTaskOrganizer.exitPip(mResizeAnimationDuration);
}
}

View File

@@ -64,9 +64,6 @@ public class PipTouchHandlerTest extends SysuiTestCase {
@Mock
private IActivityManager mActivityManager;
@Mock
private IActivityTaskManager mIActivityTaskManager;
@Mock
private PipMenuActivityController mPipMenuActivityController;
@@ -101,7 +98,7 @@ public class PipTouchHandlerTest extends SysuiTestCase {
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mPipSnapAlgorithm = new PipSnapAlgorithm(mContext);
mPipTouchHandler = new PipTouchHandler(mContext, mActivityManager, mIActivityTaskManager,
mPipTouchHandler = new PipTouchHandler(mContext, mActivityManager,
mPipMenuActivityController, mInputConsumerController, mPipBoundsHandler,
mPipTaskOrganizer, mFloatingContentCoordinator, mDeviceConfigProxy,
mPipSnapAlgorithm);

View File

@@ -2194,8 +2194,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@Override
boolean isFocusable() {
return super.isFocusable()
&& (getWindowConfiguration().canReceiveKeys() || isAlwaysFocusable());
// TODO(156521483): Propagate the state down the hierarchy instead of checking the parent
boolean canReceiveKeys = getWindowConfiguration().canReceiveKeys()
&& getTask().getWindowConfiguration().canReceiveKeys();
return super.isFocusable() && (canReceiveKeys || isAlwaysFocusable());
}
boolean isResizeable() {

View File

@@ -2188,6 +2188,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
// display area, so reparent.
stack.reparent(taskDisplayArea, true /* onTop */);
}
// Defer the windowing mode change until after the transition to prevent the activity
// from doing work and changing the activity visuals while animating
// TODO(task-org): Figure-out more structured way to do this long term.
r.setWindowingMode(stack.getWindowingMode());
stack.setWindowingMode(WINDOWING_MODE_PINNED);
// Reset the state that indicates it can enter PiP while pausing after we've moved it

View File

@@ -1940,7 +1940,6 @@ class Task extends WindowContainer<WindowContainer> {
setLastNonFullscreenBounds(currentBounds);
}
}
// TODO: Should also take care of Pip mode changes here.
saveLaunchingStateIfNeeded();
final boolean taskOrgChanged = updateTaskOrganizerState(false /* forceUpdate */);