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

Commit 76234fc2 authored by Nicolo' Mazzucato's avatar Nicolo' Mazzucato
Browse files

Do not translate shade views while unfolding when shade is on external display

Bug: 362719719
Bug: 413153761
Test: NotificationPanelUnfoldAnimationControllerTest
Flag: com.android.systemui.shade_window_goes_around
Change-Id: I9f2a27005f0c48e9d372356e128d9b9237aa808a
parent d97f841e
Loading
Loading
Loading
Loading
+48 −8
Original line number Original line Diff line number Diff line
@@ -16,21 +16,31 @@


package com.android.systemui.shade
package com.android.systemui.shade


import android.os.Looper
import android.platform.test.annotations.EnableFlags
import android.testing.TestableLooper.RunWithLooper
import android.view.Display
import android.view.View
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.filters.SmallTest
import com.android.systemui.res.R
import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestCase
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.res.R
import com.android.systemui.shade.data.repository.fakeShadeDisplaysRepository
import com.android.systemui.shade.domain.interactor.shadeDisplaysInteractor
import com.android.systemui.statusbar.StatusBarState.KEYGUARD
import com.android.systemui.statusbar.StatusBarState.KEYGUARD
import com.android.systemui.statusbar.StatusBarState.SHADE
import com.android.systemui.statusbar.StatusBarState.SHADE
import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED
import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED
import com.android.systemui.testKosmos
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Before
import org.junit.Test
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runner.RunWith
@@ -40,6 +50,7 @@ import org.mockito.Mock
import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.verify
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.whenever


/**
/**
 * Translates items away/towards the hinge when the device is opened/closed. This is controlled by
 * Translates items away/towards the hinge when the device is opened/closed. This is controlled by
@@ -47,8 +58,11 @@ import org.mockito.MockitoAnnotations
 */
 */
@SmallTest
@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWith(AndroidJUnit4::class)
@RunWithLooper
class NotificationPanelUnfoldAnimationControllerTest : SysuiTestCase() {
class NotificationPanelUnfoldAnimationControllerTest : SysuiTestCase() {


    private val kosmos = testKosmos().useUnconfinedTestDispatcher()

    @Mock private lateinit var progressProvider: NaturalRotationUnfoldProgressProvider
    @Mock private lateinit var progressProvider: NaturalRotationUnfoldProgressProvider


