diff options
21 files changed, 466 insertions, 282 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java index a5a545af641a..033f93b260ab 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java @@ -3,6 +3,7 @@ package com.android.keyguard; import static com.android.keyguard.KeyguardStatusAreaView.TRANSLATE_X_CLOCK_DESIGN; import static com.android.keyguard.KeyguardStatusAreaView.TRANSLATE_Y_CLOCK_DESIGN; import static com.android.keyguard.KeyguardStatusAreaView.TRANSLATE_Y_CLOCK_SIZE; +import static com.android.systemui.Flags.migrateClocksToBlueprint; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -191,11 +192,11 @@ public class KeyguardClockSwitch extends RelativeLayout { @Override protected void onFinishInflate() { super.onFinishInflate(); - - mSmallClockFrame = findViewById(R.id.lockscreen_clock_view); - mLargeClockFrame = findViewById(R.id.lockscreen_clock_view_large); - mStatusArea = findViewById(R.id.keyguard_status_area); - + if (!migrateClocksToBlueprint()) { + mSmallClockFrame = findViewById(R.id.lockscreen_clock_view); + mLargeClockFrame = findViewById(R.id.lockscreen_clock_view_large); + mStatusArea = findViewById(R.id.keyguard_status_area); + } onConfigChanged(); } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java index d372f5a616b1..1758831203d6 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java @@ -494,7 +494,7 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV boolean shouldBeCentered, boolean animate) { if (migrateClocksToBlueprint()) { - mKeyguardInteractor.setClockShouldBeCentered(mSplitShadeEnabled && shouldBeCentered); + mKeyguardInteractor.setClockShouldBeCentered(shouldBeCentered); } else { mKeyguardClockSwitchController.setSplitShadeCentered( splitShadeEnabled && shouldBeCentered); diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepository.kt new file mode 100644 index 000000000000..afe9151ac7a0 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepository.kt @@ -0,0 +1,34 @@ +/* + * 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.data.repository + +import android.view.View +import com.android.systemui.dagger.SysUISingleton +import javax.inject.Inject +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow + +@SysUISingleton +class KeyguardSmartspaceRepository @Inject constructor() { + private val _bcSmartspaceVisibility: MutableStateFlow<Int> = MutableStateFlow(View.GONE) + val bcSmartspaceVisibility: StateFlow<Int> = _bcSmartspaceVisibility.asStateFlow() + + fun setBcSmartspaceVisibility(visibility: Int) { + _bcSmartspaceVisibility.value = visibility + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSmartspaceInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSmartspaceInteractor.kt new file mode 100644 index 000000000000..67b57456a5c6 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardSmartspaceInteractor.kt @@ -0,0 +1,33 @@ +/* + * 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.domain.interactor + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyguard.data.repository.KeyguardSmartspaceRepository +import javax.inject.Inject +import kotlinx.coroutines.flow.StateFlow + +@SysUISingleton +class KeyguardSmartspaceInteractor +@Inject +constructor(private val keyguardSmartspaceRepository: KeyguardSmartspaceRepository) { + var bcSmartspaceVisibility: StateFlow<Int> = keyguardSmartspaceRepository.bcSmartspaceVisibility + + fun setBcSmartspaceVisibility(visibility: Int) { + keyguardSmartspaceRepository.setBcSmartspaceVisibility(visibility) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt index bf763b4e1f99..400b8bfff9b0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt @@ -30,7 +30,10 @@ import androidx.constraintlayout.widget.ConstraintSet import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle import com.android.app.animation.Interpolators +import com.android.keyguard.KeyguardClockSwitch.LARGE +import com.android.keyguard.KeyguardClockSwitch.SMALL import com.android.systemui.Flags.migrateClocksToBlueprint +import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel @@ -48,6 +51,7 @@ object KeyguardClockViewBinder { keyguardRootView: ConstraintLayout, viewModel: KeyguardClockViewModel, keyguardClockInteractor: KeyguardClockInteractor, + blueprintInteractor: KeyguardBlueprintInteractor, ) { keyguardRootView.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { @@ -61,18 +65,16 @@ object KeyguardClockViewBinder { viewModel.currentClock.collect { currentClock -> cleanupClockViews(viewModel.clock, keyguardRootView, viewModel.burnInLayer) viewModel.clock = currentClock - addClockViews(currentClock, keyguardRootView, viewModel.burnInLayer) - viewModel.burnInLayer?.updatePostLayout(keyguardRootView) - applyConstraints(clockSection, keyguardRootView, true) + addClockViews(currentClock, keyguardRootView) + updateBurnInLayer(keyguardRootView, viewModel) + blueprintInteractor.refreshBlueprint() } } - // TODO: Weather clock dozing animation - // will trigger both shouldBeCentered and clockSize change - // we should avoid this launch { if (!migrateClocksToBlueprint()) return@launch viewModel.clockSize.collect { - applyConstraints(clockSection, keyguardRootView, true) + updateBurnInLayer(keyguardRootView, viewModel) + blueprintInteractor.refreshBlueprint() } } launch { @@ -82,7 +84,7 @@ object KeyguardClockViewBinder { if (it.largeClock.config.hasCustomPositionUpdatedAnimation) { playClockCenteringAnimation(clockSection, keyguardRootView, it) } else { - applyConstraints(clockSection, keyguardRootView, true) + blueprintInteractor.refreshBlueprint() } } } @@ -90,6 +92,29 @@ object KeyguardClockViewBinder { } } } + @VisibleForTesting + fun updateBurnInLayer( + keyguardRootView: ConstraintLayout, + viewModel: KeyguardClockViewModel, + ) { + val burnInLayer = viewModel.burnInLayer + val clockController = viewModel.currentClock.value + clockController?.let { clock -> + when (viewModel.clockSize.value) { + LARGE -> { + clock.smallClock.layout.views.forEach { burnInLayer?.removeView(it) } + if (clock.config.useAlternateSmartspaceAODTransition) { + clock.largeClock.layout.views.forEach { burnInLayer?.addView(it) } + } + } + SMALL -> { + clock.smallClock.layout.views.forEach { burnInLayer?.addView(it) } + clock.largeClock.layout.views.forEach { burnInLayer?.removeView(it) } + } + } + } + viewModel.burnInLayer?.updatePostLayout(keyguardRootView) + } private fun cleanupClockViews( clockController: ClockController?, @@ -116,7 +141,6 @@ object KeyguardClockViewBinder { fun addClockViews( clockController: ClockController?, rootView: ConstraintLayout, - burnInLayer: Layer? ) { clockController?.let { clock -> clock.smallClock.layout.views[0].id = R.id.lockscreen_clock_view @@ -125,17 +149,10 @@ object KeyguardClockViewBinder { } // small clock should either be a single view or container with id // `lockscreen_clock_view` - clock.smallClock.layout.views.forEach { - rootView.addView(it) - burnInLayer?.addView(it) - } + clock.smallClock.layout.views.forEach { rootView.addView(it) } clock.largeClock.layout.views.forEach { rootView.addView(it) } - if (clock.config.useAlternateSmartspaceAODTransition) { - clock.largeClock.layout.views.forEach { burnInLayer?.addView(it) } - } } } - fun applyConstraints( clockSection: ClockSection, rootView: ConstraintLayout, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt index 81ce8f04d302..10392e3c1450 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSmartspaceViewBinder.kt @@ -16,15 +16,13 @@ package com.android.systemui.keyguard.ui.binder -import android.transition.TransitionManager import android.view.View import androidx.constraintlayout.helper.widget.Layer import androidx.constraintlayout.widget.ConstraintLayout -import androidx.constraintlayout.widget.ConstraintSet import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle import com.android.systemui.Flags.migrateClocksToBlueprint -import com.android.systemui.keyguard.ui.view.layout.sections.SmartspaceSection +import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel import com.android.systemui.lifecycle.repeatWhenAttached @@ -35,10 +33,10 @@ import kotlinx.coroutines.launch object KeyguardSmartspaceViewBinder { @JvmStatic fun bind( - smartspaceSection: SmartspaceSection, keyguardRootView: ConstraintLayout, clockViewModel: KeyguardClockViewModel, smartspaceViewModel: KeyguardSmartspaceViewModel, + blueprintInteractor: KeyguardBlueprintInteractor, ) { keyguardRootView.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { @@ -46,22 +44,56 @@ object KeyguardSmartspaceViewBinder { if (!migrateClocksToBlueprint()) return@launch clockViewModel.hasCustomWeatherDataDisplay.collect { hasCustomWeatherDataDisplay -> - if (hasCustomWeatherDataDisplay) { - removeDateWeatherToBurnInLayer(keyguardRootView, smartspaceViewModel) - } else { - addDateWeatherToBurnInLayer(keyguardRootView, smartspaceViewModel) - } - clockViewModel.burnInLayer?.updatePostLayout(keyguardRootView) - val constraintSet = ConstraintSet().apply { clone(keyguardRootView) } - smartspaceSection.applyConstraints(constraintSet) - TransitionManager.beginDelayedTransition(keyguardRootView) - constraintSet.applyTo(keyguardRootView) + updateDateWeatherToBurnInLayer( + keyguardRootView, + clockViewModel, + smartspaceViewModel + ) + blueprintInteractor.refreshBlueprint() + } + } + + launch { + smartspaceViewModel.bcSmartspaceVisibility.collect { + updateBCSmartspaceInBurnInLayer(keyguardRootView, clockViewModel) + blueprintInteractor.refreshBlueprint() } } } } } + private fun updateBCSmartspaceInBurnInLayer( + keyguardRootView: ConstraintLayout, + clockViewModel: KeyguardClockViewModel, + ) { + // Visibility is controlled by updateTargetVisibility in CardPagerAdapter + val burnInLayer = keyguardRootView.requireViewById<Layer>(R.id.burn_in_layer) + burnInLayer.apply { + val smartspaceView = + keyguardRootView.requireViewById<View>(sharedR.id.bc_smartspace_view) + if (smartspaceView.visibility == View.VISIBLE) { + addView(smartspaceView) + } else { + removeView(smartspaceView) + } + } + clockViewModel.burnInLayer?.updatePostLayout(keyguardRootView) + } + + private fun updateDateWeatherToBurnInLayer( + keyguardRootView: ConstraintLayout, + clockViewModel: KeyguardClockViewModel, + smartspaceViewModel: KeyguardSmartspaceViewModel + ) { + if (clockViewModel.hasCustomWeatherDataDisplay.value) { + removeDateWeatherFromBurnInLayer(keyguardRootView, smartspaceViewModel) + } else { + addDateWeatherToBurnInLayer(keyguardRootView, smartspaceViewModel) + } + clockViewModel.burnInLayer?.updatePostLayout(keyguardRootView) + } + private fun addDateWeatherToBurnInLayer( constraintLayout: ConstraintLayout, smartspaceViewModel: KeyguardSmartspaceViewModel @@ -76,13 +108,13 @@ object KeyguardSmartspaceViewBinder { constraintLayout.requireViewById<View>(sharedR.id.date_smartspace_view) val weatherView = constraintLayout.requireViewById<View>(sharedR.id.weather_smartspace_view) - addView(weatherView) addView(dateView) + addView(weatherView) } } } - private fun removeDateWeatherToBurnInLayer( + private fun removeDateWeatherFromBurnInLayer( constraintLayout: ConstraintLayout, smartspaceViewModel: KeyguardSmartspaceViewModel ) { 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 24d06026dcf7..8472a9f6da6d 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 @@ -23,6 +23,7 @@ import com.android.systemui.keyguard.shared.model.KeyguardBlueprint import com.android.systemui.keyguard.shared.model.KeyguardSection import com.android.systemui.keyguard.ui.view.layout.sections.AodBurnInSection import com.android.systemui.keyguard.ui.view.layout.sections.AodNotificationIconsSection +import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection import com.android.systemui.keyguard.ui.view.layout.sections.DefaultDeviceEntrySection import com.android.systemui.keyguard.ui.view.layout.sections.DefaultIndicationAreaSection import com.android.systemui.keyguard.ui.view.layout.sections.DefaultSettingsPopupMenuSection @@ -30,11 +31,10 @@ import com.android.systemui.keyguard.ui.view.layout.sections.DefaultShortcutsSec import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusBarSection import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusViewSection import com.android.systemui.keyguard.ui.view.layout.sections.KeyguardSectionsModule -import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeClockSection +import com.android.systemui.keyguard.ui.view.layout.sections.SmartspaceSection 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.keyguard.ui.view.layout.sections.SplitShadeSmartspaceSection import com.android.systemui.util.kotlin.getOrNull import java.util.Optional import javax.inject.Inject @@ -62,8 +62,8 @@ constructor( aodNotificationIconsSection: AodNotificationIconsSection, aodBurnInSection: AodBurnInSection, communalTutorialIndicatorSection: CommunalTutorialIndicatorSection, - smartspaceSection: SplitShadeSmartspaceSection, - clockSection: SplitShadeClockSection, + clockSection: ClockSection, + smartspaceSection: SmartspaceSection, mediaSection: SplitShadeMediaSection, ) : KeyguardBlueprint { override val id: String = ID diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/transitions/BaseBlueprintTransition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/transitions/BaseBlueprintTransition.kt index d0626d58a4ad..fd530b77707a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/transitions/BaseBlueprintTransition.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/transitions/BaseBlueprintTransition.kt @@ -25,6 +25,8 @@ import android.transition.Visibility import android.view.View import android.view.ViewGroup import androidx.constraintlayout.helper.widget.Layer +import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView +import com.android.systemui.res.R class BaseBlueprintTransition : TransitionSet() { init { @@ -33,7 +35,16 @@ class BaseBlueprintTransition : TransitionSet() { .addTransition(ChangeBounds()) .addTransition(AlphaInVisibility()) excludeTarget(Layer::class.java, /* exclude= */ true) + excludeClockAndSmartspaceViews() } + + private fun excludeClockAndSmartspaceViews() { + excludeTarget(R.id.lockscreen_clock_view, true) + excludeTarget(R.id.lockscreen_clock_view_large, true) + excludeTarget(SmartspaceView::class.java, true) + // TODO(b/319468190): need to exclude views from large weather clock + } + class AlphaOutVisibility : Visibility() { override fun onDisappear( sceneRoot: ViewGroup?, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInLayer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInLayer.kt new file mode 100644 index 000000000000..67a20e588198 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInLayer.kt @@ -0,0 +1,73 @@ +/* + * 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 androidx.constraintlayout.helper.widget.Layer + +class AodBurnInLayer(context: Context) : Layer(context) { + // For setScale in Layer class, it stores it in mScaleX/Y and directly apply scale to + // referenceViews instead of keeping the value in fields of View class + // when we try to clone ConstraintSet, it will call getScaleX from View class and return 1.0 + // and when we clone and apply, it will reset everything in the layer + // which cause the flicker from AOD to LS + private var _scaleX = 1F + private var _scaleY = 1F + // As described for _scaleX and _scaleY, we have similar issue with translation + private var _translationX = 1F + private var _translationY = 1F + // avoid adding views with same ids + override fun addView(view: View?) { + view?.let { if (it.id !in referencedIds) super.addView(view) } + } + override fun setScaleX(scaleX: Float) { + _scaleX = scaleX + super.setScaleX(scaleX) + } + + override fun getScaleX(): Float { + return _scaleX + } + + override fun setScaleY(scaleY: Float) { + _scaleY = scaleY + super.setScaleY(scaleY) + } + + override fun getScaleY(): Float { + return _scaleY + } + + override fun setTranslationX(dx: Float) { + _translationX = dx + super.setTranslationX(dx) + } + + override fun getTranslationX(): Float { + return _translationX + } + + override fun setTranslationY(dy: Float) { + _translationY = dy + super.setTranslationY(dy) + } + + override fun getTranslationY(): Float { + return _translationY + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt index 1ccc6ccf2cec..3d36eb03a1bc 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt @@ -19,16 +19,13 @@ package com.android.systemui.keyguard.ui.view.layout.sections import android.content.Context import android.view.View -import androidx.constraintlayout.helper.widget.Layer import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintSet import com.android.systemui.Flags.migrateClocksToBlueprint import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl import com.android.systemui.keyguard.shared.model.KeyguardSection import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel -import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel import com.android.systemui.res.R -import com.android.systemui.shared.R as sharedR import javax.inject.Inject /** Adds a layer to group elements for translation for burn-in preventation */ @@ -37,10 +34,8 @@ class AodBurnInSection constructor( private val context: Context, private val clockViewModel: KeyguardClockViewModel, - private val smartspaceViewModel: KeyguardSmartspaceViewModel, ) : KeyguardSection() { - lateinit var burnInLayer: Layer - + private lateinit var burnInLayer: AodBurnInLayer override fun addViews(constraintLayout: ConstraintLayout) { if (!KeyguardShadeMigrationNssl.isEnabled) { return @@ -48,7 +43,7 @@ constructor( val nic = constraintLayout.requireViewById<View>(R.id.aod_notification_icon_container) burnInLayer = - Layer(context).apply { + AodBurnInLayer(context).apply { id = R.id.burn_in_layer addView(nic) if (!migrateClocksToBlueprint()) { @@ -57,11 +52,6 @@ constructor( addView(statusView) } } - if (migrateClocksToBlueprint()) { - // weather and date parts won't be added here, cause their visibility doesn't align - // with others in burnInLayer - addSmartspaceViews(constraintLayout) - } constraintLayout.addView(burnInLayer) } @@ -83,14 +73,4 @@ constructor( override fun removeViews(constraintLayout: ConstraintLayout) { constraintLayout.removeView(R.id.burn_in_layer) } - - private fun addSmartspaceViews(constraintLayout: ConstraintLayout) { - burnInLayer.apply { - if (smartspaceViewModel.isSmartspaceEnabled) { - val smartspaceView = - constraintLayout.requireViewById<View>(sharedR.id.bc_smartspace_view) - addView(smartspaceView) - } - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt index f560b5f068c9..ed7abff555e7 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt @@ -30,9 +30,7 @@ import com.android.systemui.Flags.migrateClocksToBlueprint import com.android.systemui.common.ui.ConfigurationState import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl import com.android.systemui.keyguard.shared.model.KeyguardSection -import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel import com.android.systemui.res.R -import com.android.systemui.shared.R as sharedR import com.android.systemui.statusbar.notification.icon.ui.viewbinder.AlwaysOnDisplayNotificationIconViewStore import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerViewBinder import com.android.systemui.statusbar.notification.icon.ui.viewbinder.StatusBarIconViewBindingFailureTracker @@ -53,13 +51,13 @@ constructor( private val nicAodViewModel: NotificationIconContainerAlwaysOnDisplayViewModel, private val nicAodIconViewStore: AlwaysOnDisplayNotificationIconViewStore, private val notificationIconAreaController: NotificationIconAreaController, - private val smartspaceViewModel: KeyguardSmartspaceViewModel, private val systemBarUtilsState: SystemBarUtilsState, ) : KeyguardSection() { private var nicBindingDisposable: DisposableHandle? = null private val nicId = R.id.aod_notification_icon_container private lateinit var nic: NotificationIconContainer + private val smartSpaceBarrier = View.generateViewId() override fun addViews(constraintLayout: ConstraintLayout) { if (!KeyguardShadeMigrationNssl.isEnabled) { @@ -118,7 +116,7 @@ constructor( } constraintSet.apply { if (migrateClocksToBlueprint()) { - connect(nicId, TOP, sharedR.id.bc_smartspace_view, BOTTOM, bottomMargin) + connect(nicId, TOP, R.id.smart_space_barrier_bottom, BOTTOM, bottomMargin) setGoneMargin(nicId, BOTTOM, bottomMargin) } else { connect(nicId, TOP, R.id.keyguard_status_view, topAlignment, bottomMargin) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt index b5f32c8a5608..b344d3b9afea 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt @@ -23,11 +23,14 @@ 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.INVISIBLE import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID import androidx.constraintlayout.widget.ConstraintSet.START import androidx.constraintlayout.widget.ConstraintSet.TOP +import androidx.constraintlayout.widget.ConstraintSet.VISIBLE import androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT import com.android.systemui.Flags +import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor import com.android.systemui.keyguard.shared.model.KeyguardSection import com.android.systemui.keyguard.ui.binder.KeyguardClockViewBinder @@ -35,8 +38,10 @@ import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel import com.android.systemui.plugins.clocks.ClockController import com.android.systemui.plugins.clocks.ClockFaceLayout import com.android.systemui.res.R +import com.android.systemui.shared.R as sharedR import com.android.systemui.statusbar.policy.SplitShadeStateController import com.android.systemui.util.Utils +import dagger.Lazy import javax.inject.Inject internal fun ConstraintSet.setVisibility( @@ -56,6 +61,7 @@ constructor( protected val keyguardClockViewModel: KeyguardClockViewModel, private val context: Context, private val splitShadeStateController: SplitShadeStateController, + val blueprintInteractor: Lazy<KeyguardBlueprintInteractor>, ) : KeyguardSection() { override fun addViews(constraintLayout: ConstraintLayout) {} @@ -68,6 +74,7 @@ constructor( constraintLayout, keyguardClockViewModel, clockInteractor, + blueprintInteractor.get() ) } @@ -88,12 +95,16 @@ constructor( ): ConstraintSet { // Add constraint between rootView and clockContainer applyDefaultConstraints(constraintSet) + getNonTargetClockFace(clock).applyConstraints(constraintSet) getTargetClockFace(clock).applyConstraints(constraintSet) // Add constraint between elements in clock and clock container return constraintSet.apply { - setAlpha(getTargetClockFace(clock).views, 1F) - setAlpha(getNonTargetClockFace(clock).views, 0F) + setVisibility(getTargetClockFace(clock).views, VISIBLE) + setVisibility(getNonTargetClockFace(clock).views, INVISIBLE) + if (!keyguardClockViewModel.useLargeClock) { + connect(sharedR.id.bc_smartspace_view, TOP, sharedR.id.date_smartspace_view, BOTTOM) + } } } @@ -107,9 +118,12 @@ constructor( private fun getLargeClockFace(clock: ClockController): ClockFaceLayout = clock.largeClock.layout private fun getSmallClockFace(clock: ClockController): ClockFaceLayout = clock.smallClock.layout open fun applyDefaultConstraints(constraints: ConstraintSet) { + val guideline = + if (keyguardClockViewModel.clockShouldBeCentered.value) PARENT_ID + else R.id.split_shade_guideline constraints.apply { connect(R.id.lockscreen_clock_view_large, START, PARENT_ID, START) - connect(R.id.lockscreen_clock_view_large, END, PARENT_ID, END) + connect(R.id.lockscreen_clock_view_large, END, guideline, END) connect(R.id.lockscreen_clock_view_large, BOTTOM, R.id.lock_icon_view, TOP) var largeClockTopMargin = context.resources.getDimensionPixelSize(R.dimen.status_bar_height) + diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt index b0eee0a68b1f..8c5e9b4c6817 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt @@ -18,6 +18,7 @@ package com.android.systemui.keyguard.ui.view.layout.sections import android.content.Context +import android.view.View import androidx.constraintlayout.widget.ConstraintSet import androidx.constraintlayout.widget.ConstraintSet.BOTTOM import androidx.constraintlayout.widget.ConstraintSet.END @@ -27,11 +28,9 @@ import androidx.constraintlayout.widget.ConstraintSet.TOP import com.android.systemui.Flags.migrateClocksToBlueprint import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl -import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel import com.android.systemui.res.R import com.android.systemui.scene.shared.flag.SceneContainerFlags import com.android.systemui.shade.NotificationPanelView -import com.android.systemui.shared.R as sharedR import com.android.systemui.statusbar.notification.stack.AmbientState import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator @@ -54,7 +53,6 @@ constructor( ambientState: AmbientState, controller: NotificationStackScrollLayoutController, notificationStackSizeCalculator: NotificationStackSizeCalculator, - private val smartspaceViewModel: KeyguardSmartspaceViewModel, @Main mainDispatcher: CoroutineDispatcher, ) : NotificationStackScrollLayoutSection( @@ -69,6 +67,7 @@ constructor( notificationStackSizeCalculator, mainDispatcher, ) { + private val smartSpaceBarrier = View.generateViewId() override fun applyConstraints(constraintSet: ConstraintSet) { if (!KeyguardShadeMigrationNssl.isEnabled) { return @@ -76,16 +75,14 @@ constructor( constraintSet.apply { val bottomMargin = context.resources.getDimensionPixelSize(R.dimen.keyguard_status_view_bottom_margin) - if (migrateClocksToBlueprint()) { connect( R.id.nssl_placeholder, TOP, - sharedR.id.bc_smartspace_view, + R.id.smart_space_barrier_bottom, BOTTOM, bottomMargin ) - setGoneMargin(R.id.nssl_placeholder, TOP, bottomMargin) } else { connect(R.id.nssl_placeholder, TOP, R.id.keyguard_status_view, BOTTOM, bottomMargin) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt index eacd466bc473..37842a84c3d3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt @@ -18,37 +18,41 @@ package com.android.systemui.keyguard.ui.view.layout.sections import android.content.Context import android.view.View +import android.view.View.GONE +import android.view.ViewTreeObserver.OnGlobalLayoutListener +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.PARENT_ID -import androidx.constraintlayout.widget.ConstraintSet.START -import androidx.constraintlayout.widget.ConstraintSet.TOP -import androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT import com.android.systemui.Flags.migrateClocksToBlueprint import com.android.systemui.keyguard.KeyguardUnlockAnimationController +import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor +import com.android.systemui.keyguard.domain.interactor.KeyguardSmartspaceInteractor import com.android.systemui.keyguard.shared.model.KeyguardSection import com.android.systemui.keyguard.ui.binder.KeyguardSmartspaceViewBinder import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel -import com.android.systemui.res.R +import com.android.systemui.shared.R import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController +import dagger.Lazy import javax.inject.Inject open class SmartspaceSection @Inject constructor( + val context: Context, val keyguardClockViewModel: KeyguardClockViewModel, val keyguardSmartspaceViewModel: KeyguardSmartspaceViewModel, - private val context: Context, + val keyguardSmartspaceInteractor: KeyguardSmartspaceInteractor, val smartspaceController: LockscreenSmartspaceController, val keyguardUnlockAnimationController: KeyguardUnlockAnimationController, + val blueprintInteractor: Lazy<KeyguardBlueprintInteractor>, ) : KeyguardSection() { private var smartspaceView: View? = null private var weatherView: View? = null private var dateView: View? = null + private var smartspaceVisibilityListener: OnGlobalLayoutListener? = null + override fun addViews(constraintLayout: ConstraintLayout) { if (!migrateClocksToBlueprint()) { return @@ -64,6 +68,20 @@ constructor( } } keyguardUnlockAnimationController.lockscreenSmartspace = smartspaceView + smartspaceVisibilityListener = + object : OnGlobalLayoutListener { + var pastVisibility = GONE + override fun onGlobalLayout() { + smartspaceView?.let { + val newVisibility = it.visibility + if (pastVisibility != newVisibility) { + keyguardSmartspaceInteractor.setBcSmartspaceVisibility(newVisibility) + pastVisibility = newVisibility + } + } + } + } + smartspaceView?.viewTreeObserver?.addOnGlobalLayoutListener(smartspaceVisibilityListener) } override fun bindData(constraintLayout: ConstraintLayout) { @@ -71,10 +89,10 @@ constructor( return } KeyguardSmartspaceViewBinder.bind( - this, constraintLayout, keyguardClockViewModel, keyguardSmartspaceViewModel, + blueprintInteractor.get(), ) } @@ -82,65 +100,96 @@ constructor( if (!migrateClocksToBlueprint()) { return } - // Generally, weather should be next to dateView - // smartspace should be below date & weather views constraintSet.apply { // migrate addDateWeatherView, addWeatherView from KeyguardClockSwitchController - dateView?.let { dateView -> - constrainHeight(dateView.id, WRAP_CONTENT) - constrainWidth(dateView.id, WRAP_CONTENT) - connect( - dateView.id, - START, - PARENT_ID, - START, - context.resources.getDimensionPixelSize(R.dimen.below_clock_padding_start) + constrainHeight(R.id.date_smartspace_view, ConstraintSet.WRAP_CONTENT) + constrainWidth(R.id.date_smartspace_view, ConstraintSet.WRAP_CONTENT) + connect( + R.id.date_smartspace_view, + ConstraintSet.START, + ConstraintSet.PARENT_ID, + ConstraintSet.START, + context.resources.getDimensionPixelSize( + com.android.systemui.res.R.dimen.below_clock_padding_start ) - } - weatherView?.let { - constrainWidth(it.id, WRAP_CONTENT) - dateView?.let { dateView -> - connect(it.id, TOP, dateView.id, TOP) - connect(it.id, BOTTOM, dateView.id, BOTTOM) - connect(it.id, START, dateView.id, END, 4) - } - } + ) + constrainWidth(R.id.weather_smartspace_view, ConstraintSet.WRAP_CONTENT) + connect( + R.id.weather_smartspace_view, + ConstraintSet.TOP, + R.id.date_smartspace_view, + ConstraintSet.TOP + ) + connect( + R.id.weather_smartspace_view, + ConstraintSet.BOTTOM, + R.id.date_smartspace_view, + ConstraintSet.BOTTOM + ) + connect( + R.id.weather_smartspace_view, + ConstraintSet.START, + R.id.date_smartspace_view, + ConstraintSet.END, + 4 + ) + // migrate addSmartspaceView from KeyguardClockSwitchController - smartspaceView?.let { - constrainHeight(it.id, WRAP_CONTENT) - connect( - it.id, - START, - PARENT_ID, - START, - context.resources.getDimensionPixelSize(R.dimen.below_clock_padding_start) + constrainHeight(R.id.bc_smartspace_view, ConstraintSet.WRAP_CONTENT) + connect( + R.id.bc_smartspace_view, + ConstraintSet.START, + ConstraintSet.PARENT_ID, + ConstraintSet.START, + context.resources.getDimensionPixelSize( + com.android.systemui.res.R.dimen.below_clock_padding_start ) - connect( - it.id, - END, - PARENT_ID, - END, - context.resources.getDimensionPixelSize(R.dimen.below_clock_padding_end) + ) + connect( + R.id.bc_smartspace_view, + ConstraintSet.END, + if (keyguardClockViewModel.clockShouldBeCentered.value) ConstraintSet.PARENT_ID + else com.android.systemui.res.R.id.split_shade_guideline, + ConstraintSet.END, + context.resources.getDimensionPixelSize( + com.android.systemui.res.R.dimen.below_clock_padding_end ) - } + ) if (keyguardClockViewModel.hasCustomWeatherDataDisplay.value) { - dateView?.let { dateView -> - smartspaceView?.let { smartspaceView -> - connect(dateView.id, BOTTOM, smartspaceView.id, TOP) - } - } + clear(R.id.date_smartspace_view, ConstraintSet.TOP) + connect( + R.id.date_smartspace_view, + ConstraintSet.BOTTOM, + R.id.bc_smartspace_view, + ConstraintSet.TOP + ) } else { - dateView?.let { dateView -> - clear(dateView.id, BOTTOM) - connect(dateView.id, TOP, R.id.lockscreen_clock_view, BOTTOM) - constrainHeight(dateView.id, WRAP_CONTENT) - smartspaceView?.let { smartspaceView -> - clear(smartspaceView.id, TOP) - connect(smartspaceView.id, TOP, dateView.id, BOTTOM) - } - } + clear(R.id.date_smartspace_view, ConstraintSet.BOTTOM) + connect( + R.id.date_smartspace_view, + ConstraintSet.TOP, + com.android.systemui.res.R.id.lockscreen_clock_view, + ConstraintSet.BOTTOM + ) + connect( + R.id.bc_smartspace_view, + ConstraintSet.TOP, + R.id.date_smartspace_view, + ConstraintSet.BOTTOM + ) } + + createBarrier( + com.android.systemui.res.R.id.smart_space_barrier_bottom, + Barrier.BOTTOM, + 0, + *intArrayOf( + R.id.bc_smartspace_view, + R.id.date_smartspace_view, + R.id.weather_smartspace_view, + ) + ) } updateVisibility(constraintSet) } @@ -156,30 +205,28 @@ constructor( } } } + smartspaceView?.viewTreeObserver?.removeOnGlobalLayoutListener(smartspaceVisibilityListener) + smartspaceVisibilityListener = null } private fun updateVisibility(constraintSet: ConstraintSet) { constraintSet.apply { - weatherView?.let { - setVisibility( - it.id, - when (keyguardClockViewModel.hasCustomWeatherDataDisplay.value) { - true -> ConstraintSet.GONE - false -> - when (keyguardSmartspaceViewModel.isWeatherEnabled) { - true -> ConstraintSet.VISIBLE - false -> ConstraintSet.GONE - } - } - ) - } - dateView?.let { - setVisibility( - it.id, - if (keyguardClockViewModel.hasCustomWeatherDataDisplay.value) ConstraintSet.GONE - else ConstraintSet.VISIBLE - ) - } + setVisibility( + R.id.weather_smartspace_view, + when (keyguardClockViewModel.hasCustomWeatherDataDisplay.value) { + true -> ConstraintSet.GONE + false -> + when (keyguardSmartspaceViewModel.isWeatherEnabled) { + true -> ConstraintSet.VISIBLE + false -> ConstraintSet.GONE + } + } + ) + setVisibility( + R.id.date_smartspace_view, + if (keyguardClockViewModel.hasCustomWeatherDataDisplay.value) ConstraintSet.GONE + else ConstraintSet.VISIBLE + ) } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeClockSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeClockSection.kt deleted file mode 100644 index 19ba1aa4763a..000000000000 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeClockSection.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 androidx.constraintlayout.widget.ConstraintSet -import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor -import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel -import com.android.systemui.res.R -import com.android.systemui.statusbar.policy.SplitShadeStateController -import javax.inject.Inject - -class SplitShadeClockSection -@Inject -constructor( - clockInteractor: KeyguardClockInteractor, - keyguardClockViewModel: KeyguardClockViewModel, - context: Context, - splitShadeStateController: SplitShadeStateController, -) : ClockSection(clockInteractor, keyguardClockViewModel, context, splitShadeStateController) { - override fun applyDefaultConstraints(constraints: ConstraintSet) { - super.applyDefaultConstraints(constraints) - val largeClockEndGuideline = - if (keyguardClockViewModel.clockShouldBeCentered.value) ConstraintSet.PARENT_ID - else R.id.split_shade_guideline - constraints.apply { - connect( - R.id.lockscreen_clock_view_large, - ConstraintSet.END, - largeClockEndGuideline, - ConstraintSet.END - ) - } - } -} 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 index f20ab06bcda9..b12a8a811955 100644 --- 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 @@ -20,7 +20,6 @@ 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 @@ -31,11 +30,9 @@ 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 com.android.systemui.shared.R as sharedR import javax.inject.Inject /** Aligns media on left side for split shade, below smartspace, date, and weather. */ @@ -44,11 +41,9 @@ class SplitShadeMediaSection 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()) { @@ -85,18 +80,7 @@ constructor( constraintSet.apply { constrainWidth(mediaContainerId, MATCH_CONSTRAINT) constrainHeight(mediaContainerId, WRAP_CONTENT) - - createBarrier( - smartSpaceBarrier, - Barrier.BOTTOM, - 0, - *intArrayOf( - sharedR.id.bc_smartspace_view, - sharedR.id.date_smartspace_view, - sharedR.id.weather_smartspace_view, - ) - ) - connect(mediaContainerId, TOP, smartSpaceBarrier, BOTTOM) + connect(mediaContainerId, TOP, R.id.smart_space_barrier_bottom, BOTTOM) connect(mediaContainerId, START, PARENT_ID, START) connect(mediaContainerId, END, R.id.split_shade_guideline, END) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeSmartspaceSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeSmartspaceSection.kt deleted file mode 100644 index 8728adadd8c3..000000000000 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeSmartspaceSection.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.keyguard.ui.view.layout.sections - -import android.content.Context -import com.android.systemui.keyguard.KeyguardUnlockAnimationController -import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel -import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel -import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController -import javax.inject.Inject - -/* - * We need this class for the splitShadeBlueprint so `addViews` and `removeViews` will be called - * when switching to and from splitShade. - */ -class SplitShadeSmartspaceSection -@Inject -constructor( - keyguardClockViewModel: KeyguardClockViewModel, - keyguardSmartspaceViewModel: KeyguardSmartspaceViewModel, - context: Context, - smartspaceController: LockscreenSmartspaceController, - keyguardUnlockAnimationController: KeyguardUnlockAnimationController, -) : - SmartspaceSection( - keyguardClockViewModel, - keyguardSmartspaceViewModel, - context, - smartspaceController, - keyguardUnlockAnimationController, - ) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModel.kt index a1dd720a82f1..e8c1ab5feccc 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardSmartspaceViewModel.kt @@ -18,6 +18,7 @@ package com.android.systemui.keyguard.ui.viewmodel import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.keyguard.domain.interactor.KeyguardSmartspaceInteractor import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController import javax.inject.Inject import kotlinx.coroutines.CoroutineScope @@ -33,6 +34,7 @@ constructor( @Application applicationScope: CoroutineScope, smartspaceController: LockscreenSmartspaceController, keyguardClockViewModel: KeyguardClockViewModel, + smartspaceInteractor: KeyguardSmartspaceInteractor, ) { /** Whether the smartspace section is available in the build. */ val isSmartspaceEnabled: Boolean = smartspaceController.isEnabled() @@ -78,4 +80,7 @@ constructor( ): Boolean { return !clockIncludesCustomWeatherDisplay && isWeatherEnabled } + + /* trigger clock and smartspace constraints change when smartspace appears */ + var bcSmartspaceVisibility: StateFlow<Int> = smartspaceInteractor.bcSmartspaceVisibility } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt index a4d217f1af79..5dd37ae46ee8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt @@ -21,13 +21,17 @@ import androidx.constraintlayout.helper.widget.Layer import androidx.constraintlayout.widget.ConstraintLayout import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.keyguard.KeyguardClockSwitch.LARGE +import com.android.keyguard.KeyguardClockSwitch.SMALL import com.android.systemui.SysuiTestCase +import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel import com.android.systemui.plugins.clocks.ClockConfig import com.android.systemui.plugins.clocks.ClockController import com.android.systemui.plugins.clocks.ClockFaceController import com.android.systemui.plugins.clocks.ClockFaceLayout import com.android.systemui.util.mockito.whenever import kotlin.test.Test +import kotlinx.coroutines.flow.MutableStateFlow import org.junit.Before import org.junit.runner.RunWith import org.mockito.Mock @@ -48,30 +52,58 @@ class KeyguardClockViewBinderTest : SysuiTestCase() { @Mock private lateinit var smallClockView: View @Mock private lateinit var smallClockFaceLayout: ClockFaceLayout @Mock private lateinit var largeClockFaceLayout: ClockFaceLayout + @Mock private lateinit var clockViewModel: KeyguardClockViewModel + private val clockSize = MutableStateFlow(LARGE) + private val currentClock: MutableStateFlow<ClockController?> = MutableStateFlow(null) @Before fun setup() { MockitoAnnotations.initMocks(this) + whenever(clockViewModel.clockSize).thenReturn(clockSize) + whenever(clockViewModel.currentClock).thenReturn(currentClock) + whenever(clockViewModel.burnInLayer).thenReturn(burnInLayer) + } + + @Test + fun addClockViews_WeatherClock() { + setupWeatherClock() + KeyguardClockViewBinder.addClockViews(clock, rootView) + verify(rootView).addView(smallClockView) + verify(rootView).addView(largeClockView) } @Test fun addClockViews_nonWeatherClock() { setupNonWeatherClock() - KeyguardClockViewBinder.addClockViews(clock, rootView, burnInLayer) + KeyguardClockViewBinder.addClockViews(clock, rootView) verify(rootView).addView(smallClockView) verify(rootView).addView(largeClockView) - verify(burnInLayer).addView(smallClockView) + } + @Test + fun addClockViewsToBurnInLayer_LargeWeatherClock() { + setupWeatherClock() + clockSize.value = LARGE + KeyguardClockViewBinder.updateBurnInLayer(rootView, clockViewModel) + verify(burnInLayer).removeView(smallClockView) + verify(burnInLayer).addView(largeClockView) + } + + @Test + fun addClockViewsToBurnInLayer_LargeNonWeatherClock() { + setupNonWeatherClock() + clockSize.value = LARGE + KeyguardClockViewBinder.updateBurnInLayer(rootView, clockViewModel) + verify(burnInLayer).removeView(smallClockView) verify(burnInLayer, never()).addView(largeClockView) } @Test - fun addClockViews_WeatherClock() { - setupWeatherClock() - KeyguardClockViewBinder.addClockViews(clock, rootView, burnInLayer) - verify(rootView).addView(smallClockView) - verify(rootView).addView(largeClockView) + fun addClockViewsToBurnInLayer_SmallClock() { + setupNonWeatherClock() + clockSize.value = SMALL + KeyguardClockViewBinder.updateBurnInLayer(rootView, clockViewModel) verify(burnInLayer).addView(smallClockView) - verify(burnInLayer).addView(largeClockView) + verify(burnInLayer).removeView(largeClockView) } private fun setupWeatherClock() { @@ -99,5 +131,7 @@ class KeyguardClockViewBinderTest : SysuiTestCase() { whenever(clock.smallClock).thenReturn(smallClock) whenever(largeClock.layout).thenReturn(largeClockFaceLayout) whenever(smallClock.layout).thenReturn(smallClockFaceLayout) + whenever(clockViewModel.clock).thenReturn(clock) + currentClock.value = clock } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt index 070a0ccd1232..57b555989166 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt @@ -22,6 +22,7 @@ import android.content.res.Resources import androidx.constraintlayout.widget.ConstraintSet import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel import com.android.systemui.res.R @@ -31,6 +32,8 @@ import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat +import dagger.Lazy +import kotlinx.coroutines.flow.MutableStateFlow import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -46,6 +49,8 @@ class ClockSectionTest : SysuiTestCase() { @Mock private lateinit var keyguardClockInteractor: KeyguardClockInteractor @Mock private lateinit var keyguardClockViewModel: KeyguardClockViewModel @Mock private lateinit var splitShadeStateController: SplitShadeStateController + @Mock private lateinit var blueprintInteractor: Lazy<KeyguardBlueprintInteractor> + private val clockShouldBeCentered: MutableStateFlow<Boolean> = MutableStateFlow(true) private lateinit var underTest: ClockSection @@ -104,12 +109,15 @@ class ClockSectionTest : SysuiTestCase() { whenever(packageManager.getResourcesForApplication(anyString())).thenReturn(remoteResources) mContext.setMockPackageManager(packageManager) + whenever(keyguardClockViewModel.clockShouldBeCentered).thenReturn(clockShouldBeCentered) + underTest = ClockSection( keyguardClockInteractor, keyguardClockViewModel, mContext, splitShadeStateController, + blueprintInteractor ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSectionTest.kt index 28da957d31b0..deb3a83fcbee 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSectionTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSectionTest.kt @@ -26,6 +26,8 @@ import androidx.test.filters.SmallTest import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.keyguard.KeyguardUnlockAnimationController +import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor +import com.android.systemui.keyguard.domain.interactor.KeyguardSmartspaceInteractor import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel import com.android.systemui.res.R @@ -34,7 +36,8 @@ import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.flow.StateFlow +import dagger.Lazy +import kotlinx.coroutines.flow.MutableStateFlow import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -50,7 +53,8 @@ class SmartspaceSectionTest : SysuiTestCase() { @Mock private lateinit var keyguardSmartspaceViewModel: KeyguardSmartspaceViewModel @Mock private lateinit var lockscreenSmartspaceController: LockscreenSmartspaceController @Mock private lateinit var keyguardUnlockAnimationController: KeyguardUnlockAnimationController - @Mock private lateinit var hasCustomWeatherDataDisplay: StateFlow<Boolean> + @Mock private lateinit var keyguardSmartspaceInteractor: KeyguardSmartspaceInteractor + @Mock private lateinit var blueprintInteractor: Lazy<KeyguardBlueprintInteractor> private val smartspaceView = View(mContext).also { it.id = sharedR.id.bc_smartspace_view } private val weatherView = View(mContext).also { it.id = sharedR.id.weather_smartspace_view } @@ -58,17 +62,22 @@ class SmartspaceSectionTest : SysuiTestCase() { private lateinit var constraintLayout: ConstraintLayout private lateinit var constraintSet: ConstraintSet + private val clockShouldBeCentered = MutableStateFlow(false) + private val hasCustomWeatherDataDisplay = MutableStateFlow(false) + @Before fun setup() { MockitoAnnotations.initMocks(this) mSetFlagsRule.enableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT) underTest = SmartspaceSection( + mContext, keyguardClockViewModel, keyguardSmartspaceViewModel, - mContext, + keyguardSmartspaceInteractor, lockscreenSmartspaceController, keyguardUnlockAnimationController, + blueprintInteractor ) constraintLayout = ConstraintLayout(mContext) whenever(lockscreenSmartspaceController.buildAndConnectView(any())) @@ -78,6 +87,7 @@ class SmartspaceSectionTest : SysuiTestCase() { whenever(lockscreenSmartspaceController.buildAndConnectDateView(any())).thenReturn(dateView) whenever(keyguardClockViewModel.hasCustomWeatherDataDisplay) .thenReturn(hasCustomWeatherDataDisplay) + whenever(keyguardClockViewModel.clockShouldBeCentered).thenReturn(clockShouldBeCentered) constraintSet = ConstraintSet() } @@ -115,7 +125,7 @@ class SmartspaceSectionTest : SysuiTestCase() { fun testConstraintsWhenNotHasCustomWeatherDataDisplay() { whenever(keyguardSmartspaceViewModel.isSmartspaceEnabled).thenReturn(true) whenever(keyguardSmartspaceViewModel.isDateWeatherDecoupled).thenReturn(true) - whenever(keyguardClockViewModel.hasCustomWeatherDataDisplay.value).thenReturn(false) + hasCustomWeatherDataDisplay.value = false underTest.addViews(constraintLayout) underTest.applyConstraints(constraintSet) assertWeatherSmartspaceConstrains(constraintSet) @@ -129,7 +139,7 @@ class SmartspaceSectionTest : SysuiTestCase() { @Test fun testConstraintsWhenHasCustomWeatherDataDisplay() { - whenever(keyguardClockViewModel.hasCustomWeatherDataDisplay.value).thenReturn(true) + hasCustomWeatherDataDisplay.value = true underTest.addViews(constraintLayout) underTest.applyConstraints(constraintSet) assertWeatherSmartspaceConstrains(constraintSet) @@ -140,7 +150,7 @@ class SmartspaceSectionTest : SysuiTestCase() { @Test fun testNormalDateWeatherVisibility() { - whenever(keyguardClockViewModel.hasCustomWeatherDataDisplay.value).thenReturn(false) + hasCustomWeatherDataDisplay.value = false whenever(keyguardSmartspaceViewModel.isWeatherEnabled).thenReturn(true) underTest.addViews(constraintLayout) underTest.applyConstraints(constraintSet) @@ -153,7 +163,7 @@ class SmartspaceSectionTest : SysuiTestCase() { } @Test fun testCustomDateWeatherVisibility() { - whenever(keyguardClockViewModel.hasCustomWeatherDataDisplay.value).thenReturn(true) + hasCustomWeatherDataDisplay.value = true underTest.addViews(constraintLayout) underTest.applyConstraints(constraintSet) |