Merge "Check finishing opaque activity for closing TaskFragment"
This commit is contained in:
@@ -904,37 +904,46 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|
||||
* starting (about to be visible) activity that is fullscreen (opaque).
|
||||
* @param starting The currently starting activity or null if there is none.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
boolean isTranslucent(ActivityRecord starting) {
|
||||
boolean isTranslucent(@Nullable ActivityRecord starting) {
|
||||
if (!isAttached() || isForceHidden() || isForceTranslucent()) {
|
||||
return true;
|
||||
}
|
||||
final PooledPredicate p = PooledLambda.obtainPredicate(TaskFragment::isOpaqueActivity,
|
||||
PooledLambda.__(ActivityRecord.class), starting);
|
||||
PooledLambda.__(ActivityRecord.class), starting, false /* including*/);
|
||||
final ActivityRecord opaque = getActivity(p);
|
||||
p.recycle();
|
||||
return opaque == null;
|
||||
}
|
||||
|
||||
private static boolean isOpaqueActivity(ActivityRecord r, ActivityRecord starting) {
|
||||
if (r.finishing) {
|
||||
// We don't factor in finishing activities when determining translucency since
|
||||
// they will be gone soon.
|
||||
return false;
|
||||
/**
|
||||
* Whether the TaskFragment should be treated as translucent for the current transition.
|
||||
* This is different from {@link #isTranslucent(ActivityRecord)} as this function also checks
|
||||
* finishing activities when the TaskFragment itself is becoming invisible.
|
||||
*/
|
||||
boolean isTranslucentForTransition() {
|
||||
if (!isAttached() || isForceHidden() || isForceTranslucent()) {
|
||||
return true;
|
||||
}
|
||||
// Including finishing Activity if the TaskFragment is becoming invisible in the transition.
|
||||
final boolean includingFinishing = !isVisibleRequested();
|
||||
final PooledPredicate p = PooledLambda.obtainPredicate(TaskFragment::isOpaqueActivity,
|
||||
PooledLambda.__(ActivityRecord.class), null /* starting */, includingFinishing);
|
||||
final ActivityRecord opaque = getActivity(p);
|
||||
p.recycle();
|
||||
return opaque == null;
|
||||
}
|
||||
|
||||
private static boolean isOpaqueActivity(@NonNull ActivityRecord r,
|
||||
@Nullable ActivityRecord starting, boolean includingFinishing) {
|
||||
if (!r.visibleIgnoringKeyguard && r != starting) {
|
||||
// Also ignore invisible activities that are not the currently starting
|
||||
// activity (about to be visible).
|
||||
return false;
|
||||
}
|
||||
|
||||
if (r.occludesParent()) {
|
||||
// Root task isn't translucent if it has at least one fullscreen activity
|
||||
// that is visible.
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
// TaskFragment isn't translucent if it has at least one fullscreen activity that is
|
||||
// visible.
|
||||
return r.occludesParent(includingFinishing);
|
||||
}
|
||||
|
||||
ActivityRecord getTopNonFinishingActivity() {
|
||||
|
||||
@@ -1447,22 +1447,25 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
|
||||
|
||||
private static boolean isTranslucent(@NonNull WindowContainer wc) {
|
||||
final TaskFragment taskFragment = wc.asTaskFragment();
|
||||
if (taskFragment != null) {
|
||||
if (taskFragment.isTranslucent(null /* starting */)) {
|
||||
return true;
|
||||
}
|
||||
final TaskFragment adjacentTaskFragment = taskFragment.getAdjacentTaskFragment();
|
||||
if (adjacentTaskFragment != null) {
|
||||
// Treat the TaskFragment as translucent if its adjacent TF is, otherwise everything
|
||||
// behind two adjacent TaskFragments are occluded.
|
||||
return adjacentTaskFragment.isTranslucent(null /* starting */);
|
||||
}
|
||||
if (taskFragment == null) {
|
||||
return !wc.fillsParent();
|
||||
}
|
||||
|
||||
// Check containers differently as they are affected by child visibility.
|
||||
|
||||
if (taskFragment.isTranslucentForTransition()) {
|
||||
// TaskFragment doesn't contain occluded ActivityRecord.
|
||||
return true;
|
||||
}
|
||||
final TaskFragment adjacentTaskFragment = taskFragment.getAdjacentTaskFragment();
|
||||
if (adjacentTaskFragment != null) {
|
||||
// When the TaskFragment has an adjacent TaskFragment, sibling behind them should be
|
||||
// hidden unless any of them are translucent.
|
||||
return adjacentTaskFragment.isTranslucentForTransition();
|
||||
} else {
|
||||
// Non-filling without adjacent is considered as translucent.
|
||||
return !wc.fillsParent();
|
||||
}
|
||||
// TODO(b/172695805): hierarchical check. This is non-trivial because for containers
|
||||
// it is effected by child visibility but needs to work even
|
||||
// before visibility is committed. This means refactoring some
|
||||
// checks to use requested visibility.
|
||||
return !wc.fillsParent();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -704,15 +704,15 @@ public class TransitionTests extends WindowTestsBase {
|
||||
ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
|
||||
ArraySet<WindowContainer> participants = transition.mParticipants;
|
||||
|
||||
final Task newTask = createTask(mDisplayContent);
|
||||
doReturn(false).when(newTask).isTranslucent(any());
|
||||
final Task oldTask = createTask(mDisplayContent);
|
||||
doReturn(false).when(oldTask).isTranslucent(any());
|
||||
final Task newTask = createTask(mDisplayContent);
|
||||
|
||||
final ActivityRecord closing = createActivityRecord(oldTask);
|
||||
closing.setOccludesParent(true);
|
||||
closing.visibleIgnoringKeyguard = true;
|
||||
final ActivityRecord opening = createActivityRecord(newTask);
|
||||
opening.setOccludesParent(false);
|
||||
opening.setOccludesParent(true);
|
||||
opening.visibleIgnoringKeyguard = true;
|
||||
// Start states.
|
||||
changes.put(newTask, new Transition.ChangeInfo(newTask, false /* vis */, true /* exChg */));
|
||||
changes.put(oldTask, new Transition.ChangeInfo(oldTask, true /* vis */, false /* exChg */));
|
||||
@@ -735,8 +735,8 @@ public class TransitionTests extends WindowTestsBase {
|
||||
assertEquals(2, info.getChanges().size());
|
||||
assertEquals(transit, info.getType());
|
||||
|
||||
assertTrue((info.getChanges().get(0).getFlags() & FLAG_TRANSLUCENT) == 0);
|
||||
assertTrue((info.getChanges().get(1).getFlags() & FLAG_TRANSLUCENT) == 0);
|
||||
assertFalse(info.getChanges().get(0).hasFlags(FLAG_TRANSLUCENT));
|
||||
assertFalse(info.getChanges().get(1).hasFlags(FLAG_TRANSLUCENT));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -745,15 +745,15 @@ public class TransitionTests extends WindowTestsBase {
|
||||
ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
|
||||
ArraySet<WindowContainer> participants = transition.mParticipants;
|
||||
|
||||
final Task newTask = createTask(mDisplayContent);
|
||||
doReturn(true).when(newTask).isTranslucent(any());
|
||||
final Task oldTask = createTask(mDisplayContent);
|
||||
doReturn(false).when(oldTask).isTranslucent(any());
|
||||
final Task newTask = createTask(mDisplayContent);
|
||||
|
||||
final ActivityRecord closing = createActivityRecord(oldTask);
|
||||
closing.setOccludesParent(true);
|
||||
closing.visibleIgnoringKeyguard = true;
|
||||
final ActivityRecord opening = createActivityRecord(newTask);
|
||||
opening.setOccludesParent(false);
|
||||
opening.visibleIgnoringKeyguard = true;
|
||||
// Start states.
|
||||
changes.put(newTask, new Transition.ChangeInfo(newTask, false /* vis */, true /* exChg */));
|
||||
changes.put(oldTask, new Transition.ChangeInfo(oldTask, true /* vis */, false /* exChg */));
|
||||
@@ -776,8 +776,186 @@ public class TransitionTests extends WindowTestsBase {
|
||||
assertEquals(2, info.getChanges().size());
|
||||
assertEquals(transit, info.getType());
|
||||
|
||||
assertTrue((info.getChanges().get(0).getFlags() & FLAG_TRANSLUCENT) != 0);
|
||||
assertTrue((info.getChanges().get(1).getFlags() & FLAG_TRANSLUCENT) == 0);
|
||||
assertTrue(info.getChanges().get(0).hasFlags(FLAG_TRANSLUCENT));
|
||||
assertFalse(info.getChanges().get(1).hasFlags(FLAG_TRANSLUCENT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenOpaqueTaskFragment() {
|
||||
final Transition transition = createTestTransition(TRANSIT_OPEN);
|
||||
ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
|
||||
ArraySet<WindowContainer> participants = transition.mParticipants;
|
||||
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final TaskFragment closingTaskFragment = createTaskFragmentWithActivity(task);
|
||||
final TaskFragment openingTaskFragment = createTaskFragmentWithActivity(task);
|
||||
|
||||
final ActivityRecord closing = closingTaskFragment.getTopMostActivity();
|
||||
closing.setOccludesParent(true);
|
||||
closing.visibleIgnoringKeyguard = true;
|
||||
final ActivityRecord opening = openingTaskFragment.getTopMostActivity();
|
||||
opening.setOccludesParent(true);
|
||||
opening.visibleIgnoringKeyguard = true;
|
||||
// Start states.
|
||||
changes.put(openingTaskFragment, new Transition.ChangeInfo(openingTaskFragment,
|
||||
false /* vis */, true /* exChg */));
|
||||
changes.put(closingTaskFragment, new Transition.ChangeInfo(closingTaskFragment,
|
||||
true /* vis */, false /* exChg */));
|
||||
changes.put(opening, new Transition.ChangeInfo(opening, false /* vis */, true /* exChg */));
|
||||
changes.put(closing, new Transition.ChangeInfo(closing, true /* vis */, false /* exChg */));
|
||||
fillChangeMap(changes, openingTaskFragment);
|
||||
// End states.
|
||||
closing.setVisibleRequested(false);
|
||||
opening.setVisibleRequested(true);
|
||||
|
||||
final int transit = transition.mType;
|
||||
int flags = 0;
|
||||
|
||||
// Check basic both tasks participating
|
||||
participants.add(closingTaskFragment);
|
||||
participants.add(openingTaskFragment);
|
||||
ArrayList<Transition.ChangeInfo> targets =
|
||||
Transition.calculateTargets(participants, changes);
|
||||
TransitionInfo info = Transition.calculateTransitionInfo(transit, flags, targets, mMockT);
|
||||
assertEquals(2, info.getChanges().size());
|
||||
assertEquals(transit, info.getType());
|
||||
|
||||
assertFalse(info.getChanges().get(0).hasFlags(FLAG_TRANSLUCENT));
|
||||
assertFalse(info.getChanges().get(1).hasFlags(FLAG_TRANSLUCENT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenTranslucentTaskFragment() {
|
||||
final Transition transition = createTestTransition(TRANSIT_OPEN);
|
||||
ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
|
||||
ArraySet<WindowContainer> participants = transition.mParticipants;
|
||||
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final TaskFragment closingTaskFragment = createTaskFragmentWithActivity(task);
|
||||
final TaskFragment openingTaskFragment = createTaskFragmentWithActivity(task);
|
||||
|
||||
final ActivityRecord closing = closingTaskFragment.getTopMostActivity();
|
||||
closing.setOccludesParent(true);
|
||||
closing.visibleIgnoringKeyguard = true;
|
||||
final ActivityRecord opening = openingTaskFragment.getTopMostActivity();
|
||||
opening.setOccludesParent(false);
|
||||
opening.visibleIgnoringKeyguard = true;
|
||||
// Start states.
|
||||
changes.put(openingTaskFragment, new Transition.ChangeInfo(openingTaskFragment,
|
||||
false /* vis */, true /* exChg */));
|
||||
changes.put(closingTaskFragment, new Transition.ChangeInfo(closingTaskFragment,
|
||||
true /* vis */, false /* exChg */));
|
||||
changes.put(opening, new Transition.ChangeInfo(opening, false /* vis */, true /* exChg */));
|
||||
changes.put(closing, new Transition.ChangeInfo(closing, true /* vis */, false /* exChg */));
|
||||
fillChangeMap(changes, openingTaskFragment);
|
||||
// End states.
|
||||
closing.setVisibleRequested(false);
|
||||
opening.setVisibleRequested(true);
|
||||
|
||||
final int transit = transition.mType;
|
||||
int flags = 0;
|
||||
|
||||
// Check basic both tasks participating
|
||||
participants.add(closingTaskFragment);
|
||||
participants.add(openingTaskFragment);
|
||||
ArrayList<Transition.ChangeInfo> targets =
|
||||
Transition.calculateTargets(participants, changes);
|
||||
TransitionInfo info = Transition.calculateTransitionInfo(transit, flags, targets, mMockT);
|
||||
assertEquals(2, info.getChanges().size());
|
||||
assertEquals(transit, info.getType());
|
||||
|
||||
assertTrue(info.getChanges().get(0).hasFlags(FLAG_TRANSLUCENT));
|
||||
assertFalse(info.getChanges().get(1).hasFlags(FLAG_TRANSLUCENT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseOpaqueTaskFragment_withFinishingActivity() {
|
||||
final Transition transition = createTestTransition(TRANSIT_CLOSE);
|
||||
ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
|
||||
ArraySet<WindowContainer> participants = transition.mParticipants;
|
||||
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final TaskFragment openingTaskFragment = createTaskFragmentWithActivity(task);
|
||||
final TaskFragment closingTaskFragment = createTaskFragmentWithActivity(task);
|
||||
|
||||
final ActivityRecord opening = openingTaskFragment.getTopMostActivity();
|
||||
opening.setOccludesParent(true);
|
||||
opening.visibleIgnoringKeyguard = true;
|
||||
final ActivityRecord closing = closingTaskFragment.getTopMostActivity();
|
||||
closing.setOccludesParent(true);
|
||||
closing.visibleIgnoringKeyguard = true;
|
||||
closing.finishing = true;
|
||||
// Start states.
|
||||
changes.put(openingTaskFragment, new Transition.ChangeInfo(openingTaskFragment,
|
||||
false /* vis */, true /* exChg */));
|
||||
changes.put(closingTaskFragment, new Transition.ChangeInfo(closingTaskFragment,
|
||||
true /* vis */, false /* exChg */));
|
||||
changes.put(opening, new Transition.ChangeInfo(opening, false /* vis */, true /* exChg */));
|
||||
changes.put(closing, new Transition.ChangeInfo(closing, true /* vis */, false /* exChg */));
|
||||
fillChangeMap(changes, openingTaskFragment);
|
||||
// End states.
|
||||
closing.setVisibleRequested(false);
|
||||
opening.setVisibleRequested(true);
|
||||
|
||||
final int transit = transition.mType;
|
||||
int flags = 0;
|
||||
|
||||
// Check basic both tasks participating
|
||||
participants.add(closingTaskFragment);
|
||||
participants.add(openingTaskFragment);
|
||||
ArrayList<Transition.ChangeInfo> targets =
|
||||
Transition.calculateTargets(participants, changes);
|
||||
TransitionInfo info = Transition.calculateTransitionInfo(transit, flags, targets, mMockT);
|
||||
assertEquals(2, info.getChanges().size());
|
||||
assertEquals(transit, info.getType());
|
||||
|
||||
assertFalse(info.getChanges().get(0).hasFlags(FLAG_TRANSLUCENT));
|
||||
assertFalse(info.getChanges().get(1).hasFlags(FLAG_TRANSLUCENT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseTranslucentTaskFragment_withFinishingActivity() {
|
||||
final Transition transition = createTestTransition(TRANSIT_CLOSE);
|
||||
ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
|
||||
ArraySet<WindowContainer> participants = transition.mParticipants;
|
||||
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final TaskFragment openingTaskFragment = createTaskFragmentWithActivity(task);
|
||||
final TaskFragment closingTaskFragment = createTaskFragmentWithActivity(task);
|
||||
|
||||
final ActivityRecord opening = openingTaskFragment.getTopMostActivity();
|
||||
opening.setOccludesParent(true);
|
||||
opening.visibleIgnoringKeyguard = true;
|
||||
final ActivityRecord closing = closingTaskFragment.getTopMostActivity();
|
||||
closing.setOccludesParent(false);
|
||||
closing.visibleIgnoringKeyguard = true;
|
||||
closing.finishing = true;
|
||||
// Start states.
|
||||
changes.put(openingTaskFragment, new Transition.ChangeInfo(openingTaskFragment,
|
||||
false /* vis */, true /* exChg */));
|
||||
changes.put(closingTaskFragment, new Transition.ChangeInfo(closingTaskFragment,
|
||||
true /* vis */, false /* exChg */));
|
||||
changes.put(opening, new Transition.ChangeInfo(opening, false /* vis */, true /* exChg */));
|
||||
changes.put(closing, new Transition.ChangeInfo(closing, true /* vis */, false /* exChg */));
|
||||
fillChangeMap(changes, openingTaskFragment);
|
||||
// End states.
|
||||
closing.setVisibleRequested(false);
|
||||
opening.setVisibleRequested(true);
|
||||
|
||||
final int transit = transition.mType;
|
||||
int flags = 0;
|
||||
|
||||
// Check basic both tasks participating
|
||||
participants.add(closingTaskFragment);
|
||||
participants.add(openingTaskFragment);
|
||||
ArrayList<Transition.ChangeInfo> targets =
|
||||
Transition.calculateTargets(participants, changes);
|
||||
TransitionInfo info = Transition.calculateTransitionInfo(transit, flags, targets, mMockT);
|
||||
assertEquals(2, info.getChanges().size());
|
||||
assertEquals(transit, info.getType());
|
||||
|
||||
assertTrue(info.getChanges().get(0).hasFlags(FLAG_TRANSLUCENT));
|
||||
assertFalse(info.getChanges().get(1).hasFlags(FLAG_TRANSLUCENT));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user