    @Captor private lateinit var progressListenerCaptor: ArgumentCaptor<TransitionProgressListener>
    @Captor private lateinit var progressListenerCaptor: ArgumentCaptor<TransitionProgressListener>
@@ -59,6 +73,10 @@ class NotificationPanelUnfoldAnimationControllerTest : SysuiTestCase() {


    @Mock private lateinit var statusBarStateController: StatusBarStateController
    @Mock private lateinit var statusBarStateController: StatusBarStateController


    private val shadeDisplaysInteractor = kosmos.shadeDisplaysInteractor
    private val shadeDisplaysRepository = kosmos.fakeShadeDisplaysRepository
    private val testScope = kosmos.testScope

    private lateinit var underTest: NotificationPanelUnfoldAnimationController
    private lateinit var underTest: NotificationPanelUnfoldAnimationController
    private lateinit var progressListeners: List<TransitionProgressListener>
    private lateinit var progressListeners: List<TransitionProgressListener>
    private var xTranslationMax = 0f
    private var xTranslationMax = 0f
@@ -66,7 +84,7 @@ class NotificationPanelUnfoldAnimationControllerTest : SysuiTestCase() {
    @Before
    @Before
    fun setup() {
    fun setup() {
        MockitoAnnotations.initMocks(this)
        MockitoAnnotations.initMocks(this)

        if (Looper.myLooper() == null) Looper.prepare()
        xTranslationMax =
        xTranslationMax =
            context.resources.getDimensionPixelSize(R.dimen.notification_side_paddings).toFloat()
            context.resources.getDimensionPixelSize(R.dimen.notification_side_paddings).toFloat()


@@ -74,11 +92,12 @@ class NotificationPanelUnfoldAnimationControllerTest : SysuiTestCase() {
            NotificationPanelUnfoldAnimationController(
            NotificationPanelUnfoldAnimationController(
                context,
                context,
                statusBarStateController,
                statusBarStateController,
                progressProvider
                progressProvider,
            )
                shadeDisplaysInteractor,
        whenever(parent.findViewById<ViewGroup>(R.id.split_shade_status_bar)).thenReturn(
                testScope.backgroundScope,
            splitShadeStatusBar
            )
            )
        whenever(parent.findViewById<ViewGroup>(R.id.split_shade_status_bar))
            .thenReturn(splitShadeStatusBar)
        underTest.setup(parent)
        underTest.setup(parent)


        verify(progressProvider, atLeastOnce()).addCallback(capture(progressListenerCaptor))
        verify(progressProvider, atLeastOnce()).addCallback(capture(progressListenerCaptor))
@@ -204,6 +223,28 @@ class NotificationPanelUnfoldAnimationControllerTest : SysuiTestCase() {
        assertThat(view.translationX).isZero()
        assertThat(view.translationX).isZero()
    }
    }


    @Test
    @EnableFlags(Flags.FLAG_SHADE_WINDOW_GOES_AROUND)
    fun whenShadeOnExternalDisplay_nothingMoves() =
        testScope.runTest {
            whenever(statusBarStateController.getState()).thenReturn(SHADE)
            shadeDisplaysRepository.setDisplayId(Display.DEFAULT_DISPLAY + 1) // not default anymore

            val view = View(context)
            whenever(parent.findViewById<View>(R.id.quick_settings_panel)).thenReturn(view)

            onTransitionStarted()
            assertThat(view.translationX).isZero()

            onTransitionProgress(0.5f)
            assertThat(view.translationX).isZero()

            shadeDisplaysRepository.setDisplayId(Display.DEFAULT_DISPLAY) // back to default!

            onTransitionProgress(0.5f)
            assertThat(view.translationX).isNonZero()
        }

    private fun onTransitionStarted() {
    private fun onTransitionStarted() {
        progressListeners.forEach { it.onTransitionStarted() }
        progressListeners.forEach { it.onTransitionStarted() }
    }
    }
@@ -215,5 +256,4 @@ class NotificationPanelUnfoldAnimationControllerTest : SysuiTestCase() {
    private fun onTransitionFinished() {
    private fun onTransitionFinished() {
        progressListeners.forEach { it.onTransitionFinished() }
        progressListeners.forEach { it.onTransitionFinished() }
    }
    }

}
}
+39 −1
Original line number Original line Diff line number Diff line
@@ -17,9 +17,14 @@
package com.android.systemui.shade
package com.android.systemui.shade


import android.content.Context
import android.content.Context
import android.view.Display
import android.view.ViewGroup
import android.view.ViewGroup
import com.android.app.tracing.coroutines.launchTraced
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.res.R
import com.android.systemui.res.R
import com.android.systemui.shade.domain.interactor.ShadeDisplaysInteractor
import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround
import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator
import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator
import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator.Direction.END
import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator.Direction.END
import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator.Direction.START
import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator.Direction.START
@@ -27,8 +32,11 @@ import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator.Vie
import com.android.systemui.statusbar.StatusBarState.SHADE
import com.android.systemui.statusbar.StatusBarState.SHADE
import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED
import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED
import com.android.systemui.unfold.SysUIUnfoldScope
import com.android.systemui.unfold.SysUIUnfoldScope
import com.android.systemui.unfold.UnfoldTransitionProgressProvider
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
import javax.inject.Inject
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope


@SysUIUnfoldScope
@SysUIUnfoldScope
class NotificationPanelUnfoldAnimationController
class NotificationPanelUnfoldAnimationController
@@ -36,9 +44,24 @@ class NotificationPanelUnfoldAnimationController
constructor(
constructor(
    @ShadeDisplayAware private val context: Context,
    @ShadeDisplayAware private val context: Context,
    statusBarStateController: StatusBarStateController,
    statusBarStateController: StatusBarStateController,
    progressProvider: NaturalRotationUnfoldProgressProvider,
    progressProviderFromConstructor: NaturalRotationUnfoldProgressProvider,
    private val shadeDisplaysInteractor: ShadeDisplaysInteractor,
    @Background private val backgroundScope: CoroutineScope,
) {
) {


    private val scopedProgressProvider: ScopedUnfoldTransitionProgressProvider by lazy {
        ScopedUnfoldTransitionProgressProvider(progressProviderFromConstructor).apply {
            setReadyToHandleTransition(true)
        }
    }

    private val progressProvider: UnfoldTransitionProgressProvider =
        if (ShadeWindowGoesAround.isEnabled) {
            scopedProgressProvider
        } else {
            progressProviderFromConstructor
        }

    private val filterShade: () -> Boolean = {
    private val filterShade: () -> Boolean = {
        statusBarStateController.getState() == SHADE ||
        statusBarStateController.getState() == SHADE ||
            statusBarStateController.getState() == SHADE_LOCKED
            statusBarStateController.getState() == SHADE_LOCKED
@@ -79,5 +102,20 @@ constructor(
        if (splitShadeStatusBarViewGroup != null) {
        if (splitShadeStatusBarViewGroup != null) {
            translateAnimatorStatusBar.init(splitShadeStatusBarViewGroup, translationMax)
            translateAnimatorStatusBar.init(splitShadeStatusBarViewGroup, translationMax)
        }
        }
        if (ShadeWindowGoesAround.isEnabled) {
            listenForShadeDisplayChanges()
        }
    }

    private fun listenForShadeDisplayChanges() {
        ShadeWindowGoesAround.isUnexpectedlyInLegacyMode()
        backgroundScope.launchTraced("NotificationPanelUnfoldAnimationController") {
            scopedProgressProvider.setReadyToHandleTransition(
                shadeDisplaysInteractor.displayId.value == Display.DEFAULT_DISPLAY
            )
            shadeDisplaysInteractor.displayId.collect {
                scopedProgressProvider.setReadyToHandleTransition(it == Display.DEFAULT_DISPLAY)
            }
        }
    }
    }
}
}