summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Matt Pietal <mpietal@google.com> 2023-12-26 13:33:27 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2023-12-26 13:33:27 +0000
commit91487ebd89d54aae12d0485ed321c1a4ce6f38a6 (patch)
treed02a1f60a9167ab2c7af1e6da91447d4cec4e658
parent13961f6fe5a190e712f5d7da6208685febc374e6 (diff)
parent1bc217c6e86d1a92a91615d49f964d2591f517df (diff)
Merge changes I771230c1,I460dfc11 into main
* changes: Support media on splitshade with constraints Fix NSSL flicker when going to/from OCCLUDED
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml2
-rw-r--r--packages/SystemUI/res/values/ids.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeMediaSection.kt111
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt65
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt19
8 files changed, 192 insertions, 28 deletions
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
index 557fbf21d5c4..e6122a094707 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
@@ -43,7 +43,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
- android:id="@+id/status_view_media_container"
+ android:id="@id/status_view_media_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/qs_media_padding"
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index d511caba941b..80725c2bd4b5 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -225,6 +225,8 @@
<item type="id" name="communal_tutorial_indicator" />
<item type="id" name="nssl_placeholder_barrier_bottom" />
<item type="id" name="ambient_indication_container" />
+ <item type="id" name="status_view_media_container" />
+ <item type="id" name="smart_space_barrier_bottom" />
<!-- Privacy dialog -->
<item type="id" name="privacy_dialog_close_app_button" />
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt
index 16539db648bc..5344696b92fe 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt
@@ -33,6 +33,7 @@ import com.android.systemui.keyguard.ui.view.layout.sections.KeyguardSectionsMod
import com.android.systemui.keyguard.ui.view.layout.sections.SmartspaceSection
import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeClockSection
import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeGuidelines
+import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeMediaSection
import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeNotificationStackScrollLayoutSection
import com.android.systemui.util.kotlin.getOrNull
import java.util.Optional
@@ -63,6 +64,7 @@ constructor(
communalTutorialIndicatorSection: CommunalTutorialIndicatorSection,
smartspaceSection: SmartspaceSection,
clockSection: SplitShadeClockSection,
+ mediaSection: SplitShadeMediaSection,
) : KeyguardBlueprint {
override val id: String = ID
@@ -81,6 +83,7 @@ constructor(
aodBurnInSection,
communalTutorialIndicatorSection,
clockSection,
+ mediaSection,
defaultDeviceEntrySection, // Add LAST: Intentionally has z-order above other views.
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeMediaSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeMediaSection.kt
new file mode 100644
index 000000000000..5afdbaa47d95
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeMediaSection.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2023 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.keyguard.ui.view.layout.sections
+
+import android.content.Context
+import android.view.View
+import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
+import android.widget.FrameLayout
+import androidx.constraintlayout.widget.Barrier
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.constraintlayout.widget.ConstraintSet
+import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
+import androidx.constraintlayout.widget.ConstraintSet.END
+import androidx.constraintlayout.widget.ConstraintSet.MATCH_CONSTRAINT
+import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
+import androidx.constraintlayout.widget.ConstraintSet.START
+import androidx.constraintlayout.widget.ConstraintSet.TOP
+import com.android.systemui.Flags.migrateClocksToBlueprint
+import com.android.systemui.keyguard.shared.model.KeyguardSection
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
+import com.android.systemui.media.controls.ui.KeyguardMediaController
+import com.android.systemui.res.R
+import com.android.systemui.shade.NotificationPanelView
+import javax.inject.Inject
+
+/** Aligns media on left side for split shade, below smartspace, date, and weather. */
+class SplitShadeMediaSection
+@Inject
+constructor(
+ private val context: Context,
+ private val notificationPanelView: NotificationPanelView,
+ private val keyguardSmartspaceViewModel: KeyguardSmartspaceViewModel,
+ private val keyguardMediaController: KeyguardMediaController
+) : KeyguardSection() {
+ private val mediaContainerId = R.id.status_view_media_container
+ private val smartSpaceBarrier = R.id.smart_space_barrier_bottom
+
+ override fun addViews(constraintLayout: ConstraintLayout) {
+ if (!migrateClocksToBlueprint()) {
+ return
+ }
+
+ notificationPanelView.findViewById<View>(mediaContainerId)?.let {
+ notificationPanelView.removeView(it)
+ }
+
+ val mediaFrame =
+ FrameLayout(context, null).apply {
+ id = mediaContainerId
+ val padding = context.resources.getDimensionPixelSize(R.dimen.qs_media_padding)
+ val horizontalPadding =
+ padding +
+ context.resources.getDimensionPixelSize(
+ R.dimen.status_view_margin_horizontal
+ )
+
+ setPaddingRelative(horizontalPadding, padding, horizontalPadding, padding)
+ }
+ constraintLayout.addView(mediaFrame)
+ keyguardMediaController.attachSplitShadeContainer(mediaFrame)
+ }
+
+ override fun bindData(constraintLayout: ConstraintLayout) {}
+
+ override fun applyConstraints(constraintSet: ConstraintSet) {
+ if (!migrateClocksToBlueprint()) {
+ return
+ }
+
+ constraintSet.apply {
+ constrainWidth(mediaContainerId, MATCH_CONSTRAINT)
+ constrainHeight(mediaContainerId, WRAP_CONTENT)
+
+ createBarrier(
+ smartSpaceBarrier,
+ Barrier.BOTTOM,
+ 0,
+ *intArrayOf(
+ keyguardSmartspaceViewModel.smartspaceViewId,
+ keyguardSmartspaceViewModel.dateId,
+ keyguardSmartspaceViewModel.weatherId,
+ )
+ )
+ connect(mediaContainerId, TOP, smartSpaceBarrier, BOTTOM)
+ connect(mediaContainerId, START, PARENT_ID, START)
+ connect(mediaContainerId, END, R.id.split_shade_guideline, END)
+ }
+ }
+
+ override fun removeViews(constraintLayout: ConstraintLayout) {
+ if (!migrateClocksToBlueprint()) {
+ return
+ }
+
+ constraintLayout.removeView(mediaContainerId)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt
index 945bf9a5c0b2..e15e03822610 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt
@@ -27,6 +27,7 @@ import android.view.View
import android.view.ViewGroup
import androidx.annotation.VisibleForTesting
import com.android.systemui.Dumpable
+import com.android.systemui.Flags.migrateClocksToBlueprint
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
@@ -180,7 +181,11 @@ constructor(
/** Called whenever the media hosts visibility changes */
private fun onMediaHostVisibilityChanged(visible: Boolean) {
refreshMediaPosition(reason = "onMediaHostVisibilityChanged")
+
if (visible) {
+ if (migrateClocksToBlueprint() && useSplitShade) {
+ return
+ }
mediaHost.hostView.layoutParams.apply {
height = ViewGroup.LayoutParams.WRAP_CONTENT
width = ViewGroup.LayoutParams.MATCH_PARENT
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 17eb3c83fefe..286037ef1961 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -1160,9 +1160,9 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
// Occluded->Lockscreen
collectFlow(mView, mKeyguardTransitionInteractor.getOccludedToLockscreenTransition(),
mOccludedToLockscreenTransition, mMainDispatcher);
- if (!KeyguardShadeMigrationNssl.isEnabled()) {
- collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(),
+ collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(),
setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+ if (!KeyguardShadeMigrationNssl.isEnabled()) {
collectFlow(mView,
mOccludedToLockscreenTransitionViewModel.getLockscreenTranslationY(),
setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
@@ -1192,8 +1192,10 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
mLockscreenToOccludedTransition, mMainDispatcher);
collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha(),
setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
- collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenTranslationY(),
- setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
+ if (!KeyguardShadeMigrationNssl.isEnabled()) {
+ collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenTranslationY(),
+ setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
+ }
// Primary bouncer->Gone (ensures lockscreen content is not visible on successful auth)
collectFlow(mView, mPrimaryBouncerToGoneTransitionViewModel.getLockscreenAlpha(),
@@ -1463,6 +1465,9 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
}
private void attachSplitShadeMediaPlayerContainer(FrameLayout container) {
+ if (migrateClocksToBlueprint()) {
+ return;
+ }
mKeyguardMediaController.attachSplitShadeContainer(container);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
index eff91e55d9a8..5ee38bebc99b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
@@ -25,6 +25,8 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState.SHADE_LOCKED
+import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
+import com.android.systemui.keyguard.shared.model.TransitionState.STARTED
import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel
import com.android.systemui.shade.domain.interactor.ShadeInteractor
@@ -71,6 +73,20 @@ constructor(
KeyguardState.PRIMARY_BOUNCER
)
+ private val lockscreenToOccludedRunning =
+ keyguardTransitionInteractor
+ .transition(KeyguardState.LOCKSCREEN, KeyguardState.OCCLUDED)
+ .map { it.transitionState == STARTED || it.transitionState == RUNNING }
+ .distinctUntilChanged()
+ .onStart { emit(false) }
+
+ private val occludedToLockscreenRunning =
+ keyguardTransitionInteractor
+ .transition(KeyguardState.OCCLUDED, KeyguardState.LOCKSCREEN)
+ .map { it.transitionState == STARTED || it.transitionState == RUNNING }
+ .distinctUntilChanged()
+ .onStart { emit(false) }
+
val shadeCollapseFadeInComplete = MutableStateFlow(false)
val configurationBasedDimensions: Flow<ConfigurationBasedDimensions> =
@@ -122,7 +138,11 @@ constructor(
) { isKeyguard, isShadeVisible, qsExpansion ->
isKeyguard && !(isShadeVisible || qsExpansion)
}
- .distinctUntilChanged()
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.Eagerly,
+ initialValue = false,
+ )
/** Fade in only for use after the shade collapses */
val shadeCollpaseFadeIn: Flow<Boolean> =
@@ -182,26 +202,37 @@ constructor(
)
val alpha: Flow<Float> =
- isOnLockscreenWithoutShade
- .flatMapLatest { isOnLockscreenWithoutShade ->
- combineTransform(
- merge(
- occludedToLockscreenTransitionViewModel.lockscreenAlpha,
- lockscreenToOccludedTransitionViewModel.lockscreenAlpha,
- keyguardInteractor.keyguardAlpha,
- ),
- shadeCollpaseFadeIn,
- ) { alpha, shadeCollpaseFadeIn ->
- if (isOnLockscreenWithoutShade) {
- if (!shadeCollpaseFadeIn) {
- emit(alpha)
- }
+ // Due to issues with the legacy shade, some shade expansion events are sent incorrectly,
+ // such as when the shade resets. This can happen while the LOCKSCREEN<->OCCLUDED transition
+ // is running. Therefore use a series of flatmaps to prevent unwanted interruptions while
+ // those transitions are in progress. Without this, the alpha value will produce a visible
+ // flicker.
+ lockscreenToOccludedRunning.flatMapLatest { isLockscreenToOccludedRunning ->
+ if (isLockscreenToOccludedRunning) {
+ lockscreenToOccludedTransitionViewModel.lockscreenAlpha
+ } else {
+ occludedToLockscreenRunning.flatMapLatest { isOccludedToLockscreenRunning ->
+ if (isOccludedToLockscreenRunning) {
+ occludedToLockscreenTransitionViewModel.lockscreenAlpha.onStart { emit(0f) }
} else {
- emit(1f)
+ isOnLockscreenWithoutShade.flatMapLatest { isOnLockscreenWithoutShade ->
+ combineTransform(
+ keyguardInteractor.keyguardAlpha,
+ shadeCollpaseFadeIn,
+ ) { alpha, shadeCollpaseFadeIn ->
+ if (isOnLockscreenWithoutShade) {
+ if (!shadeCollpaseFadeIn) {
+ emit(alpha)
+ }
+ } else {
+ emit(1f)
+ }
+ }
+ }
}
}
}
- .distinctUntilChanged()
+ }
/**
* Under certain scenarios, such as swiping up on the lockscreen, the container will need to be
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
index 36a471238c8a..20020f23b2df 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
@@ -43,6 +43,7 @@ import com.android.systemui.statusbar.notification.stack.domain.interactor.share
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -418,13 +419,13 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
}
@Test
- fun shadeCollpaseFadeIn() =
+ fun shadeCollapseFadeIn() =
testScope.runTest {
+ val fadeIn by collectLastValue(underTest.shadeCollpaseFadeIn)
+
// Start on lockscreen without the shade
underTest.setShadeCollapseFadeInComplete(false)
showLockscreen()
-
- val fadeIn by collectLastValue(underTest.shadeCollpaseFadeIn)
assertThat(fadeIn).isEqualTo(false)
// ... then the shade expands
@@ -440,10 +441,12 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
assertThat(fadeIn).isEqualTo(false)
}
- private suspend fun showLockscreen() {
+ private suspend fun TestScope.showLockscreen() {
shadeRepository.setLockscreenShadeExpansion(0f)
shadeRepository.setQsExpansion(0f)
+ runCurrent()
keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
+ runCurrent()
keyguardTransitionRepository.sendTransitionSteps(
from = KeyguardState.AOD,
to = KeyguardState.LOCKSCREEN,
@@ -451,10 +454,12 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
)
}
- private suspend fun showLockscreenWithShadeExpanded() {
+ private suspend fun TestScope.showLockscreenWithShadeExpanded() {
shadeRepository.setLockscreenShadeExpansion(1f)
shadeRepository.setQsExpansion(0f)
+ runCurrent()
keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED)
+ runCurrent()
keyguardTransitionRepository.sendTransitionSteps(
from = KeyguardState.AOD,
to = KeyguardState.LOCKSCREEN,
@@ -462,10 +467,12 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
)
}
- private suspend fun showLockscreenWithQSExpanded() {
+ private suspend fun TestScope.showLockscreenWithQSExpanded() {
shadeRepository.setLockscreenShadeExpansion(0f)
shadeRepository.setQsExpansion(1f)
+ runCurrent()
keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED)
+ runCurrent()
keyguardTransitionRepository.sendTransitionSteps(
from = KeyguardState.AOD,
to = KeyguardState.LOCKSCREEN,