Fix PiP transition ordering
First, this cancels the existing pip animation if it is told to exit. Without this, an exit animation that starts before an enter animation finishes will have its state clobbered by the exit's finishTransition call. Next, make pip-enter transitions queue-up so that they don't interleave before other queued transitions (very common during CTS). Bug: 231150615 Test: atest PinnedStackTests Change-Id: I7f162c0b1f24ab845770b805c8fae2252814945e
This commit is contained in:
@@ -3061,6 +3061,12 @@
|
||||
"group": "WM_DEBUG_STATES",
|
||||
"at": "com\/android\/server\/wm\/RootWindowContainer.java"
|
||||
},
|
||||
"898260097": {
|
||||
"message": "Creating Pending Pip-Enter: %s",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
|
||||
},
|
||||
"898863925": {
|
||||
"message": "Attempted to add QS dialog window with unknown token %s. Aborting.",
|
||||
"level": "WARN",
|
||||
|
||||
@@ -145,6 +145,11 @@ public class PipTransition extends PipTransitionController {
|
||||
if (destinationBounds != null) {
|
||||
mExitDestinationBounds.set(destinationBounds);
|
||||
}
|
||||
final PipAnimationController.PipTransitionAnimator animator =
|
||||
mPipAnimationController.getCurrentAnimator();
|
||||
if (animator != null && animator.isRunning()) {
|
||||
animator.cancel();
|
||||
}
|
||||
mExitTransition = mTransitions.startTransition(type, out, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -377,6 +377,7 @@ public class Transitions implements RemoteCallable<Transitions> {
|
||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Invalid root leash (%s): %s",
|
||||
transitionToken, info);
|
||||
t.apply();
|
||||
finishT.apply();
|
||||
onAbort(transitionToken);
|
||||
return;
|
||||
}
|
||||
@@ -400,6 +401,7 @@ public class Transitions implements RemoteCallable<Transitions> {
|
||||
}
|
||||
if (nonTaskChange && transferStartingWindow) {
|
||||
t.apply();
|
||||
finishT.apply();
|
||||
// Treat this as an abort since we are bypassing any merge logic and effectively
|
||||
// finishing immediately.
|
||||
onAbort(transitionToken);
|
||||
|
||||
@@ -65,6 +65,7 @@ import static android.provider.Settings.System.FONT_SCALE;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.view.Display.INVALID_DISPLAY;
|
||||
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_LAUNCHER_CLEAR_SNAPSHOT;
|
||||
import static android.view.WindowManager.TRANSIT_PIP;
|
||||
|
||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
|
||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
|
||||
@@ -237,6 +238,7 @@ import com.android.internal.notification.SystemNotificationChannels;
|
||||
import com.android.internal.os.TransferPipe;
|
||||
import com.android.internal.policy.AttributeCache;
|
||||
import com.android.internal.policy.KeyguardDismissCallback;
|
||||
import com.android.internal.protolog.ProtoLogGroup;
|
||||
import com.android.internal.protolog.common.ProtoLog;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.FastPrintWriter;
|
||||
@@ -3463,6 +3465,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a transition for this pip entry. We guarantee that this gets its own transition
|
||||
// by queueing this transition on SyncEngine. This is shared by all the entry paths.
|
||||
final Transition transition = getTransitionController().isShellTransitionsEnabled()
|
||||
? new Transition(TRANSIT_PIP, 0 /* flags */,
|
||||
getTransitionController(), mWindowManager.mSyncEngine)
|
||||
: null;
|
||||
|
||||
final Runnable enterPipRunnable = () -> {
|
||||
synchronized (mGlobalLock) {
|
||||
if (r.getParent() == null) {
|
||||
@@ -3471,7 +3480,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
}
|
||||
r.setPictureInPictureParams(params);
|
||||
mRootWindowContainer.moveActivityToPinnedRootTask(r,
|
||||
null /* launchIntoPipHostActivity */, "enterPictureInPictureMode");
|
||||
null /* launchIntoPipHostActivity */, "enterPictureInPictureMode",
|
||||
transition);
|
||||
final Task task = r.getTask();
|
||||
// Continue the pausing process after entering pip.
|
||||
if (task.getPausingActivity() == r) {
|
||||
@@ -3488,12 +3498,36 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
mActivityClientController.dismissKeyguard(r.token, new KeyguardDismissCallback() {
|
||||
@Override
|
||||
public void onDismissSucceeded() {
|
||||
mH.post(enterPipRunnable);
|
||||
if (mWindowManager.mSyncEngine.hasActiveSync()) {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
"Creating Pending Pip-Enter: %s", transition);
|
||||
mWindowManager.mSyncEngine.queueSyncSet(
|
||||
() -> getTransitionController().moveToCollecting(transition),
|
||||
enterPipRunnable);
|
||||
} else {
|
||||
// Move to collecting immediately to "claim" the sync-engine for this
|
||||
// transition.
|
||||
if (transition != null) {
|
||||
getTransitionController().moveToCollecting(transition);
|
||||
}
|
||||
mH.post(enterPipRunnable);
|
||||
}
|
||||
}
|
||||
}, null /* message */);
|
||||
} else {
|
||||
// Enter picture in picture immediately otherwise
|
||||
enterPipRunnable.run();
|
||||
if (mWindowManager.mSyncEngine.hasActiveSync()) {
|
||||
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
|
||||
"Creating Pending Pip-Enter: %s", transition);
|
||||
mWindowManager.mSyncEngine.queueSyncSet(
|
||||
() -> getTransitionController().moveToCollecting(transition),
|
||||
enterPipRunnable);
|
||||
} else {
|
||||
if (transition != null) {
|
||||
getTransitionController().moveToCollecting(transition);
|
||||
}
|
||||
enterPipRunnable.run();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1977,16 +1977,21 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
|
||||
|
||||
void moveActivityToPinnedRootTask(@NonNull ActivityRecord r,
|
||||
@Nullable ActivityRecord launchIntoPipHostActivity, String reason) {
|
||||
moveActivityToPinnedRootTask(r, launchIntoPipHostActivity, reason, null /* transition */);
|
||||
}
|
||||
|
||||
void moveActivityToPinnedRootTask(@NonNull ActivityRecord r,
|
||||
@Nullable ActivityRecord launchIntoPipHostActivity, String reason,
|
||||
@Nullable Transition transition) {
|
||||
final TaskDisplayArea taskDisplayArea = r.getDisplayArea();
|
||||
final Task task = r.getTask();
|
||||
final Task rootTask;
|
||||
|
||||
Transition newTransition = null;
|
||||
// Create a transition now to collect the current pinned Task dismiss. Only do the
|
||||
// create here as the Task (trigger) to enter PIP is not ready yet.
|
||||
Transition newTransition = transition;
|
||||
// Create a transition now (if not provided) to collect the current pinned Task dismiss.
|
||||
// Only do the create here as the Task (trigger) to enter PIP is not ready yet.
|
||||
final TransitionController transitionController = task.mTransitionController;
|
||||
if (!transitionController.isCollecting()
|
||||
if (newTransition == null && !transitionController.isCollecting()
|
||||
&& transitionController.getTransitionPlayer() != null) {
|
||||
newTransition = transitionController.createTransition(TRANSIT_PIP);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user