Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 65646eac authored by Alina Zaidi's avatar Alina Zaidi Committed by Android (Google) Code Review
Browse files

Merge "Make external display status bar non-interactive if shade doesn't go around." into main

parents a827bc32 ac41d2e8
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.systemui.statusbar.phone;

import static android.view.Display.DEFAULT_DISPLAY;

import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
@@ -41,6 +43,7 @@ import com.android.systemui.Gefingerpoken;
import com.android.systemui.res.R;
import com.android.systemui.shade.ShadeExpandsOnStatusBarLongPress;
import com.android.systemui.shade.StatusBarLongPressGestureDetector;
import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround;
import com.android.systemui.statusbar.core.StatusBarConnectedDisplays;
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer;
import com.android.systemui.statusbar.window.StatusBarWindowControllerStore;
@@ -54,6 +57,8 @@ public class PhoneStatusBarView extends FrameLayout {
    private static final String TAG = "PhoneStatusBarView";
    private final StatusBarWindowControllerStore mStatusBarWindowControllerStore;

    private final boolean mShouldAllowInteractions;

    private int mRotationOrientation = -1;
    @Nullable
    private View mCutoutSpace;
@@ -80,6 +85,10 @@ public class PhoneStatusBarView extends FrameLayout {
    public PhoneStatusBarView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mStatusBarWindowControllerStore = Dependency.get(StatusBarWindowControllerStore.class);
        // With the StatusBarConnectedDisplays changes, status bar elements are only interactive
        // if touch is on default display or the shade window can change displays.
        mShouldAllowInteractions = !StatusBarConnectedDisplays.isEnabled()
                || mContext.getDisplayId() == DEFAULT_DISPLAY || ShadeWindowGoesAround.isEnabled();
    }

    void setLongPressGestureDetector(
@@ -207,8 +216,17 @@ public class PhoneStatusBarView extends FrameLayout {
        return false;
    }

    /** Whether this status bar and its elements should be interactable. */
    public boolean shouldAllowInteractions() {
        return mShouldAllowInteractions;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!shouldAllowInteractions()) {
            return false;
        }

        if (ShadeExpandsOnStatusBarLongPress.isEnabled()
                && mStatusBarLongPressGestureDetector != null) {
            mStatusBarLongPressGestureDetector.handleTouch(event);
+10 −18
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.systemui.statusbar.phone
import android.app.StatusBarManager.WINDOW_STATUS_BAR
import android.graphics.Point
import android.util.Log
import android.view.Display.DEFAULT_DISPLAY
import android.view.InputDevice
import android.view.MotionEvent
import android.view.View
@@ -138,11 +137,13 @@ private constructor(
        clock = mView.requireViewById(R.id.clock)
        battery = mView.requireViewById(R.id.battery)
        addDarkReceivers()
        if (mView.shouldAllowInteractions()) {
            addCursorSupportToIconContainers()

            if (ShadeExpandsOnStatusBarLongPress.isEnabled) {
                mView.setLongPressGestureDetector(statusBarLongPressGestureDetector.get())
            }
        }

        progressProvider?.setReadyToHandleTransition(true)
        configurationController.addCallback(configurationListener)
@@ -204,8 +205,10 @@ private constructor(
    @VisibleForTesting
    public override fun onViewDetached() {
        removeDarkReceivers()
        if (mView.shouldAllowInteractions()) {
            startSideContainer.setOnHoverListener(null)
            endSideContainer.setOnHoverListener(null)
        }
        progressProvider?.setReadyToHandleTransition(false)
        moveFromCenterAnimationController?.onViewDetached()
        configurationController.removeCallback(configurationListener)
@@ -323,18 +326,7 @@ private constructor(
                }
            }

            // With the StatusBarConnectedDisplays changes, status bar touches should result in
            // shade interaction only if ShadeWindowGoesAround.isEnabled or if touch is on default
            // display.
            return if (
                !StatusBarConnectedDisplays.isEnabled ||
                    ShadeWindowGoesAround.isEnabled ||
                    context.displayId == DEFAULT_DISPLAY
            ) {
                shadeViewController.handleExternalTouch(event)
            } else {
                false
            }
            return shadeViewController.handleExternalTouch(event)
        }
    }

+73 −36
Original line number Diff line number Diff line
@@ -71,7 +71,6 @@ import com.android.systemui.unfold.config.UnfoldTransitionConfig
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.view.ViewUtil
import com.google.common.truth.Truth.assertThat
import dagger.Lazy
@@ -86,10 +85,10 @@ import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.any
import org.mockito.kotlin.eq
import org.mockito.kotlin.whenever

@SmallTest
@RunWith(AndroidJUnit4::class)
@@ -108,6 +107,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
    @Mock private lateinit var sysuiUnfoldComponent: SysUIUnfoldComponent
    @Mock private lateinit var progressProvider: ScopedUnfoldTransitionProgressProvider
    @Mock private lateinit var mStatusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory
    @Mock private lateinit var mStatusOverlayHoverListener: StatusOverlayHoverListener
    @Mock private lateinit var userChipViewModel: StatusBarUserChipViewModel
    @Mock private lateinit var centralSurfacesImpl: CentralSurfacesImpl
    @Mock private lateinit var commandQueue: CommandQueue
@@ -142,11 +142,13 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
        configurationController =
            fakeConfigurationControllerStore.forDisplay(Display.DEFAULT_DISPLAY)

        `when`(statusBarContentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
        whenever(statusBarContentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
            .thenReturn(Insets.NONE)

        `when`(sysuiUnfoldComponent.getStatusBarMoveFromCenterAnimationController())
        whenever(sysuiUnfoldComponent.getStatusBarMoveFromCenterAnimationController())
            .thenReturn(moveFromCenterAnimation)
        whenever(mStatusOverlayHoverListenerFactory.createDarkAwareListener(any()))
            .thenReturn(mStatusOverlayHoverListener)

        // create the view and controller on main thread as it requires main looper
        InstrumentationRegistry.getInstrumentation().runOnMainSync {
            val parent = FrameLayout(mContext) // add parent to keep layout params
@@ -156,7 +158,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
            controller = createAndInitController(view)
        }

        `when`(
        whenever(
                statusBarContentInsetsProviderForSecondaryDisplay
                    .getStatusBarContentInsetsForCurrentRotation()
            )
@@ -238,6 +240,40 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
        verify(moveFromCenterAnimation, never()).onViewsReady(any())
    }

    @Test
    fun onViewAttached_statusBarInteractable_containersInteractive() {
        val view = createViewMock(allowInteractions = true)
        val endSideContainer = spy(view.requireViewById<View>(R.id.system_icons))
        whenever(view.requireViewById<View>(R.id.system_icons)).thenReturn(endSideContainer)
        val statusContainer = spy(view.requireViewById<View>(R.id.status_bar_start_side_content))
        whenever(view.requireViewById<View>(R.id.status_bar_start_side_content))
            .thenReturn(statusContainer)

        InstrumentationRegistry.getInstrumentation().runOnMainSync {
            controller = createAndInitController(view)
        }

        verify(endSideContainer).setOnHoverListener(any())
        verify(statusContainer).setOnTouchListener(any())
    }

    @Test
    fun onViewAttached_statusBarNonInteractable_containersNonInteractive() {
        val view = createViewMock(allowInteractions = false)
        val endSideContainer = spy(view.requireViewById<View>(R.id.system_icons))
        whenever(view.requireViewById<View>(R.id.system_icons)).thenReturn(endSideContainer)
        val statusContainer = spy(view.requireViewById<View>(R.id.status_bar_start_side_content))
        whenever(view.requireViewById<View>(R.id.status_bar_start_side_content))
            .thenReturn(statusContainer)

        InstrumentationRegistry.getInstrumentation().runOnMainSync {
            controller = createAndInitController(view)
        }

        verify(endSideContainer, never()).setOnHoverListener(any())
        verify(statusContainer, never()).setOnTouchListener(any())
    }

    @Test
    fun onViewDetached_darkReceiversUnregistered() {
        val view = createViewMock()
@@ -255,7 +291,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {

    @Test
    fun handleTouchEventFromStatusBar_panelsNotEnabled_returnsFalseAndNoViewEvent() {
        `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(false)
        whenever(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(false)
        val returnVal =
            view.onTouchEvent(MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0))
        assertThat(returnVal).isFalse()
@@ -264,8 +300,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {

    @Test
    fun handleTouchEventFromStatusBar_viewNotEnabled_returnsTrueAndNoViewEvent() {
        `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        `when`(shadeViewController.isViewEnabled).thenReturn(false)
        whenever(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        whenever(shadeViewController.isViewEnabled).thenReturn(false)
        val returnVal =
            view.onTouchEvent(MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0))
        assertThat(returnVal).isTrue()
@@ -274,8 +310,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {

    @Test
    fun handleTouchEventFromStatusBar_viewNotEnabledButIsMoveEvent_viewReceivesEvent() {
        `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        `when`(shadeViewController.isViewEnabled).thenReturn(false)
        whenever(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        whenever(shadeViewController.isViewEnabled).thenReturn(false)
        val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 2f, 0)

        view.onTouchEvent(event)
@@ -285,8 +321,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {

    @Test
    fun handleTouchEventFromStatusBar_panelAndViewEnabled_viewReceivesEvent() {
        `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        `when`(shadeViewController.isViewEnabled).thenReturn(true)
        whenever(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        whenever(shadeViewController.isViewEnabled).thenReturn(true)
        val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0)

        view.onTouchEvent(event)
@@ -296,8 +332,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {

    @Test
    fun handleTouchEventFromStatusBar_topEdgeTouch_viewNeverReceivesEvent() {
        `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        `when`(panelExpansionInteractor.isFullyCollapsed).thenReturn(true)
        whenever(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        whenever(panelExpansionInteractor.isFullyCollapsed).thenReturn(true)
        val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)

        view.onTouchEvent(event)
@@ -308,8 +344,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
    @Test
    @DisableFlags(StatusBarConnectedDisplays.FLAG_NAME)
    fun handleTouchEventFromStatusBar_touchOnPrimaryDisplay_statusBarConnectedDisplaysDisabled_shadeReceivesEvent() {
        `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        `when`(shadeViewController.isViewEnabled).thenReturn(true)
        whenever(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        whenever(shadeViewController.isViewEnabled).thenReturn(true)
        val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0)

        view.onTouchEvent(event)
@@ -320,8 +356,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
    @Test
    @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME, ShadeWindowGoesAround.FLAG_NAME)
    fun handleTouchEventFromStatusBar_touchOnPrimaryDisplay_statusBarConnectedDisplaysEnabled_shadeWindowGoesAroundEnabled_shadeReceivesEvent() {
        `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        `when`(shadeViewController.isViewEnabled).thenReturn(true)
        whenever(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        whenever(shadeViewController.isViewEnabled).thenReturn(true)
        val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0)

        view.onTouchEvent(event)
@@ -333,8 +369,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
    @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME)
    @DisableFlags(ShadeWindowGoesAround.FLAG_NAME)
    fun handleTouchEventFromStatusBar_touchOnPrimaryDisplay_statusBarConnectedDisplaysEnabled_shadeWindowGoesAroundDisabled_shadeReceivesEvent() {
        `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        `when`(shadeViewController.isViewEnabled).thenReturn(true)
        whenever(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        whenever(shadeViewController.isViewEnabled).thenReturn(true)
        val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0)

        view.onTouchEvent(event)
@@ -345,8 +381,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
    @Test
    @DisableFlags(StatusBarConnectedDisplays.FLAG_NAME)
    fun handleTouchEventFromStatusBar_touchOnSecondaryDisplay_statusBarConnectedDisplaysDisabled_shadeReceivesEvent() {
        `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        `when`(shadeViewController.isViewEnabled).thenReturn(true)
        whenever(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        whenever(shadeViewController.isViewEnabled).thenReturn(true)
        val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0)

        viewForSecondaryDisplay.onTouchEvent(event)
@@ -357,8 +393,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
    @Test
    @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME, ShadeWindowGoesAround.FLAG_NAME)
    fun handleTouchEventFromStatusBar_touchOnSecondaryDisplay_statusBarConnectedDisplaysEnabled_shadeWindowGoesAroundEnabled_shadeReceivesEvent() {
        `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        `when`(shadeViewController.isViewEnabled).thenReturn(true)
        whenever(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        whenever(shadeViewController.isViewEnabled).thenReturn(true)
        val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0)

        viewForSecondaryDisplay.onTouchEvent(event)
@@ -370,8 +406,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
    @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME)
    @DisableFlags(ShadeWindowGoesAround.FLAG_NAME)
    fun handleTouchEventFromStatusBar_touchOnSecondaryDisplay_statusBarConnectedDisplaysEnabled_shadeWindowGoesAroundDisabled_shadeDoesNotReceiveEvent() {
        `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        `when`(shadeViewController.isViewEnabled).thenReturn(true)
        whenever(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true)
        whenever(shadeViewController.isViewEnabled).thenReturn(true)
        val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0)

        viewForSecondaryDisplay.onTouchEvent(event)
@@ -382,7 +418,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
    @Test
    @DisableFlags(com.android.systemui.Flags.FLAG_STATUS_BAR_SWIPE_OVER_CHIP)
    fun handleInterceptTouchEventFromStatusBar_shadeReturnsFalse_flagOff_viewReturnsFalse() {
        `when`(shadeViewController.handleExternalInterceptTouch(any())).thenReturn(false)
        whenever(shadeViewController.handleExternalInterceptTouch(any())).thenReturn(false)
        val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0)

        val returnVal = view.onInterceptTouchEvent(event)
@@ -393,7 +429,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
    @Test
    @EnableFlags(com.android.systemui.Flags.FLAG_STATUS_BAR_SWIPE_OVER_CHIP)
    fun handleInterceptTouchEventFromStatusBar_shadeReturnsFalse_flagOn_viewReturnsFalse() {
        `when`(shadeViewController.handleExternalInterceptTouch(any())).thenReturn(false)
        whenever(shadeViewController.handleExternalInterceptTouch(any())).thenReturn(false)
        val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0)

        val returnVal = view.onInterceptTouchEvent(event)
@@ -404,7 +440,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
    @Test
    @DisableFlags(com.android.systemui.Flags.FLAG_STATUS_BAR_SWIPE_OVER_CHIP)
    fun handleInterceptTouchEventFromStatusBar_shadeReturnsTrue_flagOff_viewReturnsFalse() {
        `when`(shadeViewController.handleExternalInterceptTouch(any())).thenReturn(true)
        whenever(shadeViewController.handleExternalInterceptTouch(any())).thenReturn(true)
        val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0)

        val returnVal = view.onInterceptTouchEvent(event)
@@ -415,7 +451,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
    @Test
    @EnableFlags(com.android.systemui.Flags.FLAG_STATUS_BAR_SWIPE_OVER_CHIP)
    fun handleInterceptTouchEventFromStatusBar_shadeReturnsTrue_flagOn_viewReturnsTrue() {
        `when`(shadeViewController.handleExternalInterceptTouch(any())).thenReturn(true)
        whenever(shadeViewController.handleExternalInterceptTouch(any())).thenReturn(true)
        val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0)

        val returnVal = view.onInterceptTouchEvent(event)
@@ -615,12 +651,13 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
        return captor.value!!
    }

    private fun createViewMock(): PhoneStatusBarView {
        val view = spy(view)
    private fun createViewMock(allowInteractions: Boolean = true): PhoneStatusBarView {
        val mView = spy(view)
        val viewTreeObserver = mock(ViewTreeObserver::class.java)
        `when`(view.viewTreeObserver).thenReturn(viewTreeObserver)
        `when`(view.isAttachedToWindow).thenReturn(true)
        return view
        whenever(mView.viewTreeObserver).thenReturn(viewTreeObserver)
        whenever(mView.isAttachedToWindow).thenReturn(true)
        whenever(mView.shouldAllowInteractions()).thenReturn(allowInteractions)
        return mView
    }

    private fun createAndInitController(view: PhoneStatusBarView): PhoneStatusBarViewController {
+107 −12
Original line number Diff line number Diff line
@@ -16,14 +16,19 @@

package com.android.systemui.statusbar.phone

import android.content.Context
import android.content.res.Configuration
import android.graphics.Insets
import android.graphics.Rect
import android.hardware.display.DisplayManagerGlobal
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.annotations.FlakyTest
import android.testing.TestableLooper.RunWithLooper
import android.view.Display
import android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS
import android.view.DisplayCutout
import android.view.DisplayInfo
import android.view.DisplayShape
import android.view.LayoutInflater
import android.view.MotionEvent
@@ -33,22 +38,27 @@ import android.view.View
import android.view.WindowInsets
import android.widget.FrameLayout
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_SHADE_WINDOW_GOES_AROUND
import com.android.systemui.Flags.FLAG_STATUS_BAR_SWIPE_OVER_CHIP
import com.android.systemui.Gefingerpoken
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestableContext
import com.android.systemui.res.R
import com.android.systemui.shade.StatusBarLongPressGestureDetector
import com.android.systemui.shared.Flags.FLAG_STATUS_BAR_CONNECTED_DISPLAYS
import com.android.systemui.statusbar.window.StatusBarWindowController
import com.android.systemui.statusbar.window.StatusBarWindowControllerStore
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.eq
import org.mockito.kotlin.whenever

@FlakyTest(bugId = 406551872)
@SmallTest
@@ -56,33 +66,118 @@ import org.mockito.Mockito.verify
class PhoneStatusBarViewTest : SysuiTestCase() {

    private lateinit var view: PhoneStatusBarView
    private lateinit var viewForSecondaryDisplay: PhoneStatusBarView
    private val systemIconsContainer: View
        get() = view.requireViewById(R.id.system_icons)

    private val windowController = mock<StatusBarWindowController>()
    private val windowControllerStore = mock<StatusBarWindowControllerStore>()
    @Mock private lateinit var windowController: StatusBarWindowController
    @Mock private lateinit var windowControllerStore: StatusBarWindowControllerStore
    @Mock private lateinit var longPressGestureDetector: StatusBarLongPressGestureDetector

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        whenever(windowControllerStore.defaultDisplay).thenReturn(windowController)
        mDependency.injectTestDependency(
            StatusBarWindowControllerStore::class.java,
            windowControllerStore,
        )
        context.ensureTestableResources()
        view = spy(createStatusBarView())
        view = spy(createStatusBarView(context))
        whenever(view.rootWindowInsets).thenReturn(emptyWindowInsets())

        val contextForSecondaryDisplay =
            SysuiTestableContext(
                mContext.createDisplayContext(
                    Display(
                        DisplayManagerGlobal.getInstance(),
                        2,
                        DisplayInfo(),
                        DEFAULT_DISPLAY_ADJUSTMENTS,
                    )
                )
            )
        viewForSecondaryDisplay = spy(createStatusBarView(contextForSecondaryDisplay))
    }

    @Test
    fun shouldAllowInteractions_primaryDisplay_returnsTrue() {
        assertThat(view.shouldAllowInteractions()).isTrue()
    }

    @Test
    @DisableFlags(FLAG_STATUS_BAR_CONNECTED_DISPLAYS)
    fun shouldAllowInteractions_secondaryDisplay_statusBarConnectedDisplaysDisabled_returnsTrue() {
        assertThat(viewForSecondaryDisplay.shouldAllowInteractions()).isTrue()
    }

    @Test
    fun onTouchEvent_listenerNotified() {
    @EnableFlags(FLAG_STATUS_BAR_CONNECTED_DISPLAYS, FLAG_SHADE_WINDOW_GOES_AROUND)
    fun shouldAllowInteractions_secondaryDisplay_statusBarConnectedDisplaysEnabled_shadeWindowGoesAroundEnabled_returnsTrue() {
        assertThat(viewForSecondaryDisplay.shouldAllowInteractions()).isTrue()
    }

    @Test
    @EnableFlags(FLAG_STATUS_BAR_CONNECTED_DISPLAYS)
    @DisableFlags(FLAG_SHADE_WINDOW_GOES_AROUND)
    fun shouldAllowInteractions_secondaryDisplay_statusBarConnectedDisplaysEnabled_shadeWindowGoesAroundDisabled_returnsFalse() {
        assertThat(viewForSecondaryDisplay.shouldAllowInteractions()).isFalse()
    }

    @Test
    fun onTouchEvent_listenersNotified() {
        val handler = TestTouchEventHandler()
        view.setTouchEventHandler(handler)
        view.setLongPressGestureDetector(longPressGestureDetector)

        val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
        view.onTouchEvent(event)

        assertThat(handler.lastEvent).isEqualTo(event)
        verify(longPressGestureDetector).handleTouch(eq(event))
    }

    @Test
    @DisableFlags(FLAG_STATUS_BAR_CONNECTED_DISPLAYS)
    fun onTouchEvent_touchOnSecondaryDisplay_statusBarConnectedDisplaysDisabled_listenersNotified() {
        val handler = TestTouchEventHandler()
        viewForSecondaryDisplay.setTouchEventHandler(handler)
        viewForSecondaryDisplay.setLongPressGestureDetector(longPressGestureDetector)

        val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
        viewForSecondaryDisplay.onTouchEvent(event)

        assertThat(handler.lastEvent).isEqualTo(event)
        verify(longPressGestureDetector).handleTouch(eq(event))
    }

    @Test
    @EnableFlags(FLAG_STATUS_BAR_CONNECTED_DISPLAYS, FLAG_SHADE_WINDOW_GOES_AROUND)
    fun onTouchEvent_touchOnSecondaryDisplay_statusBarConnectedDisplaysEnabled_shadeWindowGoesAroundEnabled_listenersNotified() {
        val handler = TestTouchEventHandler()
        viewForSecondaryDisplay.setTouchEventHandler(handler)
        viewForSecondaryDisplay.setLongPressGestureDetector(longPressGestureDetector)

        val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
        viewForSecondaryDisplay.onTouchEvent(event)

        assertThat(handler.lastEvent).isEqualTo(event)
        verify(longPressGestureDetector).handleTouch(eq(event))
    }

    @Test
    @EnableFlags(FLAG_STATUS_BAR_CONNECTED_DISPLAYS)
    @DisableFlags(FLAG_SHADE_WINDOW_GOES_AROUND)
    fun onTouchEvent_touchOnSecondaryDisplay_statusBarConnectedDisplaysEnabled_shadeWindowGoesAroundDisabled_listenersNotNotified() {
        val handler = TestTouchEventHandler()
        viewForSecondaryDisplay.setTouchEventHandler(handler)
        viewForSecondaryDisplay.setLongPressGestureDetector(longPressGestureDetector)

        val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
        viewForSecondaryDisplay.onTouchEvent(event)

        assertThat(handler.lastEvent).isNull()
        verify(longPressGestureDetector, never()).handleTouch(eq(event))
    }

    @Test
@@ -427,7 +522,7 @@ class PhoneStatusBarViewTest : SysuiTestCase() {
        }
    }

    private fun createStatusBarView() =
    private fun createStatusBarView(context: Context) =
        LayoutInflater.from(context)
            .inflate(
                R.layout.status_bar,