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 WindowContainer<?> parent = getParent();
|
||||||
final Task thisTask = asTask();
|
final Task thisTask = asTask();
|
||||||
if (thisTask != null && parent.asTask() == null
|
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.
|
// Keep transient-hide root tasks visible. Non-root tasks still follow standard rule.
|
||||||
return TASK_FRAGMENT_VISIBILITY_VISIBLE;
|
return TASK_FRAGMENT_VISIBILITY_VISIBLE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -407,6 +407,36 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
|
|||||||
return false;
|
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) {
|
boolean canApplyDim(@NonNull Task task) {
|
||||||
if (mTransientLaunches == null) return true;
|
if (mTransientLaunches == null) return true;
|
||||||
final Dimmer dimmer = task.getDimmer();
|
final Dimmer dimmer = task.getDimmer();
|
||||||
|
|||||||
@@ -477,15 +477,22 @@ class TransitionController {
|
|||||||
if (mCollectingTransition != null && mCollectingTransition.isInTransientHide(task)) {
|
if (mCollectingTransition != null && mCollectingTransition.isInTransientHide(task)) {
|
||||||
return true;
|
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) {
|
for (int i = mPlayingTransitions.size() - 1; i >= 0; --i) {
|
||||||
if (mPlayingTransitions.get(i).isInTransientHide(task)) return true;
|
if (mPlayingTransitions.get(i).isInTransientHide(task)) return true;
|
||||||
}
|
}
|
||||||
return false;
|
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) {
|
boolean canApplyDim(@Nullable Task task) {
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
// Always allow non-activity window.
|
// Always allow non-activity window.
|
||||||
|
|||||||
@@ -656,7 +656,7 @@ public class RootTaskTests extends WindowTestsBase {
|
|||||||
topSplitPrimary.getVisibility(null /* starting */));
|
topSplitPrimary.getVisibility(null /* starting */));
|
||||||
// Make primary split root transient-hide.
|
// Make primary split root transient-hide.
|
||||||
spyOn(splitPrimary.mTransitionController);
|
spyOn(splitPrimary.mTransitionController);
|
||||||
doReturn(true).when(splitPrimary.mTransitionController).isTransientHide(
|
doReturn(true).when(splitPrimary.mTransitionController).isTransientVisible(
|
||||||
organizer.mPrimary);
|
organizer.mPrimary);
|
||||||
// The split root and its top become visible.
|
// The split root and its top become visible.
|
||||||
assertEquals(TASK_FRAGMENT_VISIBILITY_VISIBLE,
|
assertEquals(TASK_FRAGMENT_VISIBILITY_VISIBLE,
|
||||||
|
|||||||
@@ -1483,6 +1483,47 @@ public class TransitionTests extends WindowTestsBase {
|
|||||||
assertTrue(enteringAnimReports.contains(activity2));
|
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
|
@Test
|
||||||
public void testNotReadyPushPop() {
|
public void testNotReadyPushPop() {
|
||||||
final TransitionController controller = new TestTransitionController(mAtm);
|
final TransitionController controller = new TestTransitionController(mAtm);
|
||||||
|
|||||||
Reference in New Issue
Block a user