1 /* <lambda>null2 * 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 18 @file:OptIn(ExperimentalCoroutinesApi::class) 19 20 package com.android.systemui.keyguard.domain.interactor 21 22 import android.content.Context 23 import com.android.systemui.CoreStartable 24 import com.android.systemui.biometrics.domain.interactor.FingerprintPropertyInteractor 25 import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor 26 import com.android.systemui.dagger.SysUISingleton 27 import com.android.systemui.dagger.qualifiers.Application 28 import com.android.systemui.keyguard.data.repository.KeyguardBlueprintRepository 29 import com.android.systemui.keyguard.shared.ComposeLockscreen 30 import com.android.systemui.keyguard.shared.model.KeyguardBlueprint 31 import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint 32 import com.android.systemui.keyguard.ui.view.layout.blueprints.SplitShadeKeyguardBlueprint 33 import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config 34 import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Type 35 import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection 36 import com.android.systemui.keyguard.ui.view.layout.sections.SmartspaceSection 37 import com.android.systemui.shade.domain.interactor.ShadeInteractor 38 import com.android.systemui.shade.shared.model.ShadeMode 39 import javax.inject.Inject 40 import kotlinx.coroutines.CoroutineScope 41 import kotlinx.coroutines.ExperimentalCoroutinesApi 42 import kotlinx.coroutines.flow.StateFlow 43 import kotlinx.coroutines.flow.collect 44 import kotlinx.coroutines.flow.filter 45 import kotlinx.coroutines.flow.map 46 import kotlinx.coroutines.launch 47 48 @SysUISingleton 49 class KeyguardBlueprintInteractor 50 @Inject 51 constructor( 52 private val keyguardBlueprintRepository: KeyguardBlueprintRepository, 53 @Application private val applicationScope: CoroutineScope, 54 private val context: Context, 55 private val shadeInteractor: ShadeInteractor, 56 private val clockInteractor: KeyguardClockInteractor, 57 private val configurationInteractor: ConfigurationInteractor, 58 private val fingerprintPropertyInteractor: FingerprintPropertyInteractor, 59 private val smartspaceSection: SmartspaceSection, 60 private val clockSection: ClockSection, 61 ) : CoreStartable { 62 /** The current blueprint for the lockscreen. */ 63 val blueprint: StateFlow<KeyguardBlueprint> = keyguardBlueprintRepository.blueprint 64 65 /** 66 * Triggered when the blueprint isn't changed, but the ConstraintSet should be rebuilt and 67 * optionally a transition should be fired to move to the rebuilt ConstraintSet. 68 */ 69 val refreshTransition = keyguardBlueprintRepository.refreshTransition 70 71 /** Current BlueprintId */ 72 val blueprintId = 73 shadeInteractor.shadeMode.map { shadeMode -> 74 val useSplitShade = shadeMode == ShadeMode.Split && !ComposeLockscreen.isEnabled 75 when { 76 useSplitShade -> SplitShadeKeyguardBlueprint.ID 77 else -> DefaultKeyguardBlueprint.DEFAULT 78 } 79 } 80 81 override fun start() { 82 applicationScope.launch { blueprintId.collect { transitionToBlueprint(it) } } 83 applicationScope.launch { 84 fingerprintPropertyInteractor.propertiesInitialized 85 .filter { it } 86 .collect { refreshBlueprint() } 87 } 88 applicationScope.launch { 89 val refreshConfig = 90 Config( 91 Type.NoTransition, 92 rebuildSections = listOf(smartspaceSection), 93 ) 94 configurationInteractor.onAnyConfigurationChange.collect { 95 refreshBlueprint(refreshConfig) 96 } 97 } 98 } 99 100 /** 101 * Transitions to a blueprint, or refreshes it if already applied. 102 * 103 * @param blueprintId 104 * @return whether the transition has succeeded. 105 */ 106 fun transitionOrRefreshBlueprint(blueprintId: String): Boolean { 107 if (blueprintId == blueprint.value.id) { 108 refreshBlueprint() 109 return true 110 } 111 112 return keyguardBlueprintRepository.applyBlueprint(blueprintId) 113 } 114 115 /** 116 * Transitions to a blueprint. 117 * 118 * @param blueprintId 119 * @return whether the transition has succeeded. 120 */ 121 fun transitionToBlueprint(blueprintId: String): Boolean { 122 return keyguardBlueprintRepository.applyBlueprint(blueprintId) 123 } 124 125 /** Emits a value to refresh the blueprint with the appropriate transition. */ 126 fun refreshBlueprint(type: Type = Type.NoTransition) = refreshBlueprint(Config(type)) 127 128 /** Emits a value to refresh the blueprint with the appropriate transition. */ 129 fun refreshBlueprint(config: Config) = keyguardBlueprintRepository.refreshBlueprint(config) 130 131 fun getCurrentBlueprint(): KeyguardBlueprint { 132 return keyguardBlueprintRepository.blueprint.value 133 } 134 135 companion object { 136 private val TAG = "KeyguardBlueprintInteractor" 137 } 138 } 139