summaryrefslogtreecommitdiff
path: root/services/tests
diff options
context:
space:
mode:
Diffstat (limited to 'services/tests')
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java33
-rw-r--r--services/tests/servicestests/AndroidManifest.xml1
-rw-r--r--services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java25
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/gestures/GestureManifoldTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java76
-rw-r--r--services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java70
-rw-r--r--services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java23
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java3
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/FakeSystemClock.java111
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java145
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java48
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java6
-rw-r--r--services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java11
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java18
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java43
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java22
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java31
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java23
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java37
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java2
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);