Merge "Allowlist test namespace." into udc-dev
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 5c2b389..402da28 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -1008,9 +1008,8 @@
                 .allowAlarms(allowAlarms)
                 .allowMedia(allowMedia)
                 .allowSystem(allowSystem)
-                .allowConversations(allowConversations
-                        ? ZenModeConfig.getZenPolicySenders(allowConversationsFrom)
-                        : ZenPolicy.PEOPLE_TYPE_NONE);
+                .allowConversations(allowConversations ? allowConversationsFrom
+                        : ZenPolicy.CONVERSATION_SENDERS_NONE);
         if (suppressedVisualEffects == 0) {
             builder.showAllVisualEffects();
         } else {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 48686fc..02b3478 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -869,6 +869,42 @@
             "android.window.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION";
 
     /**
+     * Application level {@link android.content.pm.PackageManager.Property PackageManager.Property}
+     * for an app to inform the system that the app can be opted-out from the compatibility
+     * treatment that avoids {@link android.app.Activity#setRequestedOrientation} loops. The loop
+     * can be trigerred by ignoreRequestedOrientation display setting enabled on the device or
+     * by the landscape natural orientation of the device.
+     *
+     * <p>The system could ignore {@link android.app.Activity#setRequestedOrientation}
+     * call from an app if both of the following conditions are true:
+     * <ul>
+     *     <li>Activity has requested orientation more than 2 times within 1-second timer
+     *     <li>Activity is not letterboxed for fixed orientation
+     * </ul>
+     *
+     * <p>Setting this property to {@code false} informs the system that the app must be
+     * opted-out from the compatibility treatment even if the device manufacturer has opted the app
+     * into the treatment.
+     *
+     * <p>Not setting this property at all, or setting this property to {@code true} has no effect.
+     *
+     * <p><b>Syntax:</b>
+     * <pre>
+     * &lt;application&gt;
+     *   &lt;property
+     *     android:name=
+     *       "android.window.PROPERTY_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED"
+     *     android:value="false"/&gt;
+     * &lt;/application&gt;
+     * </pre>
+     *
+     * @hide
+     */
+    // TODO(b/274924641): Make this public API.
+    String PROPERTY_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED =
+            "android.window.PROPERTY_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED";
+
+    /**
      * Application level {@link android.content.pm.PackageManager.Property PackageManager
      * .Property} for an app to inform the system that it needs to be opted-out from the
      * compatibility treatment that sandboxes {@link android.view.View} API.
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt
index 8f1c904..30ee147 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt
@@ -63,6 +63,10 @@
                 override fun onStateChanged(newState: Int) {
                     refreshMediaPosition()
                 }
+
+                override fun onDozingChanged(isDozing: Boolean) {
+                    refreshMediaPosition()
+                }
             }
         )
         configurationController.addCallback(
@@ -198,7 +202,8 @@
             mediaHost.visible &&
                 !bypassController.bypassEnabled &&
                 keyguardOrUserSwitcher &&
-                allowMediaPlayerOnLockScreen
+                allowMediaPlayerOnLockScreen &&
+                shouldBeVisibleForSplitShade()
         if (visible) {
             showMediaPlayer()
         } else {
@@ -206,6 +211,19 @@
         }
     }
 
+    private fun shouldBeVisibleForSplitShade(): Boolean {
+        if (!useSplitShade) {
+            return true
+        }
+        // We have to explicitly hide media for split shade when on AOD, as it is a child view of
+        // keyguard status view, and nothing hides keyguard status view on AOD.
+        // When using the double-line clock, it is not an issue, as media gets implicitly hidden
+        // by the clock. This is not the case for single-line clock though.
+        // For single shade, we don't need to do it, because media is a child of NSSL, which already
+        // gets hidden on AOD.
+        return !statusBarStateController.isDozing
+    }
+
     private fun showMediaPlayer() {
         if (useSplitShade) {
             setVisibility(splitShadeContainer, View.VISIBLE)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/KeyguardMediaControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/KeyguardMediaControllerTest.kt
index 2026006..b40ebc9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/KeyguardMediaControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/KeyguardMediaControllerTest.kt
@@ -24,12 +24,14 @@
 import android.view.View.VISIBLE
 import android.widget.FrameLayout
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.statusbar.StatusBarState
 import com.android.systemui.statusbar.SysuiStatusBarStateController
 import com.android.systemui.statusbar.notification.stack.MediaContainerView
 import com.android.systemui.statusbar.phone.KeyguardBypassController
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.util.animation.UniqueObjectHostView
+import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.settings.FakeSettings
 import com.android.systemui.utils.os.FakeHandler
 import com.google.common.truth.Truth.assertThat
@@ -39,8 +41,9 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
+import org.mockito.Mockito.any
+import org.mockito.Mockito.doAnswer
 import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
 import org.mockito.junit.MockitoJUnit
 
 @SmallTest
@@ -61,9 +64,16 @@
     private lateinit var keyguardMediaController: KeyguardMediaController
     private lateinit var testableLooper: TestableLooper
     private lateinit var fakeHandler: FakeHandler
+    private lateinit var statusBarStateListener: StatusBarStateController.StateListener
 
     @Before
     fun setup() {
+        doAnswer {
+                statusBarStateListener = it.arguments[0] as StatusBarStateController.StateListener
+                return@doAnswer Unit
+            }
+            .whenever(statusBarStateController)
+            .addCallback(any(StatusBarStateController.StateListener::class.java))
         // default state is positive, media should show up
         whenever(mediaHost.visible).thenReturn(true)
         whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
@@ -170,4 +180,31 @@
     fun testMediaHost_expandedPlayer() {
         verify(mediaHost).expansion = MediaHostState.EXPANDED
     }
+
+    @Test
+    fun dozing_inSplitShade_mediaIsHidden() {
+        val splitShadeContainer = FrameLayout(context)
+        keyguardMediaController.attachSplitShadeContainer(splitShadeContainer)
+        keyguardMediaController.useSplitShade = true
+
+        setDozing()
+
+        assertThat(splitShadeContainer.visibility).isEqualTo(GONE)
+    }
+
+    @Test
+    fun dozing_inSingleShade_mediaIsVisible() {
+        val splitShadeContainer = FrameLayout(context)
+        keyguardMediaController.attachSplitShadeContainer(splitShadeContainer)
+        keyguardMediaController.useSplitShade = false
+
+        setDozing()
+
+        assertThat(mediaContainerView.visibility).isEqualTo(VISIBLE)
+    }
+
+    private fun setDozing() {
+        whenever(statusBarStateController.isDozing).thenReturn(true)
+        statusBarStateListener.onDozingChanged(true)
+    }
 }
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index 6773bcd..e447049 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -487,7 +487,7 @@
                 // The verdict changed from allow (resultIfPiSenderAllowsBal) to block, PI sender
                 // default change is on (otherwise we would have fallen into if above) and we'd
                 // allow if it were off
-                Slog.wtf(TAG, "Without BAL hardening this activity start would NOT be allowed!"
+                Slog.wtf(TAG, "Without BAL hardening this activity start would be allowed!"
                         + stateDumpLog);
             }
         }
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index 18d92f3..93233dd 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -50,6 +50,7 @@
 import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE;
 import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE;
 import static android.view.WindowManager.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS;
+import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED;
 import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION;
 
 import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__BOTTOM;
@@ -235,6 +236,9 @@
     private final Boolean mBooleanPropertyIgnoreRequestedOrientation;
 
     @Nullable
+    private final Boolean mBooleanPropertyIgnoreOrientationRequestWhenLoopDetected;
+
+    @Nullable
     private final Boolean mBooleanPropertyFakeFocus;
 
     private boolean mIsRelaunchingAfterRequestedOrientationChanged;
@@ -255,6 +259,10 @@
                 readComponentProperty(packageManager, mActivityRecord.packageName,
                         mLetterboxConfiguration::isPolicyForIgnoringRequestedOrientationEnabled,
                         PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION);
+        mBooleanPropertyIgnoreOrientationRequestWhenLoopDetected =
+                readComponentProperty(packageManager, mActivityRecord.packageName,
+                        mLetterboxConfiguration::isPolicyForIgnoringRequestedOrientationEnabled,
+                        PROPERTY_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED);
         mBooleanPropertyFakeFocus =
                 readComponentProperty(packageManager, mActivityRecord.packageName,
                         mLetterboxConfiguration::isCompatFakeFocusEnabled,
@@ -424,6 +432,8 @@
      *
      * <p>This treatment is enabled when the following conditions are met:
      * <ul>
+     *     <li>Flag gating the treatment is enabled
+     *     <li>Opt-out component property isn't enabled
      *     <li>Per-app override is enabled
      *     <li>App has requested orientation more than 2 times within 1-second
      *     timer and activity is not letterboxed for fixed orientation
@@ -431,7 +441,11 @@
      */
     @VisibleForTesting
     boolean shouldIgnoreOrientationRequestLoop() {
-        if (!mIsOverrideEnableCompatIgnoreOrientationRequestWhenLoopDetectedEnabled) {
+        if (!shouldEnableWithOptInOverrideAndOptOutProperty(
+                /* gatingCondition */ mLetterboxConfiguration
+                    ::isPolicyForIgnoringRequestedOrientationEnabled,
+                mIsOverrideEnableCompatIgnoreOrientationRequestWhenLoopDetectedEnabled,
+                mBooleanPropertyIgnoreOrientationRequestWhenLoopDetected)) {
             return false;
         }
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
index 893f538..3ba9400 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
@@ -120,12 +120,20 @@
                 .showLights(false)
                 .showBadges(false)
                 .showInAmbientDisplay(false)
+                .allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS)
+                .allowMessages(ZenPolicy.PEOPLE_TYPE_STARRED)
+                .allowConversations(ZenPolicy.CONVERSATION_SENDERS_NONE)
                 .build();
 
         ZenModeConfig config = getMutedAllConfig();
         config.allowAlarms = true;
         config.allowReminders = true;
         config.allowEvents = true;
+        config.allowCalls = true;
+        config.allowCallsFrom = Policy.PRIORITY_SENDERS_CONTACTS;
+        config.allowMessages = true;
+        config.allowMessagesFrom = Policy.PRIORITY_SENDERS_STARRED;
+        config.allowConversations = false;
         config.suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_BADGE;
         config.suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_LIGHTS;
         config.suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_AMBIENT;
@@ -138,6 +146,10 @@
         assertEquals(expected.getPriorityCategoryEvents(), actual.getPriorityCategoryEvents());
         assertEquals(expected.getVisualEffectLights(), actual.getVisualEffectLights());
         assertEquals(expected.getVisualEffectAmbient(), actual.getVisualEffectAmbient());
+        assertEquals(expected.getPriorityConversationSenders(),
+                actual.getPriorityConversationSenders());
+        assertEquals(expected.getPriorityCallSenders(), actual.getPriorityCallSenders());
+        assertEquals(expected.getPriorityMessageSenders(), actual.getPriorityMessageSenders());
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
index 2ecde8b..a15ee69 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
@@ -41,6 +41,7 @@
 import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE;
 import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE;
 import static android.view.WindowManager.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS;
+import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED;
 import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -190,6 +191,8 @@
 
     @Test
     public void testShouldIgnoreOrientationRequestLoop_overrideDisabled_returnsFalse() {
+        doReturn(true).when(mLetterboxConfiguration)
+                .isPolicyForIgnoringRequestedOrientationEnabled();
         doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio();
         // Request 3 times to simulate orientation request loop
         for (int i = 0; i <= MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) {
@@ -200,8 +203,30 @@
 
     @Test
     @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED})
+    public void testShouldIgnoreOrientationRequestLoop_propertyIsFalseAndOverride_returnsFalse()
+            throws Exception {
+        doReturn(true).when(mLetterboxConfiguration)
+                .isPolicyForIgnoringRequestedOrientationEnabled();
+        mockThatProperty(PROPERTY_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED,
+                /* value */ false);
+        doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio();
+
+        mController = new LetterboxUiController(mWm, mActivity);
+
+        // Request 3 times to simulate orientation request loop
+        for (int i = 0; i <= MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) {
+            assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false,
+                    /* expectedCount */ 0);
+        }
+    }
+
+    @Test
+    @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED})
     public void testShouldIgnoreOrientationRequestLoop_isLetterboxed_returnsFalse() {
+        doReturn(true).when(mLetterboxConfiguration)
+                .isPolicyForIgnoringRequestedOrientationEnabled();
         doReturn(true).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio();
+
         // Request 3 times to simulate orientation request loop
         for (int i = 0; i <= MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) {
             assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false,
@@ -212,7 +237,10 @@
     @Test
     @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED})
     public void testShouldIgnoreOrientationRequestLoop_noLoop_returnsFalse() {
+        doReturn(true).when(mLetterboxConfiguration)
+                .isPolicyForIgnoringRequestedOrientationEnabled();
         doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio();
+
         // No orientation request loop
         assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false,
                 /* expectedCount */ 0);
@@ -222,7 +250,10 @@
     @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED})
     public void testShouldIgnoreOrientationRequestLoop_timeout_returnsFalse()
             throws InterruptedException {
+        doReturn(true).when(mLetterboxConfiguration)
+                .isPolicyForIgnoringRequestedOrientationEnabled();
         doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio();
+
         for (int i = MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i > 0; i--) {
             assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false,
                     /* expectedCount */ 0);
@@ -233,7 +264,10 @@
     @Test
     @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED})
     public void testShouldIgnoreOrientationRequestLoop_returnsTrue() {
+        doReturn(true).when(mLetterboxConfiguration)
+                .isPolicyForIgnoringRequestedOrientationEnabled();
         doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio();
+
         for (int i = 0; i < MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) {
             assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false,
                     /* expectedCount */ i);