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

Commit 00b19cde authored by Fabian Kozynski's avatar Fabian Kozynski Committed by Android (Google) Code Review
Browse files

Merge "Debounce the inset application" into tm-dev

parents ca5c0898 43d826f7
Loading
Loading
Loading
Loading
+32 −7
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.view.WindowInsets
import androidx.annotation.VisibleForTesting
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
import androidx.constraintlayout.widget.ConstraintSet.END
@@ -11,6 +12,7 @@ import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
import androidx.constraintlayout.widget.ConstraintSet.START
import androidx.constraintlayout.widget.ConstraintSet.TOP
import com.android.systemui.R
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.navigationbar.NavigationModeController
@@ -21,14 +23,19 @@ import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener
import com.android.systemui.shared.system.QuickStepContract
import com.android.systemui.util.Utils
import com.android.systemui.util.ViewController
import com.android.systemui.util.concurrency.DelayableExecutor
import java.util.function.Consumer
import javax.inject.Inject

@VisibleForTesting
internal const val INSET_DEBOUNCE_MILLIS = 500L

class NotificationsQSContainerController @Inject constructor(
    view: NotificationsQuickSettingsContainer,
    private val navigationModeController: NavigationModeController,
    private val overviewProxyService: OverviewProxyService,
    private val featureFlags: FeatureFlags
    private val featureFlags: FeatureFlags,
    @Main private val delayableExecutor: DelayableExecutor
) : ViewController<NotificationsQuickSettingsContainer>(view), QSContainerController {

    var qsExpanded = false
@@ -60,12 +67,30 @@ class NotificationsQSContainerController @Inject constructor(
            taskbarVisible = visible
        }
    }
    private val windowInsetsListener: Consumer<WindowInsets> = Consumer { insets ->

    // With certain configuration changes (like light/dark changes), the nav bar will disappear
    // for a bit, causing `bottomStableInsets` to be unstable for some time. Debounce the value
    // for 500ms.
    // All interactions with this object happen in the main thread.
    private val delayedInsetSetter = object : Runnable, Consumer<WindowInsets> {
        private var canceller: Runnable? = null
        private var stableInsets = 0
        private var cutoutInsets = 0

        override fun accept(insets: WindowInsets) {
            // when taskbar is visible, stableInsetBottom will include its height
        bottomStableInsets = insets.stableInsetBottom
        bottomCutoutInsets = insets.displayCutout?.safeInsetBottom ?: 0
            stableInsets = insets.stableInsetBottom
            cutoutInsets = insets.displayCutout?.safeInsetBottom ?: 0
            canceller?.run()
            canceller = delayableExecutor.executeDelayed(this, INSET_DEBOUNCE_MILLIS)
        }

        override fun run() {
            bottomStableInsets = stableInsets
            bottomCutoutInsets = cutoutInsets
            updateBottomSpacing()
        }
    }

    override fun onInit() {
        val currentMode: Int = navigationModeController.addListener { mode: Int ->
@@ -77,7 +102,7 @@ class NotificationsQSContainerController @Inject constructor(
    public override fun onViewAttached() {
        updateResources()
        overviewProxyService.addCallback(taskbarVisibilityListener)
        mView.setInsetsChangedListener(windowInsetsListener)
        mView.setInsetsChangedListener(delayedInsetSetter)
        mView.setQSFragmentAttachedListener { qs: QS -> qs.setContainerController(this) }
        mView.setConfigurationChangedListener { updateResources() }
    }
+35 −3
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ import com.android.systemui.navigationbar.NavigationModeController
import com.android.systemui.navigationbar.NavigationModeController.ModeChangedListener
import com.android.systemui.recents.OverviewProxyService
import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
@@ -31,6 +33,7 @@ import org.mockito.Mockito.anyInt
import org.mockito.Mockito.doNothing
import org.mockito.Mockito.eq
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import java.util.function.Consumer
@@ -71,6 +74,8 @@ class NotificationQSContainerControllerTest : SysuiTestCase() {
    private lateinit var navigationModeCallback: ModeChangedListener
    private lateinit var taskbarVisibilityCallback: OverviewProxyListener
    private lateinit var windowInsetsCallback: Consumer<WindowInsets>
    private lateinit var delayableExecutor: FakeExecutor
    private lateinit var fakeSystemClock: FakeSystemClock

    @Before
    fun setup() {
@@ -78,11 +83,14 @@ class NotificationQSContainerControllerTest : SysuiTestCase() {
        mContext.ensureTestableResources()
        whenever(notificationsQSContainer.context).thenReturn(mContext)
        whenever(notificationsQSContainer.resources).thenReturn(mContext.resources)
        fakeSystemClock = FakeSystemClock()
        delayableExecutor = FakeExecutor(fakeSystemClock)
        controller = NotificationsQSContainerController(
                notificationsQSContainer,
                navigationModeController,
                overviewProxyService,
                featureFlags
                featureFlags,
                delayableExecutor
        )

        overrideResource(R.dimen.split_shade_notifications_scrim_margin_bottom, SCRIM_MARGIN)
@@ -490,13 +498,32 @@ class NotificationQSContainerControllerTest : SysuiTestCase() {
        container.addView(newViewWithId(1))
        container.addView(newViewWithId(View.NO_ID))
        val controller = NotificationsQSContainerController(container, navigationModeController,
                overviewProxyService, featureFlags)
                overviewProxyService, featureFlags, delayableExecutor)
        controller.updateResources()

        assertThat(container.getChildAt(0).id).isEqualTo(1)
        assertThat(container.getChildAt(1).id).isNotEqualTo(View.NO_ID)
    }

    @Test
    fun testWindowInsetDebounce() {
        disableSplitShade()
        useNewFooter(true)

        given(taskbarVisible = false,
            navigationMode = GESTURES_NAVIGATION,
            insets = emptyInsets(),
            applyImmediately = false)
        fakeSystemClock.advanceTime(INSET_DEBOUNCE_MILLIS / 2)
        windowInsetsCallback.accept(windowInsets().withStableBottom())

        delayableExecutor.advanceClockToLast()
        delayableExecutor.runAllReady()

        verify(notificationsQSContainer, never()).setQSContainerPaddingBottom(0)
        verify(notificationsQSContainer).setQSContainerPaddingBottom(STABLE_INSET_BOTTOM)
    }

    private fun disableSplitShade() {
        setSplitShadeEnabled(false)
    }
@@ -513,12 +540,17 @@ class NotificationQSContainerControllerTest : SysuiTestCase() {
    private fun given(
        taskbarVisible: Boolean,
        navigationMode: Int,
        insets: WindowInsets
        insets: WindowInsets,
        applyImmediately: Boolean = true
    ) {
        Mockito.clearInvocations(notificationsQSContainer)
        taskbarVisibilityCallback.onTaskbarStatusUpdated(taskbarVisible, false)
        navigationModeCallback.onNavigationModeChanged(navigationMode)
        windowInsetsCallback.accept(insets)
        if (applyImmediately) {
            delayableExecutor.advanceClockToLast()
            delayableExecutor.runAllReady()
        }
    }

    fun then(