diff options
Diffstat (limited to 'services/tests')
23 files changed, 715 insertions, 37 deletions
diff --git a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java index 7bd0201b997a..bcc111faadff 100644 --- a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java @@ -100,6 +100,7 @@ import org.mockito.MockitoSession; import org.mockito.quality.Strictness; import java.util.ArrayList; +import java.util.concurrent.atomic.AtomicInteger; @Presubmit @RunWith(AndroidJUnit4.class) @@ -1077,6 +1078,38 @@ public class AlarmManagerServiceTest { } } + /** + * This tests that all non wakeup alarms are sent even when the mPendingNonWakeupAlarms gets + * modified before the send is complete. This avoids bugs like b/175701084. + */ + @Test + public void allNonWakeupAlarmsSentAtomically() throws Exception { + final int numAlarms = 5; + final AtomicInteger alarmsFired = new AtomicInteger(0); + for (int i = 0; i < numAlarms; i++) { + final IAlarmListener listener = new IAlarmListener.Stub() { + @Override + public void doAlarm(IAlarmCompleteListener callback) throws RemoteException { + alarmsFired.incrementAndGet(); + mService.mPendingNonWakeupAlarms.clear(); + } + }; + setTestAlarmWithListener(ELAPSED_REALTIME, mNowElapsedTest + i + 5, listener); + } + doReturn(true).when(mService).checkAllowNonWakeupDelayLocked(anyLong()); + // Advance time past all expirations. + mNowElapsedTest += numAlarms + 5; + mTestTimer.expire(); + assertEquals(numAlarms, mService.mPendingNonWakeupAlarms.size()); + + // All of these alarms should be sent on interactive state change to true + mService.interactiveStateChangedLocked(false); + mService.interactiveStateChangedLocked(true); + + assertEquals(numAlarms, alarmsFired.get()); + assertEquals(0, mService.mPendingNonWakeupAlarms.size()); + } + @Test public void alarmCountOnPendingNonWakeupAlarmsRemoved() throws Exception { final int numAlarms = 10; diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml index 6db3233b0266..36cfcc6c2e83 100644 --- a/services/tests/servicestests/AndroidManifest.xml +++ b/services/tests/servicestests/AndroidManifest.xml @@ -77,6 +77,7 @@ <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/> <uses-permission android:name="android.permission.DUMP"/> <uses-permission android:name="android.permission.READ_DREAM_STATE"/> + <uses-permission android:name="android.permission.READ_DREAM_SUPPRESSION"/> <uses-permission android:name="android.permission.WRITE_DREAM_STATE"/> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/> <uses-permission android:name="android.permission.MODIFY_DAY_NIGHT_MODE"/> diff --git a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java index 4fbc587c8a87..0cdc2c925656 100644 --- a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java @@ -19,6 +19,7 @@ package com.android.server; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.never; @@ -34,6 +35,7 @@ import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.provider.Settings; import android.test.mock.MockContentResolver; +import android.testing.TestableLooper; import android.util.MutableBoolean; import android.view.KeyEvent; @@ -42,6 +44,7 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.test.FakeSettingsProvider; import com.android.server.LocalServices; @@ -64,6 +67,7 @@ import java.util.List; @Presubmit @SmallTest @RunWith(AndroidJUnit4.class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) public class GestureLauncherServiceTest { private static final int FAKE_USER_ID = 1337; @@ -81,6 +85,7 @@ public class GestureLauncherServiceTest { private @Mock Resources mResources; private @Mock StatusBarManagerInternal mStatusBarManagerInternal; private @Mock MetricsLogger mMetricsLogger; + @Mock private UiEventLogger mUiEventLogger; private MockContentResolver mContentResolver; private GestureLauncherService mGestureLauncherService; @@ -105,7 +110,8 @@ public class GestureLauncherServiceTest { mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); when(mContext.getContentResolver()).thenReturn(mContentResolver); - mGestureLauncherService = new GestureLauncherService(mContext, mMetricsLogger); + mGestureLauncherService = new GestureLauncherService(mContext, mMetricsLogger, + mUiEventLogger); } @Test @@ -217,6 +223,7 @@ public class GestureLauncherServiceTest { verify(mMetricsLogger, never()) .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); + verify(mUiEventLogger, never()).log(any()); final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); verify(mMetricsLogger, times(2)).histogram( @@ -261,6 +268,7 @@ public class GestureLauncherServiceTest { verify(mMetricsLogger, never()) .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); + verify(mUiEventLogger, never()).log(any()); final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); verify(mMetricsLogger, times(2)).histogram( @@ -307,6 +315,7 @@ public class GestureLauncherServiceTest { verify(mMetricsLogger, never()) .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); + verify(mUiEventLogger, never()).log(any()); final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); verify(mMetricsLogger, times(2)).histogram( @@ -355,6 +364,8 @@ public class GestureLauncherServiceTest { StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); verify(mMetricsLogger) .action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, (int) interval); + verify(mUiEventLogger, times(1)) + .log(GestureLauncherService.GestureLauncherEvent.GESTURE_CAMERA_DOUBLE_TAP_POWER); final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); verify(mMetricsLogger, times(2)).histogram( @@ -401,6 +412,7 @@ public class GestureLauncherServiceTest { verify(mMetricsLogger, never()) .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); + verify(mUiEventLogger, never()).log(any()); final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); verify(mMetricsLogger, times(1)).histogram( @@ -445,6 +457,7 @@ public class GestureLauncherServiceTest { verify(mMetricsLogger, never()) .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); + verify(mUiEventLogger, never()).log(any()); final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); verify(mMetricsLogger, times(2)).histogram( @@ -491,6 +504,7 @@ public class GestureLauncherServiceTest { verify(mMetricsLogger, never()) .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); + verify(mUiEventLogger, never()).log(any()); final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); verify(mMetricsLogger, times(2)).histogram( @@ -537,6 +551,7 @@ public class GestureLauncherServiceTest { verify(mMetricsLogger, never()) .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); + verify(mUiEventLogger, never()).log(any()); final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); verify(mMetricsLogger, times(2)).histogram( @@ -581,6 +596,7 @@ public class GestureLauncherServiceTest { verify(mMetricsLogger, never()) .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); + verify(mUiEventLogger, never()).log(any()); final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); verify(mMetricsLogger, times(2)).histogram( @@ -624,6 +640,7 @@ public class GestureLauncherServiceTest { assertFalse(outLaunched.value); verify(mMetricsLogger, never()) .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); + verify(mUiEventLogger, never()).log(any()); final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); verify(mMetricsLogger, times(2)).histogram( @@ -669,6 +686,7 @@ public class GestureLauncherServiceTest { assertFalse(outLaunched.value); verify(mMetricsLogger, never()) .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); + verify(mUiEventLogger, never()).log(any()); final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); verify(mMetricsLogger, times(2)).histogram( @@ -716,6 +734,8 @@ public class GestureLauncherServiceTest { StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); verify(mMetricsLogger) .action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, (int) interval); + verify(mUiEventLogger, times(1)) + .log(GestureLauncherService.GestureLauncherEvent.GESTURE_CAMERA_DOUBLE_TAP_POWER); final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); verify(mMetricsLogger, times(2)).histogram( @@ -762,6 +782,7 @@ public class GestureLauncherServiceTest { verify(mMetricsLogger, never()) .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); + verify(mUiEventLogger, never()).log(any()); final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); verify(mMetricsLogger, times(2)).histogram( @@ -806,6 +827,7 @@ public class GestureLauncherServiceTest { verify(mMetricsLogger, never()) .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); + verify(mUiEventLogger, never()).log(any()); final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); verify(mMetricsLogger, times(2)).histogram( @@ -852,6 +874,7 @@ public class GestureLauncherServiceTest { verify(mMetricsLogger, never()) .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt()); + verify(mUiEventLogger, never()).log(any()); final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); verify(mMetricsLogger, times(2)).histogram( diff --git a/services/tests/servicestests/src/com/android/server/accessibility/gestures/GestureManifoldTest.java b/services/tests/servicestests/src/com/android/server/accessibility/gestures/GestureManifoldTest.java index 538e2d51e88f..0e787853f617 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/gestures/GestureManifoldTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/gestures/GestureManifoldTest.java @@ -26,6 +26,7 @@ import android.accessibilityservice.AccessibilityService; import android.content.Context; import android.graphics.Point; import android.graphics.PointF; +import android.os.Handler; import android.view.MotionEvent; import androidx.test.InstrumentationRegistry; @@ -56,7 +57,8 @@ public class GestureManifoldTest { // Construct a testable GestureManifold. mResultListener = mock(GestureManifold.Listener.class); mState = new TouchState(); - mManifold = new GestureManifold(context, mResultListener, mState); + Handler handler = new Handler(context.getMainLooper()); + mManifold = new GestureManifold(context, mResultListener, mState, handler); // Play the role of touch explorer in updating the shared state. when(mResultListener.onGestureStarted()).thenReturn(onGestureStarted()); diff --git a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java index 9053234aa220..13587bc70b24 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java @@ -16,6 +16,8 @@ package com.android.server.accessibility.gestures; +import static android.view.ViewConfiguration.getDoubleTapTimeout; + import static com.android.server.accessibility.gestures.TouchState.STATE_CLEAR; import static com.android.server.accessibility.gestures.TouchState.STATE_DELEGATING; import static com.android.server.accessibility.gestures.TouchState.STATE_DRAGGING; @@ -23,6 +25,7 @@ import static com.android.server.accessibility.gestures.TouchState.STATE_TOUCH_E import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import android.content.Context; @@ -31,6 +34,7 @@ import android.os.SystemClock; import android.testing.DexmakerShareClassLoaderRule; import android.view.InputDevice; import android.view.MotionEvent; +import android.view.ViewConfiguration; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; @@ -52,6 +56,8 @@ import java.util.List; public class TouchExplorerTest { private static final String LOG_TAG = "TouchExplorerTest"; + // The constant of mDetermineUserIntentTimeout. + private static final int USER_INTENT_TIMEOUT = getDoubleTapTimeout(); private static final int FLAG_1FINGER = 0x8000; private static final int FLAG_2FINGERS = 0x0100; private static final int FLAG_3FINGERS = 0x0200; @@ -72,6 +78,8 @@ public class TouchExplorerTest { private EventStreamTransformation mCaptor; private MotionEvent mLastEvent; private TouchExplorer mTouchExplorer; + private Context mContext; + private int mTouchSlop; private long mLastDownTime = Integer.MIN_VALUE; // mock package-private GestureManifold class @@ -91,7 +99,9 @@ public class TouchExplorerTest { public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { mEvents.add(0, event.copy()); // LastEvent may not match if we're clearing the state - if (mLastEvent != null) { + // The last event becomes ACTION_UP event when sending the ACTION_CANCEL event, + // so ignoring the ACTION_CANCEL event checking. + if (mLastEvent != null && rawEvent.getActionMasked() != MotionEvent.ACTION_CANCEL) { MotionEventMatcher lastEventMatcher = new MotionEventMatcher(mLastEvent); assertThat(rawEvent, lastEventMatcher); } @@ -109,14 +119,52 @@ public class TouchExplorerTest { @Before public void setUp() { - Context context = InstrumentationRegistry.getContext(); - AccessibilityManagerService ams = new AccessibilityManagerService(context); + mContext = InstrumentationRegistry.getContext(); + mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop(); + AccessibilityManagerService ams = new AccessibilityManagerService(mContext); GestureManifold detector = mock(GestureManifold.class); mCaptor = new EventCaptor(); - mTouchExplorer = new TouchExplorer(context, ams, detector); + mTouchExplorer = new TouchExplorer(mContext, ams, detector); mTouchExplorer.setNext(mCaptor); } + /** + * Test the case where the event location is correct when clicking after the following + * situation happened: entering the delegate state through doubleTapAndHold gesture and + * receiving a cancel event to return the clear state. + */ + @Test + public void testClick_afterCanceledDoubleTapAndHold_eventLocationIsCorrect() + throws InterruptedException { + // Generates the click position by this click operation, otherwise the offset used + // while delegating could not be set. + send(downEvent(DEFAULT_X + 10, DEFAULT_Y + 10)); + // Waits for transition to touch exploring state. + Thread.sleep(2 * USER_INTENT_TIMEOUT); + send(upEvent()); + + // Simulates detecting the doubleTapAndHold gesture and enters the delegate state. + final MotionEvent sendEvent = + fromTouchscreen(downEvent(DEFAULT_X + 100, DEFAULT_Y + 100)); + mTouchExplorer.onDoubleTapAndHold(sendEvent, sendEvent, 0); + assertState(STATE_DELEGATING); + + send(cancelEvent()); + + // Generates the click operation, and checks the event location of the ACTION_HOVER_ENTER + // event is correct. + send(downEvent()); + // Waits for transition to touch exploring state. + Thread.sleep(2 * USER_INTENT_TIMEOUT); + send(upEvent()); + + final List<MotionEvent> events = getCapturedEvents(); + assertTrue(events.stream().anyMatch( + motionEvent -> motionEvent.getActionMasked() == MotionEvent.ACTION_HOVER_ENTER + && motionEvent.getX() == DEFAULT_X + && motionEvent.getY() == DEFAULT_Y)); + } + @Test public void testTwoFingersMove_shouldDelegatingAndInjectActionDownPointerDown() { goFromStateClearTo(STATE_MOVING_2FINGERS); @@ -158,7 +206,7 @@ public class TouchExplorerTest { goFromStateClearTo(STATE_DRAGGING_2FINGERS); assertState(STATE_DRAGGING); - assertCapturedEvents(MotionEvent.ACTION_DOWN); + assertCapturedEvents(MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE); assertCapturedEventsNoHistory(); } @@ -170,6 +218,7 @@ public class TouchExplorerTest { assertState(STATE_DELEGATING); assertCapturedEvents( /* goto dragging state */ MotionEvent.ACTION_DOWN, + MotionEvent.ACTION_MOVE, /* leave dragging state */ MotionEvent.ACTION_UP, MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN); @@ -226,13 +275,13 @@ public class TouchExplorerTest { break; case STATE_DRAGGING_2FINGERS: { goFromStateClearTo(STATE_TOUCH_EXPLORING_2FINGER); - moveEachPointers(mLastEvent, p(10, 0), p(10, 0)); + moveEachPointers(mLastEvent, p(mTouchSlop, 0), p(mTouchSlop, 0)); send(mLastEvent); } break; case STATE_PINCH_2FINGERS: { goFromStateClearTo(STATE_DRAGGING_2FINGERS); - moveEachPointers(mLastEvent, p(10, 0), p(-10, 1)); + moveEachPointers(mLastEvent, p(mTouchSlop, 0), p(-mTouchSlop, 1)); send(mLastEvent); } break; @@ -289,6 +338,19 @@ public class TouchExplorerTest { return ((EventCaptor) mCaptor).mEvents; } + private MotionEvent cancelEvent() { + mLastDownTime = SystemClock.uptimeMillis(); + return fromTouchscreen( + MotionEvent.obtain(mLastDownTime, mLastDownTime, MotionEvent.ACTION_CANCEL, + DEFAULT_X, DEFAULT_Y, 0)); + } + + private MotionEvent downEvent(float x, float y) { + mLastDownTime = SystemClock.uptimeMillis(); + return fromTouchscreen( + MotionEvent.obtain(mLastDownTime, mLastDownTime, MotionEvent.ACTION_DOWN, x, y, 0)); + } + private MotionEvent downEvent() { mLastDownTime = SystemClock.uptimeMillis(); return fromTouchscreen( diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java index 7d7af03ecd3d..752da31638dd 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java @@ -2043,7 +2043,8 @@ public class NetworkPolicyManagerServiceTest { final NetworkCapabilities networkCapabilities = new NetworkCapabilities(); networkCapabilities.addTransportType(TRANSPORT_WIFI); networkCapabilities.setSSID(TEST_SSID); - return new NetworkState(TYPE_WIFI, prop, networkCapabilities, null, null); + return new NetworkState(TYPE_WIFI, prop, networkCapabilities, new Network(TEST_NET_ID), + null); } private void expectHasInternetPermission(int uid, boolean hasIt) throws Exception { diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java index d244e687c8b8..d7897dbb6133 100644 --- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java @@ -77,6 +77,7 @@ import com.android.server.SystemService; import com.android.server.lights.LightsManager; import com.android.server.policy.WindowManagerPolicy; import com.android.server.power.PowerManagerService.BatteryReceiver; +import com.android.server.power.PowerManagerService.BinderService; import com.android.server.power.PowerManagerService.Injector; import com.android.server.power.PowerManagerService.NativeWrapper; import com.android.server.power.PowerManagerService.UserSwitchedReceiver; @@ -173,6 +174,7 @@ public class PowerManagerServiceTest { when(mInattentiveSleepWarningControllerMock.isShown()).thenReturn(false); when(mDisplayManagerInternalMock.requestPowerState(any(), anyBoolean())).thenReturn(true); when(mSystemPropertiesMock.get(eq(SYSTEM_PROPERTY_QUIESCENT), anyString())).thenReturn(""); + when(mAmbientDisplayConfigurationMock.ambientDisplayAvailable()).thenReturn(true); mDisplayPowerRequest = new DisplayPowerRequest(); addLocalServiceMock(LightsManager.class, mLightsManagerMock); @@ -967,4 +969,72 @@ public class PowerManagerServiceTest { assertThat(mService.getBinderServiceInstance().isAmbientDisplaySuppressedForToken("test2")) .isFalse(); } + + @Test + public void testIsAmbientDisplaySuppressedForTokenByApp_ambientDisplayUnavailable() + throws Exception { + createService(); + when(mAmbientDisplayConfigurationMock.ambientDisplayAvailable()).thenReturn(false); + + BinderService service = mService.getBinderServiceInstance(); + assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test", Binder.getCallingUid())) + .isFalse(); + } + + @Test + public void testIsAmbientDisplaySuppressedForTokenByApp_default() + throws Exception { + createService(); + + BinderService service = mService.getBinderServiceInstance(); + assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test", Binder.getCallingUid())) + .isFalse(); + } + + @Test + public void testIsAmbientDisplaySuppressedForTokenByApp_suppressedByCallingApp() + throws Exception { + createService(); + BinderService service = mService.getBinderServiceInstance(); + service.suppressAmbientDisplay("test", true); + + assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test", Binder.getCallingUid())) + .isTrue(); + // Check that isAmbientDisplaySuppressedForTokenByApp doesn't return true for another app. + assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test", /* appUid= */ 123)) + .isFalse(); + } + + @Test + public void testIsAmbientDisplaySuppressedForTokenByApp_notSuppressedByCallingApp() + throws Exception { + createService(); + BinderService service = mService.getBinderServiceInstance(); + service.suppressAmbientDisplay("test", false); + + assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test", Binder.getCallingUid())) + .isFalse(); + // Check that isAmbientDisplaySuppressedForTokenByApp doesn't return true for another app. + assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test", /* appUid= */ 123)) + .isFalse(); + } + + @Test + public void testIsAmbientDisplaySuppressedForTokenByApp_multipleTokensSuppressedByCallingApp() + throws Exception { + createService(); + BinderService service = mService.getBinderServiceInstance(); + service.suppressAmbientDisplay("test1", true); + service.suppressAmbientDisplay("test2", true); + + assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test1", Binder.getCallingUid())) + .isTrue(); + assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test2", Binder.getCallingUid())) + .isTrue(); + // Check that isAmbientDisplaySuppressedForTokenByApp doesn't return true for another app. + assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test1", /* appUid= */ 123)) + .isFalse(); + assertThat(service.isAmbientDisplaySuppressedForTokenByApp("test2", /* appUid= */ 123)) + .isFalse(); + } } diff --git a/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java index 614949c91b9a..1494642edb56 100644 --- a/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java @@ -79,7 +79,9 @@ public class UriGrantsManagerServiceTest { @Before public void setUp() throws Exception { mContext = new UriGrantsMockContext(InstrumentationRegistry.getContext()); - mService = UriGrantsManagerService.createForTest(mContext.getFilesDir()).getLocalService(); + mService = UriGrantsManagerService + .createForTest(mContext, mContext.getFilesDir()) + .getLocalService(); } /** diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java index a07e60ce838e..1ced467dffa1 100644 --- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java +++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java @@ -141,10 +141,13 @@ public class AppStandbyControllerTests { private AppStandbyController mController; private CountDownLatch mStateChangedLatch = new CountDownLatch(1); + private String mLatchPkgName = null; private AppIdleStateChangeListener mListener = new AppIdleStateChangeListener() { @Override public void onAppIdleStateChanged(String packageName, int userId, boolean idle, int bucket, int reason) { + // Ignore events not related to mLatchPkgName, if set. + if (mLatchPkgName != null && !mLatchPkgName.equals(packageName)) return; mStateChangedLatch.countDown(); } }; @@ -387,6 +390,7 @@ public class AppStandbyControllerTests { mInjector.mElapsedRealtime, false)); controller.addListener(mListener); + mLatchPkgName = null; return controller; } @@ -1390,7 +1394,7 @@ public class AppStandbyControllerTests { @Test public void testUnexemptedSyncScheduled() throws Exception { - mStateChangedLatch = new CountDownLatch(1); + rearmLatch(PACKAGE_1); mController.addListener(mListener); assertEquals("Test package did not start in the Never bucket", STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_1)); @@ -1402,7 +1406,7 @@ public class AppStandbyControllerTests { setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM); - mStateChangedLatch = new CountDownLatch(1); + rearmLatch(PACKAGE_1); mController.postReportSyncScheduled(PACKAGE_1, USER_ID, false); mStateChangedLatch.await(100, TimeUnit.MILLISECONDS); assertEquals("Unexempted sync scheduled should not elevate a non Never bucket", @@ -1413,7 +1417,7 @@ public class AppStandbyControllerTests { public void testExemptedSyncScheduled() throws Exception { setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM); mInjector.mDeviceIdleMode = true; - mStateChangedLatch = new CountDownLatch(1); + rearmLatch(PACKAGE_1); mController.postReportSyncScheduled(PACKAGE_1, USER_ID, true); mStateChangedLatch.await(100, TimeUnit.MILLISECONDS); assertEquals("Exempted sync scheduled in doze should set bucket to working set", @@ -1421,7 +1425,7 @@ public class AppStandbyControllerTests { setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM); mInjector.mDeviceIdleMode = false; - mStateChangedLatch = new CountDownLatch(1); + rearmLatch(PACKAGE_1); mController.postReportSyncScheduled(PACKAGE_1, USER_ID, true); mStateChangedLatch.await(100, TimeUnit.MILLISECONDS); assertEquals("Exempted sync scheduled while not in doze should set bucket to active", @@ -1590,10 +1594,19 @@ public class AppStandbyControllerTests { } private void setAndAssertBucket(String pkg, int user, int bucket, int reason) throws Exception { - mStateChangedLatch = new CountDownLatch(1); + rearmLatch(pkg); mController.setAppStandbyBucket(pkg, user, bucket, reason); mStateChangedLatch.await(100, TimeUnit.MILLISECONDS); assertEquals("Failed to set package bucket", bucket, getStandbyBucket(mController, PACKAGE_1)); } + + private void rearmLatch(String pkgName) { + mLatchPkgName = pkgName; + mStateChangedLatch = new CountDownLatch(1); + } + + private void rearmLatch() { + rearmLatch(null); + } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java index 078832d33a76..ca2ef9531fd1 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java @@ -103,6 +103,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase { NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake(); private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake( 1 << 30); + private InjectableSystemClock mSystemClock = new FakeSystemClock(); private NotificationManagerService mService; private String mPkg = "com.android.server.notification"; @@ -154,7 +155,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase { assertTrue(accessibilityManager.isEnabled()); mService = spy(new NotificationManagerService(getContext(), mNotificationRecordLogger, - mNotificationInstanceIdSequence)); + mSystemClock, mNotificationInstanceIdSequence)); mService.setAudioManager(mAudioManager); mService.setVibrator(mVibrator); mService.setSystemReady(true); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/FakeSystemClock.java b/services/tests/uiservicestests/src/com/android/server/notification/FakeSystemClock.java new file mode 100644 index 000000000000..c960f1766612 --- /dev/null +++ b/services/tests/uiservicestests/src/com/android/server/notification/FakeSystemClock.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.notification; + +import java.util.ArrayList; +import java.util.List; + +/** + * A fake {@link InjectableSystemClock} + * + * Attempts to simulate the behavior of a real system clock. Time can be moved forward but not + * backwards. uptimeMillis, elapsedRealtime, and currentThreadTimeMillis are all kept in sync. + * + * Unless otherwise specified, uptimeMillis and elapsedRealtime will advance the same amount with + * every call to {@link #advanceTime(long)}. Thread time always lags by 50% of the uptime + * advancement to simulate time loss due to scheduling. + * + * @hide + */ +public class FakeSystemClock implements InjectableSystemClock { + private long mUptimeMillis = 10000; + private long mElapsedRealtime = 10000; + private long mCurrentThreadTimeMillis = 10000; + + private long mCurrentTimeMillis = 1555555500000L; + + private final List<ClockTickListener> mListeners = new ArrayList<>(); + @Override + public long uptimeMillis() { + return mUptimeMillis; + } + + @Override + public long elapsedRealtime() { + return mElapsedRealtime; + } + + @Override + public long elapsedRealtimeNanos() { + return mElapsedRealtime * 1000000 + 447; + } + + @Override + public long currentThreadTimeMillis() { + return mCurrentThreadTimeMillis; + } + + @Override + public long currentTimeMillis() { + return mCurrentTimeMillis; + } + + public void setUptimeMillis(long uptime) { + advanceTime(uptime - mUptimeMillis); + } + + public void setCurrentTimeMillis(long millis) { + mCurrentTimeMillis = millis; + } + + public void advanceTime(long uptime) { + advanceTime(uptime, 0); + } + + public void advanceTime(long uptime, long sleepTime) { + if (uptime < 0 || sleepTime < 0) { + throw new IllegalArgumentException("Time cannot go backwards."); + } + + if (uptime > 0 || sleepTime > 0) { + mUptimeMillis += uptime; + mElapsedRealtime += uptime + sleepTime; + mCurrentTimeMillis += uptime + sleepTime; + + mCurrentThreadTimeMillis += Math.ceil(uptime * 0.5); + + for (ClockTickListener listener : mListeners) { + listener.onClockTick(); + } + } + } + + public void addListener(ClockTickListener listener) { + mListeners.add(listener); + } + + public void removeListener(ClockTickListener listener) { + mListeners.remove(listener); + } + + public interface ClockTickListener { + void onClockTick(); + } + + private static final long START_TIME = 10000; +} + diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 24384b1d4f31..4259831c15f8 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -199,6 +199,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.function.Consumer; @@ -287,18 +288,26 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { 1 << 30); @Mock StatusBarManagerInternal mStatusBar; + private final FakeSystemClock mSystemClock = new FakeSystemClock(); // Use a Testable subclass so we can simulate calls from the system without failing. private static class TestableNotificationManagerService extends NotificationManagerService { int countSystemChecks = 0; boolean isSystemUid = true; int countLogSmartSuggestionsVisible = 0; + // If true, don't enqueue the PostNotificationRunnables, just trap them + boolean trapEnqueuedNotifications = false; + final ArrayList<NotificationManagerService.PostNotificationRunnable> trappedRunnables = + new ArrayList<>(); @Nullable NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback; - TestableNotificationManagerService(Context context, NotificationRecordLogger logger, + TestableNotificationManagerService( + Context context, + NotificationRecordLogger logger, + InjectableSystemClock systemClock, InstanceIdSequence notificationInstanceIdSequence) { - super(context, logger, notificationInstanceIdSequence); + super(context, logger, systemClock, notificationInstanceIdSequence); } RankingHelper getRankingHelper() { @@ -353,6 +362,23 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { return new String[] {PKG_O}; } + @Override + protected void postPostNotificationRunnableMaybeDelayedLocked(NotificationRecord record, + PostNotificationRunnable runnable) { + if (trapEnqueuedNotifications) { + trappedRunnables.add(runnable); + return; + } + + super.postPostNotificationRunnableMaybeDelayedLocked(record, runnable); + } + + void drainTrappedRunnableQueue() { + for (Runnable r : trappedRunnables) { + getWorkHandler().post(r); + } + } + private void setNotificationAssistantAccessGrantedCallback( @Nullable NotificationAssistantAccessGrantedCallback callback) { this.mNotificationAssistantAccessGrantedCallback = callback; @@ -402,7 +428,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any()); mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger, - mNotificationInstanceIdSequence); + mSystemClock, mNotificationInstanceIdSequence); // Use this testable looper. mTestableLooper = TestableLooper.get(this); @@ -1344,10 +1370,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getNotification(), sbn.getUserId()); - Thread.sleep(1); // make sure the system clock advances before the next step + mSystemClock.advanceTime(1); // THEN it is canceled mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId()); - Thread.sleep(1); // here too + mSystemClock.advanceTime(1); // THEN it is posted again (before the cancel has a chance to finish) mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getNotification(), sbn.getUserId()); @@ -1362,6 +1388,60 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testChangeSystemTimeAfterPost_thenCancel_noFgs() throws Exception { + // GIVEN time X + mSystemClock.setCurrentTimeMillis(10000); + + // GIVEN a notification is posted + final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); + mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(), + sbn.getNotification(), sbn.getUserId()); + mSystemClock.advanceTime(1); + waitForIdle(); + + // THEN the system time is changed to an earlier time + mSystemClock.setCurrentTimeMillis(5000); + + // THEN a cancel is requested + mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId()); + waitForIdle(); + + // It should work + StatusBarNotification[] notifs = + mBinderService.getActiveNotifications(PKG); + assertEquals(0, notifs.length); + assertEquals(0, mService.getNotificationRecordCount()); + } + + @Test + public void testChangeSystemTimeAfterPost_thenCancel_fgs() throws Exception { + // GIVEN time X + mSystemClock.setCurrentTimeMillis(10000); + + // GIVEN a notification is posted + final StatusBarNotification sbn = generateNotificationRecord(null).getSbn(); + sbn.getNotification().flags = + Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE; + mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", sbn.getId(), + sbn.getNotification(), sbn.getUserId()); + mSystemClock.advanceTime(1); + waitForIdle(); + + // THEN the system time is changed to an earlier time + mSystemClock.setCurrentTimeMillis(5000); + + // THEN a cancel is requested + mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId()); + waitForIdle(); + + // It should work + StatusBarNotification[] notifs = + mBinderService.getActiveNotifications(PKG); + assertEquals(0, notifs.length); + assertEquals(0, mService.getNotificationRecordCount()); + } + + @Test public void testCancelNotificationWhilePostedAndEnqueued() throws Exception { mBinderService.enqueueNotificationWithTag(PKG, PKG, "testCancelNotificationWhilePostedAndEnqueued", 0, @@ -1383,6 +1463,56 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testDelayCancelWhenEnqueuedHasNotPosted() throws Exception { + // Don't allow PostNotificationRunnables to execute so we can set up problematic state + mService.trapEnqueuedNotifications = true; + // GIVEN an enqueued notification + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testDelayCancelWhenEnqueuedHasNotPosted", 0, + generateNotificationRecord(null).getNotification(), 0); + mSystemClock.advanceTime(1); + // WHEN a cancel is requested before it has posted + mBinderService.cancelNotificationWithTag(PKG, PKG, + "testDelayCancelWhenEnqueuedHasNotPosted", 0, 0); + + waitForIdle(); + + // THEN the cancel notification runnable is captured and associated with that record + ArrayMap<NotificationRecord, + ArrayList<NotificationManagerService.CancelNotificationRunnable>> delayed = + mService.mDelayedCancelations; + Set<NotificationRecord> keySet = delayed.keySet(); + assertEquals(1, keySet.size()); + } + + @Test + public void testDelayedCancelsExecuteAfterPost() throws Exception { + // Don't allow PostNotificationRunnables to execute so we can set up problematic state + mService.trapEnqueuedNotifications = true; + // GIVEN an enqueued notification + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testDelayCancelWhenEnqueuedHasNotPosted", 0, + generateNotificationRecord(null).getNotification(), 0); + mSystemClock.advanceTime(1); + // WHEN a cancel is requested before it has posted + mBinderService.cancelNotificationWithTag(PKG, PKG, + "testDelayCancelWhenEnqueuedHasNotPosted", 0, 0); + + waitForIdle(); + + // We're now in a state with an a notification awaiting PostNotificationRunnable to execute + // WHEN the PostNotificationRunnable is allowed to execute + mService.drainTrappedRunnableQueue(); + waitForIdle(); + + // THEN the cancel executes and the notification is removed + StatusBarNotification[] notifs = + mBinderService.getActiveNotifications(PKG); + assertEquals(0, notifs.length); + assertEquals(0, mService.getNotificationRecordCount()); + } + + @Test public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception { NotificationRecord r = generateNotificationRecord(null); final StatusBarNotification sbn = r.getSbn(); @@ -2529,8 +2659,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Test public void testHasCompanionDevice_noService() { - mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger, - mNotificationInstanceIdSequence); + mService = + new TestableNotificationManagerService(mContext, mNotificationRecordLogger, + mSystemClock, mNotificationInstanceIdSequence); assertFalse(mService.hasCompanionDevice(mListener)); } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java index bbb25cd20149..dd6104ef9fe3 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java @@ -96,6 +96,7 @@ import android.test.suitebuilder.annotation.SmallTest; import android.testing.TestableContentResolver; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.IntArray; import android.util.Pair; import android.util.StatsEvent; import android.util.Xml; @@ -3284,7 +3285,8 @@ public class PreferencesHelperTest extends UiServiceTestCase { channel2.setImportantConversation(true); mHelper.createNotificationChannel(PKG_O, UID_O, channel2, true, false); - List<ConversationChannelWrapper> convos = mHelper.getConversations(false); + List<ConversationChannelWrapper> convos = + mHelper.getConversations(IntArray.wrap(new int[] {0}), false); assertEquals(3, convos.size()); assertTrue(conversationWrapperContainsChannel(convos, channel)); @@ -3293,6 +3295,44 @@ public class PreferencesHelperTest extends UiServiceTestCase { } @Test + public void testGetConversations_multiUser() { + String convoId = "convo"; + NotificationChannel messages = + new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT); + mHelper.createNotificationChannel(PKG_O, UID_O, messages, true, false); + + NotificationChannel messagesUser10 = + new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT); + mHelper.createNotificationChannel( + PKG_O, UID_O + UserHandle.PER_USER_RANGE, messagesUser10, true, false); + + NotificationChannel messagesFromB = + new NotificationChannel("B person msgs", "messages from B", IMPORTANCE_DEFAULT); + messagesFromB.setConversationId(messages.getId(), "different convo"); + mHelper.createNotificationChannel(PKG_O, UID_O, messagesFromB, true, false); + + NotificationChannel messagesFromBUser10 = + new NotificationChannel("B person msgs", "messages from B", IMPORTANCE_DEFAULT); + messagesFromBUser10.setConversationId(messagesUser10.getId(), "different convo"); + mHelper.createNotificationChannel( + PKG_O, UID_O + UserHandle.PER_USER_RANGE, messagesFromBUser10, true, false); + + + List<ConversationChannelWrapper> convos = + mHelper.getConversations(IntArray.wrap(new int[] {0}), false); + + assertEquals(1, convos.size()); + assertTrue(conversationWrapperContainsChannel(convos, messagesFromB)); + + convos = + mHelper.getConversations(IntArray.wrap(new int[] {0, UserHandle.getUserId(UID_O + UserHandle.PER_USER_RANGE)}), false); + + assertEquals(2, convos.size()); + assertTrue(conversationWrapperContainsChannel(convos, messagesFromB)); + assertTrue(conversationWrapperContainsChannel(convos, messagesFromBUser10)); + } + + @Test public void testGetConversations_notDemoted() { String convoId = "convo"; NotificationChannel messages = @@ -3322,7 +3362,8 @@ public class PreferencesHelperTest extends UiServiceTestCase { channel2.setImportantConversation(true); mHelper.createNotificationChannel(PKG_O, UID_O, channel2, true, false); - List<ConversationChannelWrapper> convos = mHelper.getConversations(false); + List<ConversationChannelWrapper> convos = + mHelper.getConversations(IntArray.wrap(new int[] {0}), false); assertEquals(2, convos.size()); assertTrue(conversationWrapperContainsChannel(convos, channel)); @@ -3360,7 +3401,8 @@ public class PreferencesHelperTest extends UiServiceTestCase { channel2.setConversationId(calls.getId(), convoId); mHelper.createNotificationChannel(PKG_O, UID_O, channel2, true, false); - List<ConversationChannelWrapper> convos = mHelper.getConversations(true); + List<ConversationChannelWrapper> convos = + mHelper.getConversations(IntArray.wrap(new int[] {0}), true); assertEquals(2, convos.size()); assertTrue(conversationWrapperContainsChannel(convos, channel)); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java index 3281c3f4cfb9..ac2c6193c677 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java @@ -103,12 +103,14 @@ public class RoleObserverTest extends UiServiceTestCase { private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake( 1 << 30); private List<UserInfo> mUsers; + private InjectableSystemClock mSystemClock = new FakeSystemClock(); private static class TestableNotificationManagerService extends NotificationManagerService { TestableNotificationManagerService(Context context, NotificationRecordLogger logger, + InjectableSystemClock systemClock, InstanceIdSequence notificationInstanceIdSequence) { - super(context, logger, notificationInstanceIdSequence); + super(context, logger, systemClock, notificationInstanceIdSequence); } @Override @@ -136,7 +138,7 @@ public class RoleObserverTest extends UiServiceTestCase { when(mUm.getUsers()).thenReturn(mUsers); mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger, - mNotificationInstanceIdSequence); + mSystemClock, mNotificationInstanceIdSequence); mRoleObserver = mService.new RoleObserver(mRoleManager, mPm, mExecutor); try { diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java index a4436951f48b..dd0c162d8467 100644 --- a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java @@ -75,7 +75,6 @@ public class SliceManagerServiceTest extends UiServiceTestCase { LocalServices.addService(UsageStatsManagerInternal.class, mock(UsageStatsManagerInternal.class)); mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class)); - mContext.getTestablePermissions().setPermission(TEST_URI, PERMISSION_GRANTED); mContextSpy = spy(mContext); mService = spy(new SliceManagerService(mContextSpy, TestableLooper.get(this).getLooper())); @@ -90,6 +89,7 @@ public class SliceManagerServiceTest extends UiServiceTestCase { @Test public void testAddPinCreatesPinned() throws RemoteException { + grantSlicePermission(); doReturn("pkg").when(mService).getDefaultHome(anyInt()); mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken); @@ -99,6 +99,7 @@ public class SliceManagerServiceTest extends UiServiceTestCase { @Test public void testRemovePinDestroysPinned() throws RemoteException { + grantSlicePermission(); doReturn("pkg").when(mService).getDefaultHome(anyInt()); mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken); @@ -130,11 +131,13 @@ public class SliceManagerServiceTest extends UiServiceTestCase { @Test(expected = IllegalStateException.class) public void testNoPinThrow() throws Exception { + grantSlicePermission(); mService.getPinnedSpecs(TEST_URI, "pkg"); } @Test public void testGetPinnedSpecs() throws Exception { + grantSlicePermission(); SliceSpec[] specs = new SliceSpec[] { new SliceSpec("Something", 1) }; mService.pinSlice("pkg", TEST_URI, specs, mToken); @@ -143,4 +146,10 @@ public class SliceManagerServiceTest extends UiServiceTestCase { assertEquals(specs, mService.getPinnedSpecs(TEST_URI, "pkg")); } + private void grantSlicePermission() { + doReturn(PERMISSION_GRANTED).when(mService).checkSlicePermission( + eq(TEST_URI), anyString(), anyString(), anyInt(), anyInt(), any()); + doReturn(PERMISSION_GRANTED).when(mService).checkAccess( + anyString(), eq(TEST_URI), anyInt(), anyInt()); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java index e1ce431fc97c..5b516a9de350 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java @@ -32,6 +32,7 @@ import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.timeout; +import android.app.WaitResult; import android.content.Intent; import android.os.SystemClock; import android.platform.test.annotations.Presubmit; @@ -163,10 +164,15 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase { @Test public void testOnActivityLaunchFinished() { + // Assume that the process is started (ActivityBuilder has mocked the returned value of + // ATMS#getProcessController) but the activity has not attached process. + mTopActivity.app = null; onActivityLaunched(mTopActivity); notifyTransitionStarting(mTopActivity); - notifyWindowsDrawn(mTopActivity); + final ActivityMetricsLogger.TransitionInfoSnapshot info = notifyWindowsDrawn(mTopActivity); + assertWithMessage("Warm launch").that(info.getLaunchState()) + .isEqualTo(WaitResult.LAUNCH_STATE_WARM); verifyOnActivityLaunchFinished(mTopActivity); verifyNoMoreInteractions(mLaunchObserver); @@ -201,7 +207,7 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase { notifyActivityLaunching(noDrawnActivity.intent); notifyActivityLaunched(START_SUCCESS, noDrawnActivity); - noDrawnActivity.destroyIfPossible("test"); + noDrawnActivity.mVisibleRequested = false; mActivityMetricsLogger.notifyVisibilityChanged(noDrawnActivity); verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(noDrawnActivity)); @@ -216,7 +222,9 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase { mActivityMetricsLogger.logAppTransitionReportedDrawn(mTopActivity, false); notifyTransitionStarting(mTopActivity); // The pending fully drawn event should send when the actual windows drawn event occurs. - notifyWindowsDrawn(mTopActivity); + final ActivityMetricsLogger.TransitionInfoSnapshot info = notifyWindowsDrawn(mTopActivity); + assertWithMessage("Hot launch").that(info.getLaunchState()) + .isEqualTo(WaitResult.LAUNCH_STATE_HOT); verifyAsync(mLaunchObserver).onReportFullyDrawn(eqProto(mTopActivity), anyLong()); verifyOnActivityLaunchFinished(mTopActivity); @@ -260,8 +268,8 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase { mActivityMetricsLogger.notifyTransitionStarting(reasons); } - private void notifyWindowsDrawn(ActivityRecord r) { - mActivityMetricsLogger.notifyWindowsDrawn(r, SystemClock.elapsedRealtimeNanos()); + private ActivityMetricsLogger.TransitionInfoSnapshot notifyWindowsDrawn(ActivityRecord r) { + return mActivityMetricsLogger.notifyWindowsDrawn(r, SystemClock.elapsedRealtimeNanos()); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java index 880c486c15af..d42ab72a22b7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java @@ -20,6 +20,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.DisplayArea.Type.ABOVE_TASKS; import static com.android.server.wm.DisplayArea.Type.ANY; import static com.android.server.wm.DisplayArea.Type.BELOW_TASKS; @@ -29,11 +32,15 @@ import static com.android.server.wm.DisplayArea.Type.typeOf; import static com.android.server.wm.testing.Assert.assertThrows; import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import android.content.pm.ActivityInfo; import android.os.Binder; import android.platform.test.annotations.Presubmit; import android.view.SurfaceControl; +import android.view.View; +import android.view.WindowManager; import org.junit.Rule; import org.junit.Test; @@ -97,6 +104,42 @@ public class DisplayAreaTest { assertThrows(IllegalStateException.class, () -> checkChild(BELOW_TASKS, ANY)); } + + @Test + public void testGetOrientation() { + final DisplayArea.Tokens area = new DisplayArea.Tokens(mWmsRule.getWindowManagerService(), + ABOVE_TASKS, "test"); + final WindowToken token = createWindowToken(TYPE_APPLICATION_OVERLAY); + spyOn(token); + doReturn(mock(DisplayContent.class)).when(token).getDisplayContent(); + doNothing().when(token).setParent(any()); + final WindowState win = createWindowState(token); + spyOn(win); + doNothing().when(win).setParent(any()); + win.mAttrs.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; + token.addChild(win, 0); + area.addChild(token); + + doReturn(true).when(win).isVisible(); + + assertEquals("Visible window can request orientation", + ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, + area.getOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR)); + + doReturn(false).when(win).isVisible(); + + assertEquals("Invisible window cannot request orientation", + ActivityInfo.SCREEN_ORIENTATION_NOSENSOR, + area.getOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR)); + } + + private WindowState createWindowState(WindowToken token) { + return new WindowState(mWmsRule.getWindowManagerService(), mock(Session.class), + new TestIWindow(), token, null /* parentWindow */, 0 /* appOp */, 0 /* seq*/, + new WindowManager.LayoutParams(), View.VISIBLE, 0 /* ownerId */, 0 /* showUserId */, + false /* ownerCanAddInternalSystemWindow */, null); + } + private WindowToken createWindowToken(int type) { return new WindowToken(mWmsRule.getWindowManagerService(), new Binder(), type, false /* persist */, null /* displayContent */, diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 1948003a7499..d99606b704e4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -32,6 +32,7 @@ import static android.view.Display.FLAG_PRIVATE; import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT; import static android.view.DisplayCutout.BOUNDS_POSITION_TOP; import static android.view.DisplayCutout.fromBoundingRect; +import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_90; import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN; @@ -102,6 +103,7 @@ import android.view.IDisplayWindowRotationCallback; import android.view.IDisplayWindowRotationController; import android.view.ISystemGestureExclusionListener; import android.view.IWindowManager; +import android.view.InsetsState; import android.view.MotionEvent; import android.view.Surface; import android.view.SurfaceControl.Transaction; @@ -1114,6 +1116,17 @@ public class DisplayContentTests extends WindowTestsBase { assertTrue(mNavBarWindow.getParent().isAnimating(WindowContainer.AnimationFlags.PARENTS, ANIMATION_TYPE_FIXED_TRANSFORM)); + // If the visibility of insets state is changed, the rotated state should be updated too. + final InsetsState rotatedState = app.getFixedRotationTransformInsetsState(); + final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState(); + assertEquals(state.getSource(ITYPE_STATUS_BAR).isVisible(), + rotatedState.getSource(ITYPE_STATUS_BAR).isVisible()); + state.getSource(ITYPE_STATUS_BAR).setVisible( + !rotatedState.getSource(ITYPE_STATUS_BAR).isVisible()); + mDisplayContent.getInsetsStateController().notifyInsetsChanged(); + assertEquals(state.getSource(ITYPE_STATUS_BAR).isVisible(), + rotatedState.getSource(ITYPE_STATUS_BAR).isVisible()); + final Rect outFrame = new Rect(); final Rect outInsets = new Rect(); final Rect outStableInsets = new Rect(); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java index 58d4104bf2b0..7e3613411b37 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java @@ -52,10 +52,13 @@ import static android.view.WindowManagerPolicyConstants.ALT_BAR_LEFT; import static android.view.WindowManagerPolicyConstants.ALT_BAR_RIGHT; import static android.view.WindowManagerPolicyConstants.ALT_BAR_TOP; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; + import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertThat; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.spy; import static org.testng.Assert.expectThrows; @@ -927,6 +930,25 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { } @Test + public void testFixedRotationInsetsSourceFrame() { + final DisplayInfo info = mDisplayContent.getDisplayInfo(); + info.rotation = mFrames.mRotation; + mDisplayContent.mBaseDisplayHeight = info.logicalHeight = mFrames.mDisplayHeight; + mDisplayContent.mBaseDisplayWidth = info.logicalWidth = mFrames.mDisplayWidth; + mDisplayContent.getInsetsStateController().onPostLayout(); + mDisplayPolicy.beginLayoutLw(mFrames, mDisplayContent.getConfiguration().uiMode); + doReturn((mDisplayContent.getRotation() + 1) % 4).when(mDisplayContent) + .rotationForActivityInDifferentOrientation(eq(mWindow.mActivityRecord)); + final Rect frame = mWindow.getInsetsState().getSource(ITYPE_STATUS_BAR).getFrame(); + doReturn(mDisplayPolicy).when(mDisplayContent).getDisplayPolicy(); + mDisplayContent.rotateInDifferentOrientationIfNeeded(mWindow.mActivityRecord); + final Rect rotatedFrame = mWindow.getInsetsState().getSource(ITYPE_STATUS_BAR).getFrame(); + + assertEquals(DISPLAY_WIDTH, frame.width()); + assertEquals(DISPLAY_HEIGHT, rotatedFrame.width()); + } + + @Test public void testScreenDecorWindows() { final WindowState decorWindow = createWindow(null, TYPE_APPLICATION_OVERLAY, "decorWindow"); mWindow.mAttrs.flags = FLAG_NOT_FOCUSABLE | FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java index 90af8a1b3199..7d84920187a0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java @@ -38,10 +38,13 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import android.app.StatusBarManager; import android.platform.test.annotations.Presubmit; import android.view.InsetsSourceControl; import android.view.InsetsState; @@ -49,6 +52,8 @@ import android.view.test.InsetsModeSession; import androidx.test.filters.SmallTest; +import com.android.server.statusbar.StatusBarManagerInternal; + import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -222,6 +227,23 @@ public class InsetsPolicyTest extends WindowTestsBase { assertNotNull(fullscreenAppControls); assertEquals(1, fullscreenAppControls.length); assertEquals(ITYPE_STATUS_BAR, fullscreenAppControls[0].getType()); + + // Assume mFocusedWindow is updated but mTopFullscreenOpaqueWindowState hasn't. + final WindowState newFocusedFullscreenApp = addWindow(TYPE_APPLICATION, "newFullscreenApp"); + final InsetsState newRequestedState = new InsetsState(); + newRequestedState.getSource(ITYPE_STATUS_BAR).setVisible(true); + newFocusedFullscreenApp.updateRequestedInsetsState(newRequestedState); + // Make sure status bar is hidden by previous insets state. + mDisplayContent.getInsetsPolicy().updateBarControlTarget(fullscreenApp); + + final StatusBarManagerInternal sbmi = + mDisplayContent.getDisplayPolicy().getStatusBarManagerInternal(); + clearInvocations(sbmi); + mDisplayContent.getInsetsPolicy().updateBarControlTarget(newFocusedFullscreenApp); + // The status bar should be shown by newFocusedFullscreenApp even + // mTopFullscreenOpaqueWindowState is still fullscreenApp. + verify(sbmi).setWindowState(mDisplayContent.mDisplayId, StatusBarManager.WINDOW_STATUS_BAR, + StatusBarManager.WINDOW_STATE_SHOWING); } @Test @@ -309,6 +331,15 @@ public class InsetsPolicyTest extends WindowTestsBase { final InsetsState state = policy.getInsetsForDispatch(mAppWindow); state.setSourceVisible(ITYPE_STATUS_BAR, true); state.setSourceVisible(ITYPE_NAVIGATION_BAR, true); + + final InsetsState clientState = mAppWindow.getInsetsState(); + // The transient bar states for client should be invisible. + assertFalse(clientState.getSource(ITYPE_STATUS_BAR).isVisible()); + assertFalse(clientState.getSource(ITYPE_NAVIGATION_BAR).isVisible()); + // The original state shouldn't be modified. + assertTrue(state.getSource(ITYPE_STATUS_BAR).isVisible()); + assertTrue(state.getSource(ITYPE_NAVIGATION_BAR).isVisible()); + policy.onInsetsModified(mAppWindow, state); waitUntilWindowAnimatorIdle(); diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java index 73ac408f7980..3db00189e525 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java @@ -30,6 +30,9 @@ import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -329,6 +332,26 @@ public class InsetsStateControllerTest extends WindowTestsBase { assertNull(getController().getControlsForDispatch(app)); } + @Test + public void testTransientVisibilityOfFixedRotationState() { + final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); + final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); + final InsetsSourceProvider provider = getController().getSourceProvider(ITYPE_STATUS_BAR); + provider.setWindow(statusBar, null, null); + + final InsetsState rotatedState = new InsetsState(app.getInsetsState(), + true /* copySources */); + spyOn(app.mToken); + doReturn(rotatedState).when(app.mToken).getFixedRotationTransformInsetsState(); + assertTrue(rotatedState.getSource(ITYPE_STATUS_BAR).isVisible()); + + provider.getSource().setVisible(false); + mDisplayContent.getInsetsPolicy().showTransient(new int[] { ITYPE_STATUS_BAR }); + + assertTrue(mDisplayContent.getInsetsPolicy().isTransient(ITYPE_STATUS_BAR)); + assertFalse(app.getInsetsState().getSource(ITYPE_STATUS_BAR).isVisible()); + } + private InsetsStateController getController() { return mDisplayContent.getInsetsStateController(); } diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java index f2771175b523..d99fd0f3d18e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java @@ -393,8 +393,25 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { // Simulate giving up the swipe up gesture to keep the original activity as top. mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION); // The rotation transform should be cleared after updating orientation with display. - assertFalse(activity.hasFixedRotationTransform()); - assertFalse(mDefaultDisplay.hasTopFixedRotationLaunchingApp()); + assertTopFixedRotationLaunchingAppCleared(activity); + + // Simulate swiping up recents (home) in different rotation. + final ActivityRecord home = mDefaultDisplay.getDefaultTaskDisplayArea().getHomeActivity(); + startRecentsInDifferentRotation(home); + + // If the recents activity becomes the top running activity (e.g. the original top activity + // is either finishing or moved to back during recents animation), the display orientation + // will be determined by it so the fixed rotation must be cleared. + activity.finishing = true; + mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION); + assertTopFixedRotationLaunchingAppCleared(home); + + startRecentsInDifferentRotation(home); + // Assume recents activity becomes invisible for some reason (e.g. screen off). + home.setVisible(false); + mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION); + // Although there won't be a transition finish callback, the fixed rotation must be cleared. + assertTopFixedRotationLaunchingAppCleared(home); } @Test @@ -422,6 +439,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { final WindowState homeWindow = createWindow(null, TYPE_BASE_APPLICATION, homeActivity, "homeWindow"); + makeWindowVisible(homeWindow); homeActivity.addWindow(homeWindow); homeWindow.getAttrs().flags |= FLAG_SHOW_WALLPAPER; @@ -487,6 +505,21 @@ public class RecentsAnimationControllerTest extends WindowTestsBase { return homeActivity; } + private void startRecentsInDifferentRotation(ActivityRecord recentsActivity) { + final DisplayContent displayContent = recentsActivity.mDisplayContent; + displayContent.setFixedRotationLaunchingApp(recentsActivity, + (displayContent.getRotation() + 1) % 4); + mController = new RecentsAnimationController(mWm, mMockRunner, mAnimationCallbacks, + displayContent.getDisplayId()); + initializeRecentsAnimationController(mController, recentsActivity); + assertTrue(recentsActivity.hasFixedRotationTransform()); + } + + private static void assertTopFixedRotationLaunchingAppCleared(ActivityRecord activity) { + assertFalse(activity.hasFixedRotationTransform()); + assertFalse(activity.mDisplayContent.hasTopFixedRotationLaunchingApp()); + } + private static void initializeRecentsAnimationController(RecentsAnimationController controller, ActivityRecord activity) { controller.initialize(activity.getActivityType(), new SparseBooleanArray(), activity); diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index a979c862a8e4..250dc2469be1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -568,6 +568,8 @@ public class SizeCompatTests extends ActivityTestsBase { private static WindowState addWindowToActivity(ActivityRecord activity) { final WindowManager.LayoutParams params = new WindowManager.LayoutParams(); params.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; + params.setFitInsetsSides(0); + params.setFitInsetsTypes(0); final WindowTestUtils.TestWindowState w = new WindowTestUtils.TestWindowState( activity.mWmService, mock(Session.class), new TestIWindow(), params, activity); WindowTestsBase.makeWindowVisible(w); |