Merge "Polish ActivityEmbedding enter/exit PiP (1/n)"
This commit is contained in:
@@ -407,6 +407,7 @@ public final class TransitionInfo implements Parcelable {
|
||||
public static final class Change implements Parcelable {
|
||||
private final WindowContainerToken mContainer;
|
||||
private WindowContainerToken mParent;
|
||||
private WindowContainerToken mLastParent;
|
||||
private final SurfaceControl mLeash;
|
||||
private @TransitionMode int mMode = TRANSIT_NONE;
|
||||
private @ChangeFlags int mFlags = FLAG_NONE;
|
||||
@@ -435,6 +436,7 @@ public final class TransitionInfo implements Parcelable {
|
||||
private Change(Parcel in) {
|
||||
mContainer = in.readTypedObject(WindowContainerToken.CREATOR);
|
||||
mParent = in.readTypedObject(WindowContainerToken.CREATOR);
|
||||
mLastParent = in.readTypedObject(WindowContainerToken.CREATOR);
|
||||
mLeash = new SurfaceControl();
|
||||
mLeash.readFromParcel(in);
|
||||
mMode = in.readInt();
|
||||
@@ -458,6 +460,14 @@ public final class TransitionInfo implements Parcelable {
|
||||
mParent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parent of this change's container before the transition if this change's
|
||||
* container is reparented in the transition.
|
||||
*/
|
||||
public void setLastParent(@Nullable WindowContainerToken lastParent) {
|
||||
mLastParent = lastParent;
|
||||
}
|
||||
|
||||
/** Sets the transition mode for this change */
|
||||
public void setMode(@TransitionMode int mode) {
|
||||
mMode = mode;
|
||||
@@ -541,6 +551,17 @@ public final class TransitionInfo implements Parcelable {
|
||||
return mParent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the parent of the changing container before the transition if it is reparented
|
||||
* in the transition. The parent window may not be collected in the transition as a
|
||||
* participant, and it may have been detached from the display. {@code null} if the changing
|
||||
* container has not been reparented in the transition, or if the parent is not organizable.
|
||||
*/
|
||||
@Nullable
|
||||
public WindowContainerToken getLastParent() {
|
||||
return mLastParent;
|
||||
}
|
||||
|
||||
/** @return which action this change represents. */
|
||||
public @TransitionMode int getMode() {
|
||||
return mMode;
|
||||
@@ -640,6 +661,7 @@ public final class TransitionInfo implements Parcelable {
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeTypedObject(mContainer, flags);
|
||||
dest.writeTypedObject(mParent, flags);
|
||||
dest.writeTypedObject(mLastParent, flags);
|
||||
mLeash.writeToParcel(dest, flags);
|
||||
dest.writeInt(mMode);
|
||||
dest.writeInt(mFlags);
|
||||
@@ -685,6 +707,7 @@ public final class TransitionInfo implements Parcelable {
|
||||
+ mStartRotation + "->" + mEndRotation + ":" + mRotationAnimation
|
||||
+ " endFixedRotation=" + mEndFixedRotation;
|
||||
if (mSnapshot != null) out += " snapshot=" + mSnapshot;
|
||||
if (mLastParent != null) out += " lastParent=" + mLastParent;
|
||||
return out + "}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,14 +452,17 @@ public class PipTransition extends PipTransitionController {
|
||||
@NonNull Transitions.TransitionFinishCallback finishCallback,
|
||||
@NonNull TaskInfo taskInfo, @Nullable TransitionInfo.Change pipTaskChange) {
|
||||
TransitionInfo.Change pipChange = pipTaskChange;
|
||||
if (pipChange == null) {
|
||||
if (mCurrentPipTaskToken == null) {
|
||||
ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
|
||||
"%s: There is no existing PiP Task for TRANSIT_EXIT_PIP", TAG);
|
||||
} else if (pipChange == null) {
|
||||
// The pipTaskChange is null, this can happen if we are reparenting the PIP activity
|
||||
// back to its original Task. In that case, we should animate the activity leash
|
||||
// instead, which should be the only non-task, independent, TRANSIT_CHANGE window.
|
||||
// instead, which should be the change whose last parent is the recorded PiP Task.
|
||||
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
|
||||
final TransitionInfo.Change change = info.getChanges().get(i);
|
||||
if (change.getTaskInfo() == null && change.getMode() == TRANSIT_CHANGE
|
||||
&& TransitionInfo.isIndependent(change, info)) {
|
||||
if (mCurrentPipTaskToken.equals(change.getLastParent())) {
|
||||
// Find the activity that is exiting PiP.
|
||||
pipChange = change;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2020,7 +2020,12 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
|
||||
// non-fullscreen bounds. Then when this new PIP task exits PIP, it can restore
|
||||
// to its previous freeform bounds.
|
||||
rootTask.setLastNonFullscreenBounds(task.mLastNonFullscreenBounds);
|
||||
rootTask.setBounds(task.getBounds());
|
||||
// When creating a new Task for PiP, set its initial bounds as the TaskFragment in
|
||||
// case the activity is embedded, so that it can be animated to PiP window from the
|
||||
// current bounds.
|
||||
// Use Task#setBoundsUnchecked to skip checking windowing mode as the windowing mode
|
||||
// will be updated later after this is collected in transition.
|
||||
rootTask.setBoundsUnchecked(r.getTaskFragment().getBounds());
|
||||
|
||||
// Move the last recents animation transaction from original task to the new one.
|
||||
if (task.mLastRecentsAnimationTransaction != null) {
|
||||
|
||||
@@ -2605,6 +2605,13 @@ class Task extends TaskFragment {
|
||||
return boundsChange;
|
||||
}
|
||||
|
||||
/** Sets the requested bounds regardless of the windowing mode. */
|
||||
int setBoundsUnchecked(@NonNull Rect bounds) {
|
||||
final int boundsChange = super.setBounds(bounds);
|
||||
updateSurfaceBounds();
|
||||
return boundsChange;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompatible(int windowingMode, int activityType) {
|
||||
// TODO: Should we just move this to ConfigurationContainer?
|
||||
@@ -5852,10 +5859,7 @@ class Task extends TaskFragment {
|
||||
return BOUNDS_CHANGE_NONE;
|
||||
}
|
||||
|
||||
final int result = super.setBounds(!inMultiWindowMode() ? null : bounds);
|
||||
|
||||
updateSurfaceBounds();
|
||||
return result;
|
||||
return setBoundsUnchecked(!inMultiWindowMode() ? null : bounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1561,6 +1561,10 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
if (info.mEndParent != null) {
|
||||
change.setParent(info.mEndParent.mRemoteToken.toWindowContainerToken());
|
||||
}
|
||||
if (info.mStartParent != null && info.mStartParent.mRemoteToken != null
|
||||
&& target.getParent() != info.mStartParent) {
|
||||
change.setLastParent(info.mStartParent.mRemoteToken.toWindowContainerToken());
|
||||
}
|
||||
change.setMode(info.getTransitMode(target));
|
||||
change.setStartAbsBounds(info.mAbsoluteBounds);
|
||||
change.setFlags(info.getChangeFlags(target));
|
||||
|
||||
@@ -72,6 +72,7 @@ import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Rect;
|
||||
import android.os.PowerManager;
|
||||
import android.os.UserHandle;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
@@ -391,6 +392,33 @@ public class RootWindowContainerTests extends WindowTestsBase {
|
||||
assertEquals(WINDOWING_MODE_FULLSCREEN, fullscreenTask.getWindowingMode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMovingEmbeddedActivityToPip() {
|
||||
final Rect taskBounds = new Rect(0, 0, 800, 1000);
|
||||
final Rect taskFragmentBounds = new Rect(0, 0, 400, 1000);
|
||||
final Task task = mRootWindowContainer.getDefaultTaskDisplayArea().createRootTask(
|
||||
WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD, true /* onTop */);
|
||||
task.setBounds(taskBounds);
|
||||
assertEquals(taskBounds, task.getBounds());
|
||||
final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
|
||||
.setParentTask(task)
|
||||
.createActivityCount(2)
|
||||
.setBounds(taskFragmentBounds)
|
||||
.build();
|
||||
assertEquals(taskFragmentBounds, taskFragment.getBounds());
|
||||
final ActivityRecord topActivity = taskFragment.getTopMostActivity();
|
||||
|
||||
// Move the top activity to pinned root task.
|
||||
mRootWindowContainer.moveActivityToPinnedRootTask(topActivity,
|
||||
null /* launchIntoPipHostActivity */, "test");
|
||||
|
||||
final Task pinnedRootTask = task.getDisplayArea().getRootPinnedTask();
|
||||
|
||||
// Ensure the initial bounds of the PiP Task is the same as the TaskFragment.
|
||||
ensureTaskPlacement(pinnedRootTask, topActivity);
|
||||
assertEquals(taskFragmentBounds, pinnedRootTask.getBounds());
|
||||
}
|
||||
|
||||
private static void ensureTaskPlacement(Task task, ActivityRecord... activities) {
|
||||
final ArrayList<ActivityRecord> taskActivities = new ArrayList<>();
|
||||
|
||||
|
||||
@@ -1324,6 +1324,35 @@ public class TransitionTests extends WindowTestsBase {
|
||||
assertTrue(info.getChanges().get(0).hasFlags(FLAG_FILLS_TASK));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReparentChangeLastParent() {
|
||||
final Transition transition = createTestTransition(TRANSIT_CHANGE);
|
||||
final ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
|
||||
final ArraySet<WindowContainer> participants = transition.mParticipants;
|
||||
|
||||
// Reparent activity in transition.
|
||||
final Task lastParent = createTask(mDisplayContent);
|
||||
final Task newParent = createTask(mDisplayContent);
|
||||
final ActivityRecord activity = createActivityRecord(lastParent);
|
||||
activity.mVisibleRequested = true;
|
||||
// Skip manipulate the SurfaceControl.
|
||||
doNothing().when(activity).setDropInputMode(anyInt());
|
||||
changes.put(activity, new Transition.ChangeInfo(activity));
|
||||
activity.reparent(newParent, POSITION_TOP);
|
||||
activity.mVisibleRequested = false;
|
||||
|
||||
participants.add(activity);
|
||||
final ArrayList<WindowContainer> targets = Transition.calculateTargets(
|
||||
participants, changes);
|
||||
final TransitionInfo info = Transition.calculateTransitionInfo(
|
||||
transition.mType, 0 /* flags */, targets, changes, mMockT);
|
||||
|
||||
// Change contains last parent info.
|
||||
assertEquals(1, info.getChanges().size());
|
||||
assertEquals(lastParent.mRemoteToken.toWindowContainerToken(),
|
||||
info.getChanges().get(0).getLastParent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncludeEmbeddedActivityReparent() {
|
||||
final Transition transition = createTestTransition(TRANSIT_OPEN);
|
||||
|
||||
Reference in New Issue
Block a user