diff options
| author | 2024-02-23 13:23:39 +0000 | |
|---|---|---|
| committer | 2024-02-23 13:23:39 +0000 | |
| commit | 7eb5e11082deef5de7da401afd4591bdcb06c8c4 (patch) | |
| tree | 6e4c61d3021b5433574e988c887c420d673a8e39 | |
| parent | 0c4a251501a2b1db45eae904c4afcb56f5c9647e (diff) | |
| parent | 0827a052a0dd038dc60273a0f03577d4c3a02b27 (diff) | |
Merge "Fix NPE in LockscreenShadeTransitionController" into main
10 files changed, 99 insertions, 20 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt index 72a5c468ea94..c1b20374dbac 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt @@ -84,6 +84,10 @@ interface QSSceneAdapter { */ val qsHeight: Int + /** Compatibility for use by LockscreenShadeTransitionController. Matches default from [QS] */ + val isQsFullyCollapsed: Boolean + get() = true + sealed interface State { val isVisible: Boolean @@ -165,6 +169,10 @@ constructor( override val qsHeight: Int get() = qsImpl.value?.qsHeight ?: 0 + // If value is null, there's no QS and therefore it's fully collapsed. + override val isQsFullyCollapsed: Boolean + get() = qsImpl.value?.isFullyCollapsed ?: true + // Same config changes as in FragmentHostManager private val interestingChanges = InterestingConfigChanges( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt index 4d0552e7cb31..adca3f2d25d6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt @@ -21,9 +21,9 @@ import android.util.IndentingPrintWriter import android.util.MathUtils import androidx.annotation.FloatRange import androidx.annotation.Px -import com.android.systemui.res.R import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.qs.QS +import com.android.systemui.res.R import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.SplitShadeStateController import dagger.assisted.Assisted @@ -38,7 +38,7 @@ constructor( context: Context, configurationController: ConfigurationController, dumpManager: DumpManager, - @Assisted private val qsProvider: () -> QS, + @Assisted private val qsProvider: () -> QS?, splitShadeStateController: SplitShadeStateController ) : AbstractLockscreenShadeTransitionController( @@ -48,7 +48,7 @@ constructor( splitShadeStateController ) { - private val qs: QS + private val qs: QS? get() = qsProvider() /** @@ -135,7 +135,7 @@ constructor( /* amount= */ MathUtils.saturate(qsDragDownAmount / qsSquishTransitionDistance) ) isTransitioningToFullShade = dragDownAmount > 0.0f - qs.setTransitionToFullShadeProgress( + qs?.setTransitionToFullShadeProgress( isTransitioningToFullShade, qsTransitionFraction, qsSquishTransitionFraction @@ -163,6 +163,6 @@ constructor( @AssistedFactory fun interface Factory { - fun create(qsProvider: () -> QS): LockscreenShadeQsTransitionController + fun create(qsProvider: () -> QS?): LockscreenShadeQsTransitionController } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt index a59d753971f6..4ee83497b368 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt @@ -31,6 +31,7 @@ import com.android.systemui.plugins.ActivityStarter.OnDismissAction import com.android.systemui.plugins.FalsingManager import com.android.systemui.plugins.qs.QS import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.qs.ui.adapter.QSSceneAdapter import com.android.systemui.res.R import com.android.systemui.shade.ShadeLockscreenInteractor import com.android.systemui.shade.data.repository.ShadeRepository @@ -84,6 +85,7 @@ constructor( private val splitShadeStateController: SplitShadeStateController, private val shadeLockscreenInteractorLazy: Lazy<ShadeLockscreenInteractor>, naturalScrollingSettingObserver: NaturalScrollingSettingObserver, + private val lazyQSSceneAdapter: Lazy<QSSceneAdapter>, ) : Dumpable { private var pulseHeight: Float = 0f @@ -93,7 +95,11 @@ constructor( private var useSplitShade: Boolean = false private lateinit var nsslController: NotificationStackScrollLayoutController lateinit var centralSurfaces: CentralSurfaces - lateinit var qS: QS + + // When in scene container mode, this will be null. In that case, we use the adapter if needed + var qS: QS? = null + private val isQsFullyCollapsed: Boolean + get() = qS?.isFullyCollapsed ?: lazyQSSceneAdapter.get().isQsFullyCollapsed /** A handler that handles the next keyguard dismiss animation. */ private var animationHandlerOnKeyguardDismiss: ((Long) -> Unit)? = null @@ -286,7 +292,8 @@ constructor( /** @return true if the interaction is accepted, false if it should be cancelled */ internal fun canDragDown(): Boolean { return (statusBarStateController.state == StatusBarState.KEYGUARD || - nsslController.isInLockedDownShade()) && (qS.isFullyCollapsed || useSplitShade) + nsslController.isInLockedDownShade()) && + (isQsFullyCollapsed || useSplitShade) } /** Called by the touch helper when when a gesture has completed all the way and released. */ @@ -410,7 +417,7 @@ constructor( get() = (statusBarStateController.getState() == StatusBarState.KEYGUARD && !keyguardBypassController.bypassEnabled && - (qS.isFullyCollapsed || useSplitShade)) + (isQsFullyCollapsed || useSplitShade)) /** The amount in pixels that the user has dragged down. */ internal var dragDownAmount = 0f diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt b/packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt index e47c914341a6..612a365dbe8b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt @@ -27,7 +27,7 @@ constructor( private val context: Context, private val scrimController: ScrimController, private val statusBarStateController: SysuiStatusBarStateController, - @Assisted private val qSProvider: () -> QS, + @Assisted private val qSProvider: () -> QS?, @Assisted private val nsslControllerProvider: () -> NotificationStackScrollLayoutController ) : LockScreenShadeOverScroller { @@ -37,7 +37,7 @@ constructor( private var maxOverScrollAmount = 0 private var previousOverscrollAmount = 0 - private val qS: QS + private val qS: QS? get() = qSProvider() private val nsslController: NotificationStackScrollLayoutController @@ -90,7 +90,7 @@ constructor( } private fun applyOverscroll(overscrollAmount: Int) { - qS.setOverScrollAmount(overscrollAmount) + qS?.setOverScrollAmount(overscrollAmount) scrimController.setNotificationsOverScrollAmount(overscrollAmount) nsslController.setOverScrollAmount(overscrollAmount) } @@ -109,7 +109,7 @@ constructor( val animator = ValueAnimator.ofInt(previousOverscrollAmount, 0) animator.addUpdateListener { val overScrollAmount = it.animatedValue as Int - qS.setOverScrollAmount(overScrollAmount) + qS?.setOverScrollAmount(overScrollAmount) scrimController.setNotificationsOverScrollAmount(overScrollAmount) nsslController.setOverScrollAmount(overScrollAmount) } @@ -143,7 +143,7 @@ constructor( @AssistedFactory fun interface Factory { fun create( - qSProvider: () -> QS, + qSProvider: () -> QS?, nsslControllerProvider: () -> NotificationStackScrollLayoutController ): SplitShadeLockScreenOverScroller } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt index 0b4de345e2d7..402d9aab66bd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt @@ -18,12 +18,13 @@ package com.android.systemui.statusbar import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest -import com.android.systemui.res.R import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.qs.QS +import com.android.systemui.res.R import com.android.systemui.statusbar.policy.FakeConfigurationController import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController +import com.android.systemui.util.mockito.mock import com.google.common.truth.Expect import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -43,13 +44,15 @@ class LockscreenShadeQsTransitionControllerTest : SysuiTestCase() { @get:Rule val expect: Expect = Expect.create() @Mock private lateinit var dumpManager: DumpManager - @Mock private lateinit var qS: QS + private var qS: QS? = null private lateinit var controller: LockscreenShadeQsTransitionController @Before fun setUp() { MockitoAnnotations.initMocks(this) + qS = mock() + setTransitionDistance(TRANSITION_DISTANCE) setTransitionDelay(TRANSITION_DELAY) setSquishTransitionDistance(SQUISH_TRANSITION_DISTANCE) @@ -220,7 +223,7 @@ class LockscreenShadeQsTransitionControllerTest : SysuiTestCase() { controller.dragDownAmount = rawDragAmount - verify(qS) + verify(qS!!) .setTransitionToFullShadeProgress( /* isTransitioningToFullShade= */ true, /* transitionFraction= */ controller.qsTransitionFraction, @@ -228,6 +231,15 @@ class LockscreenShadeQsTransitionControllerTest : SysuiTestCase() { ) } + @Test + fun nullQS_onDragAmountChanged_doesNotCrash() { + qS = null + + val rawDragAmount = 200f + + controller.dragDownAmount = rawDragAmount + } + private fun setTransitionDistance(value: Int) { overrideResource(R.dimen.lockscreen_shade_qs_transition_distance, value) configurationController.notifyConfigurationChanged() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt index 91701b17b5e6..86116a073d9e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt @@ -18,6 +18,7 @@ import com.android.systemui.keyguard.domain.interactor.NaturalScrollingSettingOb import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager import com.android.systemui.plugins.qs.QS import com.android.systemui.power.domain.interactor.PowerInteractor +import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter import com.android.systemui.res.R import com.android.systemui.shade.ShadeLockscreenInteractor import com.android.systemui.shade.data.repository.FakeShadeRepository @@ -82,6 +83,8 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { private val testScope get() = testComponent.testScope + private val qsSceneAdapter = FakeQSSceneAdapter({ mock() }) + lateinit var row: ExpandableNotificationRow @Mock lateinit var centralSurfaces: CentralSurfaces @@ -189,6 +192,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { splitShadeStateController = ResourcesSplitShadeStateController(), shadeLockscreenInteractorLazy = {shadeLockscreenInteractor}, naturalScrollingSettingObserver = naturalScrollingSettingObserver, + lazyQSSceneAdapter = { qsSceneAdapter } ) transitionController.addCallback(transitionControllerCallback) @@ -567,6 +571,16 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { verify(shadeLockscreenInteractor).setKeyguardStatusBarAlpha(-1f) } + @Test + fun nullQs_canDragDownFromAdapter() { + transitionController.qS = null + + qsSceneAdapter.isQsFullyCollapsed = true + assertTrue("Can't drag down on keyguard", transitionController.canDragDown()) + qsSceneAdapter.isQsFullyCollapsed = false + assertFalse("Can drag down when QS is expanded", transitionController.canDragDown()) + } + private fun enableSplitShade() { setSplitShadeEnabled(true) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt index 81d5c4d52b74..700fb1ec332c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt @@ -9,6 +9,7 @@ import com.android.systemui.plugins.qs.QS import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController import com.android.systemui.statusbar.phone.ScrimController import com.android.systemui.statusbar.policy.FakeConfigurationController +import com.android.systemui.util.mockito.mock import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -31,7 +32,7 @@ class SplitShadeLockScreenOverScrollerTest : SysuiTestCase() { @Mock private lateinit var scrimController: ScrimController @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController - @Mock private lateinit var qS: QS + private var qS: QS? = null @Mock private lateinit var nsslController: NotificationStackScrollLayoutController @Mock private lateinit var dumpManager: DumpManager @@ -40,6 +41,7 @@ class SplitShadeLockScreenOverScrollerTest : SysuiTestCase() { @Before fun setUp() { MockitoAnnotations.initMocks(this) + qS = mock() whenever(nsslController.height).thenReturn(1800) @@ -92,7 +94,7 @@ class SplitShadeLockScreenOverScrollerTest : SysuiTestCase() { setDragAmount(1000f) whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE) setDragAmount(999f) - reset(qS, scrimController, nsslController) + reset(qS!!, scrimController, nsslController) setDragAmount(998f) setDragAmount(997f) @@ -100,8 +102,15 @@ class SplitShadeLockScreenOverScrollerTest : SysuiTestCase() { verifyNoMoreOverScrollChanges() } + @Test + fun qsNull_applyOverscroll_doesNotCrash() { + qS = null + + setDragAmount(100f) + } + private fun verifyOverScrollPerformed() { - verify(qS).setOverScrollAmount(intThat { it > 0 }) + verify(qS!!).setOverScrollAmount(intThat { it > 0 }) verify(scrimController).setNotificationsOverScrollAmount(intThat { it > 0 }) verify(nsslController).setOverScrollAmount(intThat { it > 0 }) } @@ -109,7 +118,7 @@ class SplitShadeLockScreenOverScrollerTest : SysuiTestCase() { private fun verifyOverScrollResetToZero() { // Might be more than once as the animator might have multiple values close to zero that // round down to zero. - verify(qS, atLeast(1)).setOverScrollAmount(0) + verify(qS!!, atLeast(1)).setOverScrollAmount(0) verify(scrimController, atLeast(1)).setNotificationsOverScrollAmount(0) verify(nsslController, atLeast(1)).setOverScrollAmount(0) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt index b1581d1771fd..4d902fa35204 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt @@ -41,6 +41,8 @@ class FakeQSSceneAdapter( private val _navBarPadding = MutableStateFlow<Int>(0) val navBarPadding = _navBarPadding.asStateFlow() + override var isQsFullyCollapsed: Boolean = true + override suspend fun inflate(context: Context) { _view.value = inflateDelegate(context) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterKosmos.kt new file mode 100644 index 000000000000..00ab0b57fab7 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterKosmos.kt @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2024 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.systemui.qs.ui.adapter + +import android.view.View +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +var Kosmos.fakeQSSceneAdapter by Kosmos.Fixture { FakeQSSceneAdapter({ mock<View>() }) } + +val Kosmos.qsSceneAdapter: QSSceneAdapter by Kosmos.Fixture { fakeQSSceneAdapter } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerKosmos.kt index e5072f1c9f1c..e4a3896378f6 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerKosmos.kt @@ -26,6 +26,7 @@ import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.media.controls.ui.controller.mediaHierarchyManager import com.android.systemui.plugins.activityStarter +import com.android.systemui.qs.ui.adapter.qsSceneAdapter import com.android.systemui.shade.data.repository.shadeRepository import com.android.systemui.shade.domain.interactor.shadeInteractor import com.android.systemui.shade.domain.interactor.shadeLockscreenInteractor @@ -61,5 +62,6 @@ val Kosmos.lockscreenShadeTransitionController by Fixture { splitShadeStateController = splitShadeStateController, shadeLockscreenInteractorLazy = { shadeLockscreenInteractor }, naturalScrollingSettingObserver = naturalScrollingSettingObserver, + lazyQSSceneAdapter = { qsSceneAdapter } ) } |