Merge "Add unit tests for SplitAttributes runtime APIs" into udc-dev
This commit is contained in:
@@ -308,7 +308,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
synchronized (mLock) {
|
||||
final List<TaskFragmentContainer> containers = taskContainer.mContainers;
|
||||
// Clean up the TaskFragmentContainers by the z-order from the lowest.
|
||||
for (int i = 0; i < containers.size() - 1; i++) {
|
||||
for (int i = 0; i < containers.size(); i++) {
|
||||
final TaskFragmentContainer container = containers.get(i);
|
||||
if (pendingFinishingContainers.contains(container)) {
|
||||
// Don't update records here to prevent double invocation.
|
||||
@@ -318,7 +318,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
}
|
||||
// Remove container records.
|
||||
removeContainers(taskContainer, pendingFinishingContainers);
|
||||
// Update the change to the client side.
|
||||
// Update the change to the server side.
|
||||
updateContainersInTaskIfVisible(wct, taskContainer.getTaskId());
|
||||
}
|
||||
});
|
||||
@@ -353,21 +353,25 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
@Override
|
||||
public void updateSplitAttributes(@NonNull IBinder splitInfoToken,
|
||||
@NonNull SplitAttributes splitAttributes) {
|
||||
Objects.requireNonNull(splitInfoToken);
|
||||
Objects.requireNonNull(splitAttributes);
|
||||
synchronized (mLock) {
|
||||
final SplitContainer splitContainer = getSplitContainer(splitInfoToken);
|
||||
if (splitContainer == null) {
|
||||
Log.w(TAG, "Cannot find SplitContainer for token:" + splitInfoToken);
|
||||
return;
|
||||
}
|
||||
WindowContainerTransaction wct = mTransactionManager.startNewTransaction()
|
||||
.getTransaction();
|
||||
// Override the default split Attributes so that it will be applied
|
||||
// if the SplitContainer is not visible currently.
|
||||
splitContainer.updateDefaultSplitAttributes(splitAttributes);
|
||||
|
||||
final TransactionRecord transactionRecord = mTransactionManager.startNewTransaction();
|
||||
final WindowContainerTransaction wct = transactionRecord.getTransaction();
|
||||
if (updateSplitContainerIfNeeded(splitContainer, wct, splitAttributes)) {
|
||||
splitContainer.updateDefaultSplitAttributes(splitAttributes);
|
||||
mTransactionManager.getCurrentTransactionRecord()
|
||||
.apply(false /* shouldApplyIndependently */);
|
||||
transactionRecord.apply(false /* shouldApplyIndependently */);
|
||||
} else {
|
||||
// Abort if the SplitContainer wasn't updated.
|
||||
mTransactionManager.getCurrentTransactionRecord().abort();
|
||||
transactionRecord.abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1559,8 +1563,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
*
|
||||
* @return {@code true} if the update succeed. Otherwise, returns {@code false}.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
@GuardedBy("mLock")
|
||||
private boolean updateSplitContainerIfNeeded(@NonNull SplitContainer splitContainer,
|
||||
boolean updateSplitContainerIfNeeded(@NonNull SplitContainer splitContainer,
|
||||
@NonNull WindowContainerTransaction wct, @Nullable SplitAttributes splitAttributes) {
|
||||
if (!isTopMostSplit(splitContainer)) {
|
||||
// Skip position update - it isn't the topmost split.
|
||||
@@ -1904,6 +1909,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
return null;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@Nullable
|
||||
@GuardedBy("mLock")
|
||||
SplitContainer getSplitContainer(@NonNull IBinder token) {
|
||||
|
||||
@@ -67,6 +67,7 @@ import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.Activity;
|
||||
@@ -82,6 +83,7 @@ import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.util.ArraySet;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowMetrics;
|
||||
import android.window.TaskFragmentInfo;
|
||||
@@ -100,12 +102,14 @@ import androidx.window.extensions.layout.WindowLayoutInfo;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
@@ -1323,6 +1327,125 @@ public class SplitControllerTest {
|
||||
verify(mTransaction).startActivityInTaskFragment(any(), any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFinishActivityStacks_emptySet_earlyReturn() {
|
||||
mSplitController.finishActivityStacks(Collections.emptySet());
|
||||
|
||||
verify(mSplitController, never()).updateContainersInTaskIfVisible(any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFinishActivityStacks_invalidStacks_earlyReturn() {
|
||||
mSplitController.finishActivityStacks(Collections.singleton(new Binder()));
|
||||
|
||||
verify(mSplitController, never()).updateContainersInTaskIfVisible(any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFinishActivityStacks_finishSingleActivityStack() {
|
||||
TaskFragmentContainer tf = mSplitController.newContainer(mActivity, TASK_ID);
|
||||
tf.setInfo(mTransaction, createMockTaskFragmentInfo(tf, mActivity));
|
||||
|
||||
List<TaskFragmentContainer> containers = mSplitController.mTaskContainers.get(TASK_ID)
|
||||
.mContainers;
|
||||
|
||||
assertEquals(containers.get(0), tf);
|
||||
|
||||
mSplitController.finishActivityStacks(Collections.singleton(tf.getTaskFragmentToken()));
|
||||
|
||||
verify(mSplitPresenter).deleteTaskFragment(any(), eq(tf.getTaskFragmentToken()));
|
||||
assertTrue(containers.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFinishActivityStacks_finishActivityStacksInOrder() {
|
||||
TaskFragmentContainer bottomTf = mSplitController.newContainer(mActivity, TASK_ID);
|
||||
TaskFragmentContainer topTf = mSplitController.newContainer(mActivity, TASK_ID);
|
||||
bottomTf.setInfo(mTransaction, createMockTaskFragmentInfo(bottomTf, mActivity));
|
||||
topTf.setInfo(mTransaction, createMockTaskFragmentInfo(topTf, createMockActivity()));
|
||||
|
||||
List<TaskFragmentContainer> containers = mSplitController.mTaskContainers.get(TASK_ID)
|
||||
.mContainers;
|
||||
|
||||
assertEquals(containers.size(), 2);
|
||||
|
||||
Set<IBinder> activityStackTokens = new ArraySet<>(new IBinder[]{
|
||||
topTf.getTaskFragmentToken(), bottomTf.getTaskFragmentToken()});
|
||||
|
||||
mSplitController.finishActivityStacks(activityStackTokens);
|
||||
|
||||
ArgumentCaptor<IBinder> argumentCaptor = ArgumentCaptor.forClass(IBinder.class);
|
||||
|
||||
verify(mSplitPresenter, times(2)).deleteTaskFragment(any(), argumentCaptor.capture());
|
||||
|
||||
List<IBinder> fragmentTokens = argumentCaptor.getAllValues();
|
||||
assertEquals("The ActivityStack must be deleted from the lowest z-order "
|
||||
+ "regardless of the order in ActivityStack set",
|
||||
bottomTf.getTaskFragmentToken(), fragmentTokens.get(0));
|
||||
assertEquals("The ActivityStack must be deleted from the lowest z-order "
|
||||
+ "regardless of the order in ActivityStack set",
|
||||
topTf.getTaskFragmentToken(), fragmentTokens.get(1));
|
||||
|
||||
assertTrue(containers.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateSplitAttributes_invalidSplitContainerToken_earlyReturn() {
|
||||
mSplitController.updateSplitAttributes(new Binder(), SPLIT_ATTRIBUTES);
|
||||
|
||||
verify(mTransactionManager, never()).startNewTransaction();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateSplitAttributes_nullParams_throwException() {
|
||||
assertThrows(NullPointerException.class,
|
||||
() -> mSplitController.updateSplitAttributes(null, SPLIT_ATTRIBUTES));
|
||||
|
||||
final SplitContainer splitContainer = mock(SplitContainer.class);
|
||||
final IBinder token = new Binder();
|
||||
doReturn(token).when(splitContainer).getToken();
|
||||
doReturn(splitContainer).when(mSplitController).getSplitContainer(eq(token));
|
||||
|
||||
assertThrows(NullPointerException.class,
|
||||
() -> mSplitController.updateSplitAttributes(token, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateSplitAttributes_doNotNeedToUpdateSplitContainer_doNotApplyTransaction() {
|
||||
final SplitContainer splitContainer = mock(SplitContainer.class);
|
||||
final IBinder token = new Binder();
|
||||
doReturn(token).when(splitContainer).getToken();
|
||||
doReturn(splitContainer).when(mSplitController).getSplitContainer(eq(token));
|
||||
doReturn(false).when(mSplitController).updateSplitContainerIfNeeded(
|
||||
eq(splitContainer), any(), eq(SPLIT_ATTRIBUTES));
|
||||
TransactionManager.TransactionRecord testRecord =
|
||||
mock(TransactionManager.TransactionRecord.class);
|
||||
doReturn(testRecord).when(mTransactionManager).startNewTransaction();
|
||||
|
||||
mSplitController.updateSplitAttributes(token, SPLIT_ATTRIBUTES);
|
||||
|
||||
verify(splitContainer).updateDefaultSplitAttributes(eq(SPLIT_ATTRIBUTES));
|
||||
verify(testRecord).abort();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateSplitAttributes_splitContainerUpdated_updateAttrs() {
|
||||
final SplitContainer splitContainer = mock(SplitContainer.class);
|
||||
final IBinder token = new Binder();
|
||||
doReturn(token).when(splitContainer).getToken();
|
||||
doReturn(splitContainer).when(mSplitController).getSplitContainer(eq(token));
|
||||
doReturn(true).when(mSplitController).updateSplitContainerIfNeeded(
|
||||
eq(splitContainer), any(), eq(SPLIT_ATTRIBUTES));
|
||||
TransactionManager.TransactionRecord testRecord =
|
||||
mock(TransactionManager.TransactionRecord.class);
|
||||
doReturn(testRecord).when(mTransactionManager).startNewTransaction();
|
||||
|
||||
mSplitController.updateSplitAttributes(token, SPLIT_ATTRIBUTES);
|
||||
|
||||
verify(splitContainer).updateDefaultSplitAttributes(eq(SPLIT_ATTRIBUTES));
|
||||
verify(testRecord).apply(eq(false));
|
||||
}
|
||||
|
||||
/** Creates a mock activity in the organizer process. */
|
||||
private Activity createMockActivity() {
|
||||
return createMockActivity(TASK_ID);
|
||||
|
||||
Reference in New Issue
Block a user