1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.keyguard.ui.view.layout.sections 18 19 import android.content.Context 20 import android.view.View 21 import android.view.ViewGroup 22 import android.view.ViewTreeObserver.OnGlobalLayoutListener 23 import androidx.constraintlayout.widget.Barrier 24 import androidx.constraintlayout.widget.ConstraintLayout 25 import androidx.constraintlayout.widget.ConstraintSet 26 import com.android.systemui.dagger.SysUISingleton 27 import com.android.systemui.keyguard.KeyguardUnlockAnimationController 28 import com.android.systemui.keyguard.MigrateClocksToBlueprint 29 import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor 30 import com.android.systemui.keyguard.domain.interactor.KeyguardSmartspaceInteractor 31 import com.android.systemui.keyguard.shared.model.KeyguardSection 32 import com.android.systemui.keyguard.ui.binder.KeyguardSmartspaceViewBinder 33 import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel 34 import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel 35 import com.android.systemui.res.R as R 36 import com.android.systemui.shared.R as sharedR 37 import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController 38 import dagger.Lazy 39 import javax.inject.Inject 40 41 @SysUISingleton 42 open class SmartspaceSection 43 @Inject 44 constructor( 45 val context: Context, 46 val keyguardClockViewModel: KeyguardClockViewModel, 47 val keyguardSmartspaceViewModel: KeyguardSmartspaceViewModel, 48 private val keyguardSmartspaceInteractor: KeyguardSmartspaceInteractor, 49 val smartspaceController: LockscreenSmartspaceController, 50 val keyguardUnlockAnimationController: KeyguardUnlockAnimationController, 51 private val blueprintInteractor: Lazy<KeyguardBlueprintInteractor>, 52 ) : KeyguardSection() { 53 private var smartspaceView: View? = null 54 private var weatherView: View? = null 55 private var dateWeatherView: ViewGroup? = null 56 57 private var smartspaceVisibilityListener: OnGlobalLayoutListener? = null 58 private var pastVisibility: Int = -1 59 onRebuildBeginnull60 override fun onRebuildBegin() { 61 smartspaceController.suppressDisconnects = true 62 } 63 onRebuildEndnull64 override fun onRebuildEnd() { 65 smartspaceController.suppressDisconnects = false 66 } 67 addViewsnull68 override fun addViews(constraintLayout: ConstraintLayout) { 69 if (!MigrateClocksToBlueprint.isEnabled) return 70 if (!keyguardSmartspaceViewModel.isSmartspaceEnabled) return 71 smartspaceView = smartspaceController.buildAndConnectView(constraintLayout) 72 weatherView = smartspaceController.buildAndConnectWeatherView(constraintLayout) 73 dateWeatherView = 74 smartspaceController.buildAndConnectDateView(constraintLayout) as ViewGroup 75 pastVisibility = smartspaceView?.visibility ?: View.GONE 76 constraintLayout.addView(smartspaceView) 77 if (keyguardSmartspaceViewModel.isDateWeatherDecoupled) { 78 constraintLayout.addView(dateWeatherView) 79 // Place weather right after the date, before the extras (alarm and dnd) 80 val index = if (dateWeatherView?.childCount == 0) 0 else 1 81 dateWeatherView?.addView(weatherView, index) 82 } 83 keyguardUnlockAnimationController.lockscreenSmartspace = smartspaceView 84 smartspaceVisibilityListener = OnGlobalLayoutListener { 85 smartspaceView?.let { 86 val newVisibility = it.visibility 87 if (pastVisibility != newVisibility) { 88 keyguardSmartspaceInteractor.setBcSmartspaceVisibility(newVisibility) 89 pastVisibility = newVisibility 90 } 91 } 92 } 93 smartspaceView?.viewTreeObserver?.addOnGlobalLayoutListener(smartspaceVisibilityListener) 94 } 95 bindDatanull96 override fun bindData(constraintLayout: ConstraintLayout) { 97 if (!MigrateClocksToBlueprint.isEnabled) return 98 if (!keyguardSmartspaceViewModel.isSmartspaceEnabled) return 99 KeyguardSmartspaceViewBinder.bind( 100 constraintLayout, 101 keyguardClockViewModel, 102 keyguardSmartspaceViewModel, 103 blueprintInteractor.get(), 104 ) 105 } 106 applyConstraintsnull107 override fun applyConstraints(constraintSet: ConstraintSet) { 108 if (!MigrateClocksToBlueprint.isEnabled) return 109 if (!keyguardSmartspaceViewModel.isSmartspaceEnabled) return 110 val horizontalPaddingStart = KeyguardSmartspaceViewModel.getSmartspaceStartMargin(context) 111 val horizontalPaddingEnd = KeyguardSmartspaceViewModel.getSmartspaceEndMargin(context) 112 constraintSet.apply { 113 // migrate addDateWeatherView, addWeatherView from KeyguardClockSwitchController 114 constrainHeight(sharedR.id.date_smartspace_view, ConstraintSet.WRAP_CONTENT) 115 constrainWidth(sharedR.id.date_smartspace_view, ConstraintSet.WRAP_CONTENT) 116 connect( 117 sharedR.id.date_smartspace_view, 118 ConstraintSet.START, 119 ConstraintSet.PARENT_ID, 120 ConstraintSet.START, 121 horizontalPaddingStart 122 ) 123 124 // migrate addSmartspaceView from KeyguardClockSwitchController 125 constrainHeight(sharedR.id.bc_smartspace_view, ConstraintSet.WRAP_CONTENT) 126 connect( 127 sharedR.id.bc_smartspace_view, 128 ConstraintSet.START, 129 ConstraintSet.PARENT_ID, 130 ConstraintSet.START, 131 horizontalPaddingStart 132 ) 133 connect( 134 sharedR.id.bc_smartspace_view, 135 ConstraintSet.END, 136 if (keyguardClockViewModel.clockShouldBeCentered.value) ConstraintSet.PARENT_ID 137 else R.id.split_shade_guideline, 138 ConstraintSet.END, 139 horizontalPaddingEnd 140 ) 141 142 if (keyguardClockViewModel.hasCustomWeatherDataDisplay.value) { 143 clear(sharedR.id.date_smartspace_view, ConstraintSet.TOP) 144 connect( 145 sharedR.id.date_smartspace_view, 146 ConstraintSet.BOTTOM, 147 sharedR.id.bc_smartspace_view, 148 ConstraintSet.TOP 149 ) 150 } else { 151 clear(sharedR.id.date_smartspace_view, ConstraintSet.BOTTOM) 152 connect( 153 sharedR.id.date_smartspace_view, 154 ConstraintSet.TOP, 155 R.id.lockscreen_clock_view, 156 ConstraintSet.BOTTOM 157 ) 158 connect( 159 sharedR.id.bc_smartspace_view, 160 ConstraintSet.TOP, 161 sharedR.id.date_smartspace_view, 162 ConstraintSet.BOTTOM 163 ) 164 } 165 166 createBarrier( 167 R.id.smart_space_barrier_bottom, 168 Barrier.BOTTOM, 169 0, 170 *intArrayOf( 171 sharedR.id.bc_smartspace_view, 172 sharedR.id.date_smartspace_view, 173 ) 174 ) 175 } 176 updateVisibility(constraintSet) 177 } 178 removeViewsnull179 override fun removeViews(constraintLayout: ConstraintLayout) { 180 if (!MigrateClocksToBlueprint.isEnabled) return 181 if (!keyguardSmartspaceViewModel.isSmartspaceEnabled) return 182 listOf(smartspaceView, dateWeatherView).forEach { 183 it?.let { 184 if (it.parent == constraintLayout) { 185 constraintLayout.removeView(it) 186 } 187 } 188 } 189 smartspaceView?.viewTreeObserver?.removeOnGlobalLayoutListener(smartspaceVisibilityListener) 190 smartspaceVisibilityListener = null 191 } 192 updateVisibilitynull193 private fun updateVisibility(constraintSet: ConstraintSet) { 194 // This may update the visibility of the smartspace views 195 smartspaceController.requestSmartspaceUpdate() 196 197 constraintSet.apply { 198 val weatherVisibility = 199 when (keyguardSmartspaceViewModel.isWeatherVisible.value) { 200 true -> ConstraintSet.VISIBLE 201 false -> ConstraintSet.GONE 202 } 203 setVisibility(sharedR.id.weather_smartspace_view, weatherVisibility) 204 setAlpha( 205 sharedR.id.weather_smartspace_view, 206 if (weatherVisibility == View.VISIBLE) 1f else 0f 207 ) 208 val dateVisibility = 209 if (keyguardClockViewModel.hasCustomWeatherDataDisplay.value) ConstraintSet.GONE 210 else ConstraintSet.VISIBLE 211 setVisibility(sharedR.id.date_smartspace_view, dateVisibility) 212 setAlpha( 213 sharedR.id.date_smartspace_view, 214 if (dateVisibility == ConstraintSet.VISIBLE) 1f else 0f 215 ) 216 } 217 } 218 } 219