Merge "Allow launching placeholder when the TaskFragment is visible" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
04f120732a
@@ -425,12 +425,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
if (container != null) {
|
||||
// Cleanup if the TaskFragment vanished is not requested by the organizer.
|
||||
removeContainer(container);
|
||||
// Make sure the top container is updated.
|
||||
final TaskFragmentContainer newTopContainer = getTopActiveContainer(
|
||||
container.getTaskId());
|
||||
if (newTopContainer != null) {
|
||||
updateContainer(wct, newTopContainer);
|
||||
}
|
||||
// Make sure the containers in the Task are up-to-date.
|
||||
updateContainersInTaskIfVisible(wct, container.getTaskId());
|
||||
}
|
||||
cleanupTaskFragment(taskFragmentInfo.getFragmentToken());
|
||||
}
|
||||
@@ -470,6 +466,13 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
updateContainersInTask(wct, taskContainer);
|
||||
}
|
||||
|
||||
void updateContainersInTaskIfVisible(@NonNull WindowContainerTransaction wct, int taskId) {
|
||||
final TaskContainer taskContainer = getTaskContainer(taskId);
|
||||
if (taskContainer != null && taskContainer.isVisible()) {
|
||||
updateContainersInTask(wct, taskContainer);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateContainersInTask(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull TaskContainer taskContainer) {
|
||||
// Update all TaskFragments in the Task. Make a copy of the list since some may be
|
||||
@@ -1320,9 +1323,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
void removeContainer(@NonNull TaskFragmentContainer container) {
|
||||
// Remove all split containers that included this one
|
||||
final TaskContainer taskContainer = container.getTaskContainer();
|
||||
if (taskContainer == null) {
|
||||
return;
|
||||
}
|
||||
taskContainer.mContainers.remove(container);
|
||||
// Marked as a pending removal which will be removed after it is actually removed on the
|
||||
// server side (#onTaskFragmentVanished).
|
||||
@@ -1515,14 +1515,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
}
|
||||
|
||||
final TaskFragmentContainer container = getContainerWithActivity(activity);
|
||||
// Don't launch placeholder if the container is occluded.
|
||||
if (container != null && container != getTopActiveContainer(container.getTaskId())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final SplitContainer splitContainer = getActiveSplitForContainer(container);
|
||||
if (splitContainer != null && container.equals(splitContainer.getPrimaryContainer())) {
|
||||
// Don't launch placeholder in primary split container
|
||||
if (container != null && !allowLaunchPlaceholder(container)) {
|
||||
// We don't allow activity in this TaskFragment to launch placeholder.
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1550,6 +1544,32 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Whether or not to allow activity in this container to launch placeholder. */
|
||||
@GuardedBy("mLock")
|
||||
private boolean allowLaunchPlaceholder(@NonNull TaskFragmentContainer container) {
|
||||
final TaskFragmentContainer topContainer = getTopActiveContainer(container.getTaskId());
|
||||
if (container != topContainer) {
|
||||
// The container is not the top most.
|
||||
if (!container.isVisible()) {
|
||||
// In case the container is visible (the one on top may be transparent), we may
|
||||
// still want to launch placeholder even if it is not the top most.
|
||||
return false;
|
||||
}
|
||||
if (topContainer.isWaitingActivityAppear()) {
|
||||
// When the top container appeared info is not sent by the server yet, the visible
|
||||
// check above may not be reliable.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
final SplitContainer splitContainer = getActiveSplitForContainer(container);
|
||||
if (splitContainer != null && container.equals(splitContainer.getPrimaryContainer())) {
|
||||
// Don't launch placeholder for primary split container.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the activity options for starting the placeholder activity. In case the placeholder is
|
||||
* launched when the Task is in the background, we don't want to bring the Task to the front.
|
||||
|
||||
@@ -154,12 +154,8 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
||||
void cleanupContainer(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull TaskFragmentContainer container, boolean shouldFinishDependent) {
|
||||
container.finish(shouldFinishDependent, this, wct, mController);
|
||||
|
||||
final TaskFragmentContainer newTopContainer = mController.getTopActiveContainer(
|
||||
container.getTaskId());
|
||||
if (newTopContainer != null) {
|
||||
mController.updateContainer(wct, newTopContainer);
|
||||
}
|
||||
// Make sure the containers in the Task is up-to-date.
|
||||
mController.updateContainersInTaskIfVisible(wct, container.getTaskId());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -184,6 +184,11 @@ class TaskFragmentContainer {
|
||||
return allActivities;
|
||||
}
|
||||
|
||||
/** Whether this TaskFragment is visible. */
|
||||
boolean isVisible() {
|
||||
return mInfo != null && mInfo.isVisible();
|
||||
}
|
||||
|
||||
/** Whether the TaskFragment is in an intermediate state waiting for the server update.*/
|
||||
boolean isInIntermediateState() {
|
||||
if (mInfo == null) {
|
||||
|
||||
@@ -163,11 +163,17 @@ public class EmbeddingTestUtils {
|
||||
/** Creates a mock TaskFragmentInfo for the given TaskFragment. */
|
||||
static TaskFragmentInfo createMockTaskFragmentInfo(@NonNull TaskFragmentContainer container,
|
||||
@NonNull Activity activity) {
|
||||
return createMockTaskFragmentInfo(container, activity, true /* isVisible */);
|
||||
}
|
||||
|
||||
/** Creates a mock TaskFragmentInfo for the given TaskFragment. */
|
||||
static TaskFragmentInfo createMockTaskFragmentInfo(@NonNull TaskFragmentContainer container,
|
||||
@NonNull Activity activity, boolean isVisible) {
|
||||
return new TaskFragmentInfo(container.getTaskFragmentToken(),
|
||||
mock(WindowContainerToken.class),
|
||||
new Configuration(),
|
||||
1,
|
||||
true /* isVisible */,
|
||||
isVisible,
|
||||
Collections.singletonList(activity.getActivityToken()),
|
||||
new Point(),
|
||||
false /* isTaskClearedForReuse */,
|
||||
|
||||
@@ -1254,6 +1254,68 @@ public class SplitControllerTest {
|
||||
verify(mEmbeddingCallback).accept(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLaunchPlaceholderIfNecessary_nonEmbeddedActivity() {
|
||||
// Launch placeholder for non embedded activity.
|
||||
setupPlaceholderRule(mActivity);
|
||||
mTransactionManager.startNewTransaction();
|
||||
mSplitController.launchPlaceholderIfNecessary(mTransaction, mActivity,
|
||||
true /* isOnCreated */);
|
||||
|
||||
verify(mTransaction).startActivityInTaskFragment(any(), any(), eq(PLACEHOLDER_INTENT),
|
||||
any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLaunchPlaceholderIfNecessary_embeddedInTopTaskFragment() {
|
||||
// Launch placeholder for activity in top TaskFragment.
|
||||
setupPlaceholderRule(mActivity);
|
||||
mTransactionManager.startNewTransaction();
|
||||
final TaskFragmentContainer container = mSplitController.newContainer(mActivity, TASK_ID);
|
||||
mSplitController.launchPlaceholderIfNecessary(mTransaction, mActivity,
|
||||
true /* isOnCreated */);
|
||||
|
||||
assertTrue(container.hasActivity(mActivity.getActivityToken()));
|
||||
verify(mTransaction).startActivityInTaskFragment(any(), any(), eq(PLACEHOLDER_INTENT),
|
||||
any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLaunchPlaceholderIfNecessary_embeddedBelowTaskFragment() {
|
||||
// Do not launch placeholder for invisible activity below the top TaskFragment.
|
||||
setupPlaceholderRule(mActivity);
|
||||
mTransactionManager.startNewTransaction();
|
||||
final TaskFragmentContainer bottomTf = mSplitController.newContainer(mActivity, TASK_ID);
|
||||
final TaskFragmentContainer topTf = mSplitController.newContainer(new Intent(), mActivity,
|
||||
TASK_ID);
|
||||
bottomTf.setInfo(mTransaction, createMockTaskFragmentInfo(bottomTf, mActivity,
|
||||
false /* isVisible */));
|
||||
topTf.setInfo(mTransaction, createMockTaskFragmentInfo(topTf, createMockActivity()));
|
||||
assertFalse(bottomTf.isVisible());
|
||||
mSplitController.launchPlaceholderIfNecessary(mTransaction, mActivity,
|
||||
true /* isOnCreated */);
|
||||
|
||||
verify(mTransaction, never()).startActivityInTaskFragment(any(), any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLaunchPlaceholderIfNecessary_embeddedBelowTransparentTaskFragment() {
|
||||
// Launch placeholder for visible activity below the top TaskFragment.
|
||||
setupPlaceholderRule(mActivity);
|
||||
mTransactionManager.startNewTransaction();
|
||||
final TaskFragmentContainer bottomTf = mSplitController.newContainer(mActivity, TASK_ID);
|
||||
final TaskFragmentContainer topTf = mSplitController.newContainer(new Intent(), mActivity,
|
||||
TASK_ID);
|
||||
bottomTf.setInfo(mTransaction, createMockTaskFragmentInfo(bottomTf, mActivity,
|
||||
true /* isVisible */));
|
||||
topTf.setInfo(mTransaction, createMockTaskFragmentInfo(topTf, createMockActivity()));
|
||||
assertTrue(bottomTf.isVisible());
|
||||
mSplitController.launchPlaceholderIfNecessary(mTransaction, mActivity,
|
||||
true /* isOnCreated */);
|
||||
|
||||
verify(mTransaction).startActivityInTaskFragment(any(), any(), any(), any());
|
||||
}
|
||||
|
||||
/** Creates a mock activity in the organizer process. */
|
||||
private Activity createMockActivity() {
|
||||
return createMockActivity(TASK_ID);
|
||||
|
||||
@@ -500,6 +500,29 @@ public class TaskFragmentContainerTest {
|
||||
assertEquals(2, taskContainer.indexOf(tf1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsVisible() {
|
||||
final TaskContainer taskContainer = createTestTaskContainer();
|
||||
final TaskFragmentContainer container = new TaskFragmentContainer(
|
||||
null /* pendingAppearedActivity */, new Intent(), taskContainer, mController,
|
||||
null /* pairedPrimaryTaskFragment */);
|
||||
|
||||
// Not visible when there is not appeared.
|
||||
assertFalse(container.isVisible());
|
||||
|
||||
// Respect info.isVisible.
|
||||
TaskFragmentInfo info = createMockTaskFragmentInfo(container, mActivity,
|
||||
true /* isVisible */);
|
||||
container.setInfo(mTransaction, info);
|
||||
|
||||
assertTrue(container.isVisible());
|
||||
|
||||
info = createMockTaskFragmentInfo(container, mActivity, false /* isVisible */);
|
||||
container.setInfo(mTransaction, info);
|
||||
|
||||
assertFalse(container.isVisible());
|
||||
}
|
||||
|
||||
/** Creates a mock activity in the organizer process. */
|
||||
private Activity createMockActivity() {
|
||||
final Activity activity = mock(Activity.class);
|
||||
|
||||
@@ -2553,7 +2553,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|
||||
mRemoteToken.toWindowContainerToken(),
|
||||
getConfiguration(),
|
||||
getNonFinishingActivityCount(),
|
||||
isVisibleRequested(),
|
||||
shouldBeVisible(null /* starting */),
|
||||
childActivities,
|
||||
positionInParent,
|
||||
mClearedTaskForReuse,
|
||||
@@ -2849,6 +2849,8 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|
||||
if (parentTf != null) {
|
||||
parentTf.onActivityVisibleRequestedChanged();
|
||||
}
|
||||
// Send the info changed to update the TaskFragment visibility.
|
||||
sendTaskFragmentInfoChanged();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
Reference in New Issue
Block a user