Merge "Make PIP into split screen" into tm-qpr-dev am: 5c978d3fb3
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20766589 Change-Id: I7bf4d8adbe69e5bbd72289d2fc8420f6717fcd0b Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -216,7 +216,6 @@ public class TaskStackListenerImpl extends TaskStackListener implements Handler.
|
||||
args.argi1 = homeTaskVisible ? 1 : 0;
|
||||
args.argi2 = clearedTask ? 1 : 0;
|
||||
args.argi3 = wasVisible ? 1 : 0;
|
||||
mMainHandler.removeMessages(ON_ACTIVITY_RESTART_ATTEMPT);
|
||||
mMainHandler.obtainMessage(ON_ACTIVITY_RESTART_ATTEMPT, args).sendToTarget();
|
||||
}
|
||||
|
||||
|
||||
@@ -1409,7 +1409,6 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
@PipAnimationController.TransitionDirection int direction,
|
||||
@PipAnimationController.AnimationType int type) {
|
||||
final Rect preResizeBounds = new Rect(mPipBoundsState.getBounds());
|
||||
final boolean isPipTopLeft = isPipTopLeft();
|
||||
mPipBoundsState.setBounds(destinationBounds);
|
||||
if (direction == TRANSITION_DIRECTION_REMOVE_STACK) {
|
||||
removePipImmediately();
|
||||
@@ -1455,9 +1454,11 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
null /* callback */, false /* withStartDelay */);
|
||||
});
|
||||
} else {
|
||||
applyFinishBoundsResize(wct, direction, isPipTopLeft);
|
||||
applyFinishBoundsResize(wct, direction, false);
|
||||
}
|
||||
} else {
|
||||
final boolean isPipTopLeft =
|
||||
direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN && isPipToTopLeft();
|
||||
applyFinishBoundsResize(wct, direction, isPipTopLeft);
|
||||
}
|
||||
|
||||
@@ -1526,6 +1527,14 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
return topLeft.contains(mPipBoundsState.getBounds());
|
||||
}
|
||||
|
||||
private boolean isPipToTopLeft() {
|
||||
if (!mSplitScreenOptional.isPresent()) {
|
||||
return false;
|
||||
}
|
||||
return mSplitScreenOptional.get().getActivateSplitPosition(mTaskInfo)
|
||||
== SPLIT_POSITION_TOP_OR_LEFT;
|
||||
}
|
||||
|
||||
/**
|
||||
* The windowing mode to restore to when resizing out of PIP direction. Defaults to undefined
|
||||
* and can be overridden to restore to an alternate windowing mode.
|
||||
@@ -1662,8 +1671,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
final Rect topLeft = new Rect();
|
||||
final Rect bottomRight = new Rect();
|
||||
mSplitScreenOptional.get().getStageBounds(topLeft, bottomRight);
|
||||
final boolean isPipTopLeft = isPipTopLeft();
|
||||
destinationBoundsOut.set(isPipTopLeft ? topLeft : bottomRight);
|
||||
destinationBoundsOut.set(isPipToTopLeft() ? topLeft : bottomRight);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1747,6 +1755,11 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
mSurfaceControlTransactionFactory = factory;
|
||||
}
|
||||
|
||||
public boolean isLaunchToSplit(TaskInfo taskInfo) {
|
||||
return mSplitScreenOptional.isPresent()
|
||||
&& mSplitScreenOptional.get().isLaunchToSplit(taskInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps internal states.
|
||||
*/
|
||||
|
||||
@@ -570,8 +570,12 @@ public class PipController implements PipTransitionController.PipTransitionCallb
|
||||
if (task.getWindowingMode() != WINDOWING_MODE_PINNED) {
|
||||
return;
|
||||
}
|
||||
mTouchHandler.getMotionHelper().expandLeavePip(
|
||||
clearedTask /* skipAnimation */);
|
||||
if (mPipTaskOrganizer.isLaunchToSplit(task)) {
|
||||
mTouchHandler.getMotionHelper().expandIntoSplit();
|
||||
} else {
|
||||
mTouchHandler.getMotionHelper().expandLeavePip(
|
||||
clearedTask /* skipAnimation */);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ import android.app.ActivityManager;
|
||||
import android.app.ActivityOptions;
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.TaskInfo;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
@@ -421,6 +422,14 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
|
||||
mStageCoordinator.goToFullscreenFromSplit();
|
||||
}
|
||||
|
||||
public boolean isLaunchToSplit(TaskInfo taskInfo) {
|
||||
return mStageCoordinator.isLaunchToSplit(taskInfo);
|
||||
}
|
||||
|
||||
public int getActivateSplitPosition(TaskInfo taskInfo) {
|
||||
return mStageCoordinator.getActivateSplitPosition(taskInfo);
|
||||
}
|
||||
|
||||
public void startTask(int taskId, @SplitPosition int position, @Nullable Bundle options) {
|
||||
final int[] result = new int[1];
|
||||
IRemoteAnimationRunner wrapper = new IRemoteAnimationRunner.Stub() {
|
||||
|
||||
@@ -74,6 +74,7 @@ import android.app.ActivityManager;
|
||||
import android.app.ActivityOptions;
|
||||
import android.app.IActivityTaskManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.TaskInfo;
|
||||
import android.app.WindowConfiguration;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
@@ -124,6 +125,7 @@ import com.android.wm.shell.common.SyncTransactionQueue;
|
||||
import com.android.wm.shell.common.TransactionPool;
|
||||
import com.android.wm.shell.common.split.SplitLayout;
|
||||
import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition;
|
||||
import com.android.wm.shell.common.split.SplitScreenUtils;
|
||||
import com.android.wm.shell.common.split.SplitWindowManager;
|
||||
import com.android.wm.shell.protolog.ShellProtoLogGroup;
|
||||
import com.android.wm.shell.recents.RecentTasksController;
|
||||
@@ -208,6 +210,36 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
|
||||
private DefaultMixedHandler mMixedHandler;
|
||||
private final Toast mSplitUnsupportedToast;
|
||||
private SplitRequest mSplitRequest;
|
||||
|
||||
class SplitRequest {
|
||||
@SplitPosition
|
||||
int mActivatePosition;
|
||||
int mActivateTaskId;
|
||||
int mActivateTaskId2;
|
||||
Intent mStartIntent;
|
||||
Intent mStartIntent2;
|
||||
|
||||
SplitRequest(int taskId, Intent startIntent, int position) {
|
||||
mActivateTaskId = taskId;
|
||||
mStartIntent = startIntent;
|
||||
mActivatePosition = position;
|
||||
}
|
||||
SplitRequest(Intent startIntent, int position) {
|
||||
mStartIntent = startIntent;
|
||||
mActivatePosition = position;
|
||||
}
|
||||
SplitRequest(Intent startIntent, Intent startIntent2, int position) {
|
||||
mStartIntent = startIntent;
|
||||
mStartIntent2 = startIntent2;
|
||||
mActivatePosition = position;
|
||||
}
|
||||
SplitRequest(int taskId1, int taskId2, int position) {
|
||||
mActivateTaskId = taskId1;
|
||||
mActivateTaskId2 = taskId2;
|
||||
mActivatePosition = position;
|
||||
}
|
||||
}
|
||||
|
||||
private final SplitWindowManager.ParentContainerCallbacks mParentContainerCallbacks =
|
||||
new SplitWindowManager.ParentContainerCallbacks() {
|
||||
@@ -393,6 +425,23 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
setSideStagePosition(sideStagePosition, wct);
|
||||
final WindowContainerTransaction evictWct = new WindowContainerTransaction();
|
||||
targetStage.evictAllChildren(evictWct);
|
||||
|
||||
// Apply surface bounds before animation start.
|
||||
SurfaceControl.Transaction startT = mTransactionPool.acquire();
|
||||
if (startT != null) {
|
||||
updateSurfaceBounds(mSplitLayout, startT, false /* applyResizingOffset */);
|
||||
startT.apply();
|
||||
mTransactionPool.release(startT);
|
||||
}
|
||||
// reparent the task to an invisible split root will make the activity invisible. Reorder
|
||||
// the root task to front to make the entering transition from pip to split smooth.
|
||||
wct.reorder(mRootTaskInfo.token, true);
|
||||
wct.setForceTranslucent(mRootTaskInfo.token, true);
|
||||
wct.reorder(targetStage.mRootTaskInfo.token, true);
|
||||
wct.setForceTranslucent(targetStage.mRootTaskInfo.token, true);
|
||||
// prevent the fling divider to center transition
|
||||
mIsDropEntering = true;
|
||||
|
||||
targetStage.addTask(task, wct);
|
||||
|
||||
if (ENABLE_SHELL_TRANSITIONS) {
|
||||
@@ -547,7 +596,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
}
|
||||
}
|
||||
|
||||
if (isEnteringSplit && !openingToSide) {
|
||||
if (isEnteringSplit && !openingToSide && apps != null) {
|
||||
mMainExecutor.execute(() -> exitSplitScreen(
|
||||
mSideStage.getChildCount() == 0 ? mMainStage : mSideStage,
|
||||
EXIT_REASON_UNKNOWN));
|
||||
@@ -587,7 +636,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
if (isEnteringSplit && mLogger.isEnterRequestedByDrag()) {
|
||||
updateWindowBounds(mSplitLayout, wct);
|
||||
}
|
||||
|
||||
mSplitRequest = new SplitRequest(intent.getIntent(), position);
|
||||
wct.sendPendingIntent(intent, fillInIntent, options);
|
||||
mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct);
|
||||
}
|
||||
@@ -686,6 +735,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
|
||||
addActivityOptions(options1, mSideStage);
|
||||
wct.startTask(taskId1, options1);
|
||||
mSplitRequest = new SplitRequest(taskId1, taskId2, splitPosition);
|
||||
startWithLegacyTransition(wct, taskId2, options2, splitPosition, splitRatio, adapter,
|
||||
instanceId);
|
||||
}
|
||||
@@ -719,6 +769,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
wct.startShortcut(mContext.getPackageName(), shortcutInfo1, options1);
|
||||
} else {
|
||||
wct.sendPendingIntent(pendingIntent1, fillInIntent1, options1);
|
||||
mSplitRequest = new SplitRequest(pendingIntent1.getIntent(),
|
||||
pendingIntent2 != null ? pendingIntent2.getIntent() : null, splitPosition);
|
||||
}
|
||||
startWithLegacyTransition(wct, pendingIntent2, fillInIntent2, shortcutInfo2, options2,
|
||||
splitPosition, splitRatio, adapter, instanceId);
|
||||
@@ -743,6 +795,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
|
||||
addActivityOptions(options1, mSideStage);
|
||||
wct.sendPendingIntent(pendingIntent, fillInIntent, options1);
|
||||
mSplitRequest = new SplitRequest(taskId, pendingIntent.getIntent(), splitPosition);
|
||||
startWithLegacyTransition(wct, taskId, options2, splitPosition, splitRatio, adapter,
|
||||
instanceId);
|
||||
}
|
||||
@@ -815,7 +868,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
// Set false to avoid record new bounds with old task still on top;
|
||||
mShouldUpdateRecents = false;
|
||||
mIsSplitEntering = true;
|
||||
|
||||
if (mSplitRequest == null) {
|
||||
mSplitRequest = new SplitRequest(mainTaskId,
|
||||
mainPendingIntent != null ? mainPendingIntent.getIntent() : null,
|
||||
sidePosition);
|
||||
}
|
||||
setSideStagePosition(sidePosition, wct);
|
||||
if (!mMainStage.isActive()) {
|
||||
mMainStage.activate(wct, false /* reparent */);
|
||||
@@ -906,6 +963,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
WindowContainerTransaction evictWct) {
|
||||
mIsSplitEntering = false;
|
||||
mShouldUpdateRecents = true;
|
||||
mSplitRequest = null;
|
||||
// If any stage has no child after animation finished, it means that split will display
|
||||
// nothing, such status will happen if task and intent is same app but not support
|
||||
// multi-instance, we should exit split and expand that app as full screen.
|
||||
@@ -1739,7 +1797,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
mSplitLayout.init();
|
||||
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
if (mLogger.isEnterRequestedByDrag()) {
|
||||
if (mIsDropEntering) {
|
||||
prepareEnterSplitScreen(wct);
|
||||
} else {
|
||||
// TODO (b/238697912) : Add the validation to prevent entering non-recovered status
|
||||
@@ -1764,6 +1822,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
}
|
||||
if (mMainStageListener.mHasChildren && mSideStageListener.mHasChildren) {
|
||||
mShouldUpdateRecents = true;
|
||||
mSplitRequest = null;
|
||||
updateRecentTasksSplitPair();
|
||||
|
||||
if (!mLogger.hasStartedSession()) {
|
||||
@@ -2316,6 +2375,33 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
mSplitLayout.flingDividerToDismiss(!leftOrTop, EXIT_REASON_FULLSCREEN_SHORTCUT);
|
||||
}
|
||||
|
||||
boolean isLaunchToSplit(TaskInfo taskInfo) {
|
||||
return getActivateSplitPosition(taskInfo) != SPLIT_POSITION_UNDEFINED;
|
||||
}
|
||||
|
||||
int getActivateSplitPosition(TaskInfo taskInfo) {
|
||||
if (mSplitRequest == null || taskInfo == null) {
|
||||
return SPLIT_POSITION_UNDEFINED;
|
||||
}
|
||||
if (mSplitRequest.mActivateTaskId != 0
|
||||
&& mSplitRequest.mActivateTaskId2 == taskInfo.taskId) {
|
||||
return mSplitRequest.mActivatePosition;
|
||||
}
|
||||
if (mSplitRequest.mActivateTaskId == taskInfo.taskId) {
|
||||
return mSplitRequest.mActivatePosition;
|
||||
}
|
||||
final String packageName1 = SplitScreenUtils.getPackageName(mSplitRequest.mStartIntent);
|
||||
final String basePackageName = SplitScreenUtils.getPackageName(taskInfo.baseIntent);
|
||||
if (packageName1 != null && packageName1.equals(basePackageName)) {
|
||||
return mSplitRequest.mActivatePosition;
|
||||
}
|
||||
final String packageName2 = SplitScreenUtils.getPackageName(mSplitRequest.mStartIntent2);
|
||||
if (packageName2 != null && packageName2.equals(basePackageName)) {
|
||||
return mSplitRequest.mActivatePosition;
|
||||
}
|
||||
return SPLIT_POSITION_UNDEFINED;
|
||||
}
|
||||
|
||||
/** Synchronize split-screen state with transition and make appropriate preparations. */
|
||||
public void prepareDismissAnimation(@StageType int toStage, @ExitReason int dismissReason,
|
||||
@NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t,
|
||||
|
||||
Reference in New Issue
Block a user