Merge "Pause transient hide activities before resuming next" into udc-qpr-dev
This commit is contained in:
@@ -1020,7 +1020,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|
||||
final WindowContainer<?> parent = getParent();
|
||||
final Task thisTask = asTask();
|
||||
if (thisTask != null && parent.asTask() == null
|
||||
&& mTransitionController.isTransientHide(thisTask)) {
|
||||
&& mTransitionController.isTransientVisible(thisTask)) {
|
||||
// Keep transient-hide root tasks visible. Non-root tasks still follow standard rule.
|
||||
return TASK_FRAGMENT_VISIBILITY_VISIBLE;
|
||||
}
|
||||
|
||||
@@ -407,6 +407,36 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns {@code true} if the task should keep visible if this is a transient transition. */
|
||||
boolean isTransientVisible(@NonNull Task task) {
|
||||
if (mTransientLaunches == null) return false;
|
||||
int occludedCount = 0;
|
||||
final int numTransient = mTransientLaunches.size();
|
||||
for (int i = numTransient - 1; i >= 0; --i) {
|
||||
final Task transientRoot = mTransientLaunches.keyAt(i).getRootTask();
|
||||
if (transientRoot == null) continue;
|
||||
final WindowContainer<?> rootParent = transientRoot.getParent();
|
||||
if (rootParent == null || rootParent.getTopChild() == transientRoot) continue;
|
||||
final ActivityRecord topOpaque = mController.mAtm.mTaskSupervisor
|
||||
.mOpaqueActivityHelper.getOpaqueActivity(rootParent);
|
||||
if (transientRoot.compareTo(topOpaque.getRootTask()) < 0) {
|
||||
occludedCount++;
|
||||
}
|
||||
}
|
||||
if (occludedCount == numTransient) {
|
||||
for (int i = mTransientLaunches.size() - 1; i >= 0; --i) {
|
||||
if (mTransientLaunches.keyAt(i).isDescendantOf(task)) {
|
||||
// Keep transient activity visible until transition finished, so it won't pause
|
||||
// with transient-hide tasks that may delay resuming the next top.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Let transient-hide activities pause before transition is finished.
|
||||
return false;
|
||||
}
|
||||
return isInTransientHide(task);
|
||||
}
|
||||
|
||||
boolean canApplyDim(@NonNull Task task) {
|
||||
if (mTransientLaunches == null) return true;
|
||||
final Dimmer dimmer = task.getDimmer();
|
||||
|
||||
@@ -477,15 +477,22 @@ class TransitionController {
|
||||
if (mCollectingTransition != null && mCollectingTransition.isInTransientHide(task)) {
|
||||
return true;
|
||||
}
|
||||
for (int i = mWaitingTransitions.size() - 1; i >= 0; --i) {
|
||||
if (mWaitingTransitions.get(i).isInTransientHide(task)) return true;
|
||||
}
|
||||
for (int i = mPlayingTransitions.size() - 1; i >= 0; --i) {
|
||||
if (mPlayingTransitions.get(i).isInTransientHide(task)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isTransientVisible(@NonNull Task task) {
|
||||
if (mCollectingTransition != null && mCollectingTransition.isTransientVisible(task)) {
|
||||
return true;
|
||||
}
|
||||
for (int i = mPlayingTransitions.size() - 1; i >= 0; --i) {
|
||||
if (mPlayingTransitions.get(i).isTransientVisible(task)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean canApplyDim(@Nullable Task task) {
|
||||
if (task == null) {
|
||||
// Always allow non-activity window.
|
||||
|
||||
@@ -656,7 +656,7 @@ public class RootTaskTests extends WindowTestsBase {
|
||||
topSplitPrimary.getVisibility(null /* starting */));
|
||||
// Make primary split root transient-hide.
|
||||
spyOn(splitPrimary.mTransitionController);
|
||||
doReturn(true).when(splitPrimary.mTransitionController).isTransientHide(
|
||||
doReturn(true).when(splitPrimary.mTransitionController).isTransientVisible(
|
||||
organizer.mPrimary);
|
||||
// The split root and its top become visible.
|
||||
assertEquals(TASK_FRAGMENT_VISIBILITY_VISIBLE,
|
||||
|
||||
@@ -1483,6 +1483,47 @@ public class TransitionTests extends WindowTestsBase {
|
||||
assertTrue(enteringAnimReports.contains(activity2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsTransientVisible() {
|
||||
final ActivityRecord appB = new ActivityBuilder(mAtm).setCreateTask(true)
|
||||
.setVisible(false).build();
|
||||
final ActivityRecord recent = new ActivityBuilder(mAtm).setCreateTask(true)
|
||||
.setVisible(false).build();
|
||||
final ActivityRecord appA = new ActivityBuilder(mAtm).setCreateTask(true).build();
|
||||
final Task taskA = appA.getTask();
|
||||
final Task taskB = appB.getTask();
|
||||
final Task taskRecent = recent.getTask();
|
||||
registerTestTransitionPlayer();
|
||||
final TransitionController controller = mRootWindowContainer.mTransitionController;
|
||||
final Transition transition = createTestTransition(TRANSIT_OPEN, controller);
|
||||
controller.moveToCollecting(transition);
|
||||
transition.collect(recent);
|
||||
transition.collect(taskA);
|
||||
transition.setTransientLaunch(recent, taskA);
|
||||
taskRecent.moveToFront("move-recent-to-front");
|
||||
|
||||
// During collecting and playing, the recent is on top so it is visible naturally.
|
||||
// While B needs isTransientVisible to keep visibility because it is occluded by recents.
|
||||
assertFalse(controller.isTransientVisible(taskB));
|
||||
assertTrue(controller.isTransientVisible(taskA));
|
||||
assertFalse(controller.isTransientVisible(taskRecent));
|
||||
// Switch to playing state.
|
||||
transition.onTransactionReady(transition.getSyncId(), mMockT);
|
||||
assertTrue(controller.isTransientVisible(taskA));
|
||||
|
||||
// Switch to another task. For example, use gesture navigation to switch tasks.
|
||||
taskB.moveToFront("move-b-to-front");
|
||||
// The previous app (taskA) should be paused first so it loses transient visible. Because
|
||||
// visually it is taskA -> taskB, the pause -> resume order should be the same.
|
||||
assertFalse(controller.isTransientVisible(taskA));
|
||||
// Keep the recent visible so there won't be 2 activities pausing at the same time. It is
|
||||
// to avoid the latency to resume the current top, i.e. appB.
|
||||
assertTrue(controller.isTransientVisible(taskRecent));
|
||||
// The recent is paused after the transient transition is finished.
|
||||
controller.finishTransition(transition);
|
||||
assertFalse(controller.isTransientVisible(taskRecent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotReadyPushPop() {
|
||||
final TransitionController controller = new TestTransitionController(mAtm);
|
||||
|
||||
Reference in New Issue
Block a user