summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Fabian Kozynski <kozynski@google.com> 2024-02-23 13:23:39 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-02-23 13:23:39 +0000
commit7eb5e11082deef5de7da401afd4591bdcb06c8c4 (patch)
tree6e4c61d3021b5433574e988c887c420d673a8e39
parent0c4a251501a2b1db45eae904c4afcb56f5c9647e (diff)
parent0827a052a0dd038dc60273a0f03577d4c3a02b27 (diff)
Merge "Fix NPE in LockscreenShadeTransitionController" into main
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt17
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterKosmos.kt25
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerKosmos.kt2
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 }
)
}