Merge "Update config ordering when entering/leaving pip" into rvc-dev am: d8fb783389
Change-Id: Iac736f444b9330784a0b84c49a40e226b8c4eec9
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
*/
|
||||
|
||||
@@ -101,7 +101,7 @@ public class PipAccessibilityInteractionConnection
|
||||
result = true;
|
||||
break;
|
||||
case AccessibilityNodeInfo.ACTION_EXPAND:
|
||||
mMotionHelper.expandPip();
|
||||
mMotionHelper.expandPipToFullscreen();
|
||||
result = true;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -468,7 +468,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
mPipTaskOrganizer.scheduleAnimateResizePip(mCurrentPipBounds, mResizeAnimationDuration,
|
||||
null);
|
||||
} else {
|
||||
mPipTaskOrganizer.dismissPip(mResizeAnimationDuration);
|
||||
mPipTaskOrganizer.exitPip(mResizeAnimationDuration);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */);
|
||||
|
||||
Reference in New Issue
Block a user