summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/tests/coretests/src/android/app/activity/ActivityThreadTest.java176
1 files changed, 106 insertions, 70 deletions
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 927c67cb1d36..be0669c42d44 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -34,9 +34,11 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.annotation.NonNull;
@@ -67,7 +69,6 @@ import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.os.Bundle;
import android.os.IBinder;
-import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
import android.util.DisplayMetrics;
@@ -90,7 +91,6 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
@@ -123,9 +123,7 @@ public class ActivityThreadTest {
@Rule(order = 1)
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);
- @Mock
- private BiConsumer<IBinder, ActivityWindowInfo> mActivityWindowInfoListener;
-
+ private ActivityWindowInfoListener mActivityWindowInfoListener;
private WindowTokenClientController mOriginalWindowTokenClientController;
private Configuration mOriginalAppConfig;
@@ -140,6 +138,7 @@ public class ActivityThreadTest {
mOriginalWindowTokenClientController = WindowTokenClientController.getInstance();
mOriginalAppConfig = new Configuration(ActivityThread.currentActivityThread()
.getConfiguration());
+ mActivityWindowInfoListener = spy(new ActivityWindowInfoListener());
}
@After
@@ -808,96 +807,107 @@ public class ActivityThreadTest {
@Test
public void testActivityWindowInfoChanged_activityLaunch() {
mSetFlagsRule.enableFlags(FLAG_ACTIVITY_WINDOW_INFO_FLAG);
-
ClientTransactionListenerController.getInstance().registerActivityWindowInfoChangedListener(
mActivityWindowInfoListener);
final Activity activity = mActivityTestRule.launchActivity(new Intent());
- InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ mActivityWindowInfoListener.await();
final ActivityClientRecord activityClientRecord = getActivityClientRecord(activity);
- verify(mActivityWindowInfoListener).accept(activityClientRecord.token,
+ // In case the system change the window after launch, there can be more than one callback.
+ verify(mActivityWindowInfoListener, atLeastOnce()).accept(activityClientRecord.token,
activityClientRecord.getActivityWindowInfo());
}
@Test
- public void testActivityWindowInfoChanged_activityRelaunch() throws RemoteException {
+ public void testActivityWindowInfoChanged_activityRelaunch() {
mSetFlagsRule.enableFlags(FLAG_ACTIVITY_WINDOW_INFO_FLAG);
-
ClientTransactionListenerController.getInstance().registerActivityWindowInfoChangedListener(
mActivityWindowInfoListener);
final Activity activity = mActivityTestRule.launchActivity(new Intent());
- final IApplicationThread appThread = activity.getActivityThread().getApplicationThread();
- appThread.scheduleTransaction(newRelaunchResumeTransaction(activity));
- InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ mActivityWindowInfoListener.await();
final ActivityClientRecord activityClientRecord = getActivityClientRecord(activity);
- // The same ActivityWindowInfo won't trigger duplicated callback.
- verify(mActivityWindowInfoListener).accept(activityClientRecord.token,
- activityClientRecord.getActivityWindowInfo());
-
- final Configuration currentConfig = activity.getResources().getConfiguration();
- final ActivityWindowInfo activityWindowInfo = new ActivityWindowInfo();
- activityWindowInfo.set(true /* isEmbedded */, new Rect(0, 0, 1000, 2000),
- new Rect(0, 0, 1000, 1000));
- final ActivityRelaunchItem relaunchItem = ActivityRelaunchItem.obtain(
- activity.getActivityToken(), null, null, 0,
- new MergedConfiguration(currentConfig, currentConfig),
- false /* preserveWindow */, activityWindowInfo);
- final ClientTransaction transaction = newTransaction(activity);
- transaction.addTransactionItem(relaunchItem);
- appThread.scheduleTransaction(transaction);
- InstrumentationRegistry.getInstrumentation().waitForIdleSync();
-
- verify(mActivityWindowInfoListener).accept(activityClientRecord.token,
- activityWindowInfo);
+ // Run on main thread to avoid racing from updating from window relayout.
+ final ActivityThread activityThread = activity.getActivityThread();
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ // Try relaunch with the same ActivityWindowInfo
+ clearInvocations(mActivityWindowInfoListener);
+ activityThread.executeTransaction(newRelaunchResumeTransaction(activity));
+
+ // The same ActivityWindowInfo won't trigger duplicated callback.
+ verify(mActivityWindowInfoListener, never()).accept(activityClientRecord.token,
+ activityClientRecord.getActivityWindowInfo());
+
+ // Try relaunch with different ActivityWindowInfo
+ final Configuration currentConfig = activity.getResources().getConfiguration();
+ final ActivityWindowInfo newInfo = new ActivityWindowInfo();
+ newInfo.set(true /* isEmbedded */, new Rect(0, 0, 1000, 2000),
+ new Rect(0, 0, 1000, 1000));
+ final ActivityRelaunchItem relaunchItem = ActivityRelaunchItem.obtain(
+ activity.getActivityToken(), null, null, 0,
+ new MergedConfiguration(currentConfig, currentConfig),
+ false /* preserveWindow */, newInfo);
+ final ClientTransaction transaction = newTransaction(activity);
+ transaction.addTransactionItem(relaunchItem);
+
+ clearInvocations(mActivityWindowInfoListener);
+ activityThread.executeTransaction(transaction);
+
+ // Trigger callback with a different ActivityWindowInfo
+ verify(mActivityWindowInfoListener).accept(activityClientRecord.token, newInfo);
+ });
}
@Test
- public void testActivityWindowInfoChanged_activityConfigurationChanged()
- throws RemoteException {
+ public void testActivityWindowInfoChanged_activityConfigurationChanged() {
mSetFlagsRule.enableFlags(FLAG_ACTIVITY_WINDOW_INFO_FLAG);
-
ClientTransactionListenerController.getInstance().registerActivityWindowInfoChangedListener(
mActivityWindowInfoListener);
final Activity activity = mActivityTestRule.launchActivity(new Intent());
- final IApplicationThread appThread = activity.getActivityThread().getApplicationThread();
- InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ mActivityWindowInfoListener.await();
- clearInvocations(mActivityWindowInfoListener);
- final Configuration config = new Configuration(activity.getResources().getConfiguration());
- config.seq++;
- final Rect taskBounds = new Rect(0, 0, 1000, 2000);
- final Rect taskFragmentBounds = new Rect(0, 0, 1000, 1000);
- final ActivityWindowInfo activityWindowInfo = new ActivityWindowInfo();
- activityWindowInfo.set(true /* isEmbedded */, taskBounds, taskFragmentBounds);
- final ActivityConfigurationChangeItem activityConfigurationChangeItem =
- ActivityConfigurationChangeItem.obtain(
- activity.getActivityToken(), config, activityWindowInfo);
- final ClientTransaction transaction = newTransaction(activity);
- transaction.addTransactionItem(activityConfigurationChangeItem);
- appThread.scheduleTransaction(transaction);
- InstrumentationRegistry.getInstrumentation().waitForIdleSync();
-
- verify(mActivityWindowInfoListener).accept(activity.getActivityToken(),
- activityWindowInfo);
-
- clearInvocations(mActivityWindowInfoListener);
- final ActivityWindowInfo activityWindowInfo2 = new ActivityWindowInfo();
- activityWindowInfo2.set(true /* isEmbedded */, taskBounds, taskFragmentBounds);
- config.seq++;
- final ActivityConfigurationChangeItem activityConfigurationChangeItem2 =
- ActivityConfigurationChangeItem.obtain(
- activity.getActivityToken(), config, activityWindowInfo2);
- final ClientTransaction transaction2 = newTransaction(activity);
- transaction2.addTransactionItem(activityConfigurationChangeItem2);
- appThread.scheduleTransaction(transaction);
- InstrumentationRegistry.getInstrumentation().waitForIdleSync();
-
- // The same ActivityWindowInfo won't trigger duplicated callback.
- verify(mActivityWindowInfoListener, never()).accept(any(), any());
+ final ActivityThread activityThread = activity.getActivityThread();
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ // Trigger callback with different ActivityWindowInfo
+ final Configuration config = new Configuration(activity.getResources()
+ .getConfiguration());
+ config.seq++;
+ final Rect taskBounds = new Rect(0, 0, 1000, 2000);
+ final Rect taskFragmentBounds = new Rect(0, 0, 1000, 1000);
+ final ActivityWindowInfo activityWindowInfo = new ActivityWindowInfo();
+ activityWindowInfo.set(true /* isEmbedded */, taskBounds, taskFragmentBounds);
+ final ActivityConfigurationChangeItem activityConfigurationChangeItem =
+ ActivityConfigurationChangeItem.obtain(
+ activity.getActivityToken(), config, activityWindowInfo);
+ final ClientTransaction transaction = newTransaction(activity);
+ transaction.addTransactionItem(activityConfigurationChangeItem);
+
+ clearInvocations(mActivityWindowInfoListener);
+ activityThread.executeTransaction(transaction);
+
+ // Trigger callback with a different ActivityWindowInfo
+ verify(mActivityWindowInfoListener).accept(activity.getActivityToken(),
+ activityWindowInfo);
+
+ // Try callback with the same ActivityWindowInfo
+ final ActivityWindowInfo activityWindowInfo2 =
+ new ActivityWindowInfo(activityWindowInfo);
+ config.seq++;
+ final ActivityConfigurationChangeItem activityConfigurationChangeItem2 =
+ ActivityConfigurationChangeItem.obtain(
+ activity.getActivityToken(), config, activityWindowInfo2);
+ final ClientTransaction transaction2 = newTransaction(activity);
+ transaction2.addTransactionItem(activityConfigurationChangeItem2);
+
+ clearInvocations(mActivityWindowInfoListener);
+ activityThread.executeTransaction(transaction);
+
+ // The same ActivityWindowInfo won't trigger duplicated callback.
+ verify(mActivityWindowInfoListener, never()).accept(any(), any());
+ });
}
/**
@@ -958,10 +968,12 @@ public class ActivityThreadTest {
@NonNull
private static ClientTransaction newRelaunchResumeTransaction(@NonNull Activity activity) {
final Configuration currentConfig = activity.getResources().getConfiguration();
+ final ActivityWindowInfo activityWindowInfo = getActivityClientRecord(activity)
+ .getActivityWindowInfo();
final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(
activity.getActivityToken(), null, null, 0,
new MergedConfiguration(currentConfig, currentConfig),
- false /* preserveWindow */, new ActivityWindowInfo());
+ false /* preserveWindow */, activityWindowInfo);
final ResumeActivityItem resumeStateRequest =
ResumeActivityItem.obtain(activity.getActivityToken(), true /* isForward */,
false /* shouldSendCompatFakeFocus*/);
@@ -1127,4 +1139,28 @@ public class ActivityThreadTest {
return mPipEnterSkipped;
}
}
+
+ public static class ActivityWindowInfoListener implements
+ BiConsumer<IBinder, ActivityWindowInfo> {
+
+ CountDownLatch mCallbackLatch = new CountDownLatch(1);
+
+ @Override
+ public void accept(@NonNull IBinder activityToken,
+ @NonNull ActivityWindowInfo activityWindowInfo) {
+ mCallbackLatch.countDown();
+ }
+
+ /**
+ * When the test is expecting to receive a callback, waits until the callback is triggered.
+ */
+ void await() {
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ try {
+ mCallbackLatch.await(TIMEOUT_SEC, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
}