Merge "Forward CommunalContainer touches when hub mode closed" into main
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
index 2c4dc80..185a06c 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
@@ -7,6 +7,7 @@
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
@@ -19,8 +20,10 @@
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
+import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.pointer.pointerInteropFilter
import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.Edge
import com.android.compose.animation.scene.ElementKey
@@ -28,6 +31,7 @@
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.SceneScope
import com.android.compose.animation.scene.SceneTransitionLayout
+import com.android.compose.animation.scene.SceneTransitionLayoutState
import com.android.compose.animation.scene.Swipe
import com.android.compose.animation.scene.SwipeDirection
import com.android.compose.animation.scene.transitions
@@ -56,6 +60,7 @@
* This is a temporary container to allow the communal UI to use [SceneTransitionLayout] for gesture
* handling and transitions before the full Flexiglass layout is ready.
*/
+@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun CommunalContainer(
modifier: Modifier = Modifier,
@@ -65,6 +70,7 @@
viewModel.currentScene
.transform<CommunalSceneKey, SceneKey> { value -> value.toTransitionSceneKey() }
.collectAsState(TransitionSceneKey.Blank)
+ val sceneTransitionLayoutState = remember { SceneTransitionLayoutState(currentScene) }
// Don't show hub mode UI if keyguard is present. This is important since we're in the shade,
// which can be opened from many locations.
val isKeyguardShowing by viewModel.isKeyguardVisible.collectAsState(initial = false)
@@ -75,32 +81,59 @@
return
}
- SceneTransitionLayout(
- modifier = modifier.fillMaxSize(),
- currentScene = currentScene,
- onChangeScene = { sceneKey -> viewModel.onSceneChanged(sceneKey.toCommunalSceneKey()) },
- transitions = sceneTransitions,
- edgeDetector = FixedSizeEdgeDetector(ContainerDimensions.EdgeSwipeSize)
- ) {
- scene(
- TransitionSceneKey.Blank,
- userActions =
- mapOf(
- Swipe(SwipeDirection.Left, fromEdge = Edge.Right) to TransitionSceneKey.Communal
- )
+ Box(modifier = modifier.fillMaxSize()) {
+ SceneTransitionLayout(
+ modifier = Modifier.fillMaxSize(),
+ currentScene = currentScene,
+ onChangeScene = { sceneKey -> viewModel.onSceneChanged(sceneKey.toCommunalSceneKey()) },
+ transitions = sceneTransitions,
+ state = sceneTransitionLayoutState,
+ edgeDetector = FixedSizeEdgeDetector(ContainerDimensions.EdgeSwipeSize)
) {
- BlankScene { showSceneTransitionLayout = false }
+ scene(
+ TransitionSceneKey.Blank,
+ userActions =
+ mapOf(
+ Swipe(SwipeDirection.Left, fromEdge = Edge.Right) to
+ TransitionSceneKey.Communal
+ )
+ ) {
+ BlankScene { showSceneTransitionLayout = false }
+ }
+
+ scene(
+ TransitionSceneKey.Communal,
+ userActions =
+ mapOf(
+ Swipe(SwipeDirection.Right, fromEdge = Edge.Left) to
+ TransitionSceneKey.Blank
+ ),
+ ) {
+ CommunalScene(viewModel, modifier = modifier)
+ }
}
- scene(
- TransitionSceneKey.Communal,
- userActions =
- mapOf(
- Swipe(SwipeDirection.Right, fromEdge = Edge.Left) to TransitionSceneKey.Blank
- ),
- ) {
- CommunalScene(viewModel, modifier = modifier)
- }
+ // TODO(b/308813166): remove once CommunalContainer is moved lower in z-order and doesn't
+ // block touches anymore.
+ Box(
+ modifier =
+ Modifier.fillMaxSize()
+ // Offsetting to the left so that edge swipe to open the hub still works. This
+ // does mean that the very right edge of the hub won't refresh the screen
+ // timeout, but should be good enough for a temporary solution.
+ .offset(x = -ContainerDimensions.EdgeSwipeSize)
+ .pointerInteropFilter {
+ viewModel.onUserActivity()
+ if (
+ sceneTransitionLayoutState.transitionState.currentScene ==
+ TransitionSceneKey.Blank
+ ) {
+ viewModel.onOuterTouch(it)
+ return@pointerInteropFilter true
+ }
+ false
+ }
+ )
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt
index ce7db80..ea3006f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.communal.view.viewmodel
import android.app.smartspace.SmartspaceTarget
+import android.os.PowerManager
import android.provider.Settings
import android.widget.RemoteViews
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -33,6 +34,7 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.media.controls.ui.MediaHost
+import com.android.systemui.shade.ShadeViewController
import com.android.systemui.smartspace.data.repository.FakeSmartspaceRepository
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
@@ -50,6 +52,8 @@
@RunWith(AndroidJUnit4::class)
class CommunalEditModeViewModelTest : SysuiTestCase() {
@Mock private lateinit var mediaHost: MediaHost
+ @Mock private lateinit var shadeViewController: ShadeViewController
+ @Mock private lateinit var powerManager: PowerManager
private lateinit var testScope: TestScope
@@ -79,6 +83,8 @@
underTest =
CommunalEditModeViewModel(
withDeps.communalInteractor,
+ shadeViewController,
+ powerManager,
mediaHost,
)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
index 32f4d07..9bd0835 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.communal.view.viewmodel
import android.app.smartspace.SmartspaceTarget
+import android.os.PowerManager
import android.provider.Settings
import android.widget.RemoteViews
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -33,6 +34,7 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.media.controls.ui.MediaHost
+import com.android.systemui.shade.ShadeViewController
import com.android.systemui.smartspace.data.repository.FakeSmartspaceRepository
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
@@ -50,6 +52,8 @@
@RunWith(AndroidJUnit4::class)
class CommunalViewModelTest : SysuiTestCase() {
@Mock private lateinit var mediaHost: MediaHost
+ @Mock private lateinit var shadeViewController: ShadeViewController
+ @Mock private lateinit var powerManager: PowerManager
private lateinit var testScope: TestScope
@@ -80,6 +84,8 @@
CommunalViewModel(
withDeps.communalInteractor,
withDeps.tutorialInteractor,
+ shadeViewController,
+ powerManager,
mediaHost,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalHubSection.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalHubSection.kt
index ad02f62..4219d6d6 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalHubSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalHubSection.kt
@@ -2,63 +2,16 @@
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
-import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
-import com.android.systemui.compose.ComposeFacade
import com.android.systemui.keyguard.shared.model.KeyguardSection
-import com.android.systemui.keyguard.ui.view.layout.sections.removeView
-import com.android.systemui.res.R
import javax.inject.Inject
/** A keyguard section that hosts the communal hub. */
-class DefaultCommunalHubSection
-@Inject
-constructor(
- private val viewModel: CommunalViewModel,
-) : KeyguardSection() {
- private val communalHubViewId = R.id.communal_hub
-
- override fun addViews(constraintLayout: ConstraintLayout) {
- constraintLayout.addView(
- ComposeFacade.createCommunalView(
- context = constraintLayout.context,
- viewModel = viewModel,
- )
- .apply { id = communalHubViewId },
- )
- }
+class DefaultCommunalHubSection @Inject constructor() : KeyguardSection() {
+ override fun addViews(constraintLayout: ConstraintLayout) {}
override fun bindData(constraintLayout: ConstraintLayout) {}
- override fun applyConstraints(constraintSet: ConstraintSet) {
- constraintSet.apply {
- connect(
- communalHubViewId,
- ConstraintSet.START,
- ConstraintSet.PARENT_ID,
- ConstraintSet.START,
- )
- connect(
- communalHubViewId,
- ConstraintSet.TOP,
- ConstraintSet.PARENT_ID,
- ConstraintSet.TOP,
- )
- connect(
- communalHubViewId,
- ConstraintSet.END,
- ConstraintSet.PARENT_ID,
- ConstraintSet.END,
- )
- connect(
- communalHubViewId,
- ConstraintSet.BOTTOM,
- ConstraintSet.PARENT_ID,
- ConstraintSet.BOTTOM,
- )
- }
- }
+ override fun applyConstraints(constraintSet: ConstraintSet) {}
- override fun removeViews(constraintLayout: ConstraintLayout) {
- constraintLayout.removeView(communalHubViewId)
- }
+ override fun removeViews(constraintLayout: ConstraintLayout) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
index 4d8e893..bed4283 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
@@ -16,16 +16,22 @@
package com.android.systemui.communal.ui.viewmodel
+import android.os.PowerManager
+import android.os.SystemClock
+import android.view.MotionEvent
import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.communal.domain.model.CommunalContentModel
import com.android.systemui.communal.shared.model.CommunalSceneKey
import com.android.systemui.media.controls.ui.MediaHost
+import com.android.systemui.shade.ShadeViewController
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
/** The base view model for the communal hub. */
abstract class BaseCommunalViewModel(
private val communalInteractor: CommunalInteractor,
+ private val shadeViewController: ShadeViewController,
+ private val powerManager: PowerManager,
val mediaHost: MediaHost,
) {
val isKeyguardVisible: Flow<Boolean> = communalInteractor.isKeyguardVisible
@@ -36,6 +42,26 @@
communalInteractor.onSceneChanged(scene)
}
+ // TODO(b/308813166): remove once CommunalContainer is moved lower in z-order and doesn't block
+ // touches anymore.
+ /** Called when a touch is received outside the edge swipe area when hub mode is closed. */
+ fun onOuterTouch(motionEvent: MotionEvent) {
+ // Forward the touch to the shade so that basic gestures like swipe up/down for
+ // shade/bouncer work.
+ shadeViewController.handleExternalTouch(motionEvent)
+ }
+
+ // TODO(b/308813166): remove once CommunalContainer is moved lower in z-order and doesn't block
+ // touches anymore.
+ /** Called to refresh the screen timeout when a user touch is received. */
+ fun onUserActivity() {
+ powerManager.userActivity(
+ SystemClock.uptimeMillis(),
+ PowerManager.USER_ACTIVITY_EVENT_TOUCH,
+ 0
+ )
+ }
+
/** A list of all the communal content to be displayed in the communal hub. */
abstract val communalContent: Flow<List<CommunalContentModel>>
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt
index 111f8b4..b6843c5 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt
@@ -16,11 +16,13 @@
package com.android.systemui.communal.ui.viewmodel
+import android.os.PowerManager
import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.communal.domain.model.CommunalContentModel
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.media.controls.ui.MediaHost
import com.android.systemui.media.dagger.MediaModule
+import com.android.systemui.shade.ShadeViewController
import javax.inject.Inject
import javax.inject.Named
import kotlinx.coroutines.flow.Flow
@@ -31,8 +33,10 @@
@Inject
constructor(
private val communalInteractor: CommunalInteractor,
+ shadeViewController: ShadeViewController,
+ powerManager: PowerManager,
@Named(MediaModule.COMMUNAL_HUB) mediaHost: MediaHost,
-) : BaseCommunalViewModel(communalInteractor, mediaHost) {
+) : BaseCommunalViewModel(communalInteractor, shadeViewController, powerManager, mediaHost) {
override val isEditMode = true
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
index 11bde6b..d7dcdb9 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
@@ -16,12 +16,14 @@
package com.android.systemui.communal.ui.viewmodel
+import android.os.PowerManager
import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.communal.domain.interactor.CommunalTutorialInteractor
import com.android.systemui.communal.domain.model.CommunalContentModel
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.media.controls.ui.MediaHost
import com.android.systemui.media.dagger.MediaModule
+import com.android.systemui.shade.ShadeViewController
import javax.inject.Inject
import javax.inject.Named
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -37,8 +39,10 @@
constructor(
private val communalInteractor: CommunalInteractor,
tutorialInteractor: CommunalTutorialInteractor,
+ shadeViewController: ShadeViewController,
+ powerManager: PowerManager,
@Named(MediaModule.COMMUNAL_HUB) mediaHost: MediaHost,
-) : BaseCommunalViewModel(communalInteractor, mediaHost) {
+) : BaseCommunalViewModel(communalInteractor, shadeViewController, powerManager, mediaHost) {
@OptIn(ExperimentalCoroutinesApi::class)
override val communalContent: Flow<List<CommunalContentModel>> =
tutorialInteractor.isTutorialAvailable.flatMapLatest { isTutorialMode ->