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.qs.tiles.base.viewmodel 18 19 import com.android.systemui.dagger.qualifiers.Background 20 import com.android.systemui.plugins.FalsingManager 21 import com.android.systemui.qs.pipeline.shared.TileSpec 22 import com.android.systemui.qs.tiles.base.analytics.QSTileAnalytics 23 import com.android.systemui.qs.tiles.base.interactor.DisabledByPolicyInteractor 24 import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor 25 import com.android.systemui.qs.tiles.base.interactor.QSTileDataToStateMapper 26 import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor 27 import com.android.systemui.qs.tiles.base.logging.QSTileLogger 28 import com.android.systemui.qs.tiles.impl.custom.di.CustomTileComponent 29 import com.android.systemui.qs.tiles.impl.custom.di.QSTileConfigModule 30 import com.android.systemui.qs.tiles.impl.custom.domain.entity.CustomTileDataModel 31 import com.android.systemui.qs.tiles.impl.di.QSTileComponent 32 import com.android.systemui.qs.tiles.viewmodel.QSTileConfigProvider 33 import com.android.systemui.qs.tiles.viewmodel.QSTileState 34 import com.android.systemui.qs.tiles.viewmodel.QSTileViewModel 35 import com.android.systemui.user.data.repository.UserRepository 36 import com.android.systemui.util.time.SystemClock 37 import javax.inject.Inject 38 import kotlinx.coroutines.CoroutineDispatcher 39 40 /** 41 * Factory to create an appropriate [QSTileViewModelImpl] instance depending on your circumstances. 42 * 43 * @see [QSTileViewModelFactory.Component] 44 * @see [QSTileViewModelFactory.Static] 45 */ 46 sealed interface QSTileViewModelFactory<T> { 47 48 /** 49 * This factory allows you to pass an instance of [QSTileComponent] to a view model effectively 50 * binding them together. This achieves a DI scope that lives along the instance of 51 * [QSTileViewModelImpl]. 52 */ 53 class Component 54 @Inject 55 constructor( 56 private val disabledByPolicyInteractor: DisabledByPolicyInteractor, 57 private val userRepository: UserRepository, 58 private val falsingManager: FalsingManager, 59 private val qsTileAnalytics: QSTileAnalytics, 60 private val qsTileLogger: QSTileLogger, 61 private val qsTileConfigProvider: QSTileConfigProvider, 62 private val systemClock: SystemClock, 63 @Background private val backgroundDispatcher: CoroutineDispatcher, 64 private val customTileComponentBuilder: CustomTileComponent.Builder, 65 ) : QSTileViewModelFactory<CustomTileDataModel> { 66 67 /** 68 * Creates [QSTileViewModelImpl] based on the interactors obtained from [QSTileComponent]. 69 * Reference of that [QSTileComponent] is then stored along the view model. 70 */ createnull71 fun create( 72 tileSpec: TileSpec, 73 ): QSTileViewModel { 74 val config = qsTileConfigProvider.getConfig(tileSpec.spec) 75 val component = 76 customTileComponentBuilder.qsTileConfigModule(QSTileConfigModule(config)).build() 77 return QSTileViewModelImpl( 78 config, 79 component::userActionInteractor, 80 component::dataInteractor, 81 component::dataToStateMapper, 82 disabledByPolicyInteractor, 83 userRepository, 84 falsingManager, 85 qsTileAnalytics, 86 qsTileLogger, 87 systemClock, 88 backgroundDispatcher, 89 component.coroutineScope(), 90 ) 91 } 92 } 93 94 /** 95 * This factory passes by necessary implementations to the [QSTileViewModelImpl]. This is a 96 * default choice for most of the tiles. 97 */ 98 class Static<T> 99 @Inject 100 constructor( 101 private val disabledByPolicyInteractor: DisabledByPolicyInteractor, 102 private val userRepository: UserRepository, 103 private val falsingManager: FalsingManager, 104 private val qsTileAnalytics: QSTileAnalytics, 105 private val qsTileLogger: QSTileLogger, 106 private val qsTileConfigProvider: QSTileConfigProvider, 107 private val systemClock: SystemClock, 108 @Background private val backgroundDispatcher: CoroutineDispatcher, 109 private val coroutineScopeFactory: QSTileCoroutineScopeFactory, 110 ) : QSTileViewModelFactory<T> { 111 112 /** 113 * @param tileSpec of the created tile. 114 * @param userActionInteractor encapsulates user input processing logic. Use it to start 115 * activities, show dialogs or otherwise update the tile state. 116 * @param tileDataInteractor provides [DATA_TYPE] and its availability. 117 * @param mapper maps [DATA_TYPE] to the [QSTileState] that is then displayed by the View 118 * layer. It's called in [backgroundDispatcher], so it's safe to perform long running 119 * operations there. 120 */ createnull121 fun create( 122 tileSpec: TileSpec, 123 userActionInteractor: QSTileUserActionInteractor<T>, 124 tileDataInteractor: QSTileDataInteractor<T>, 125 mapper: QSTileDataToStateMapper<T>, 126 ): QSTileViewModelImpl<T> = 127 QSTileViewModelImpl( 128 qsTileConfigProvider.getConfig(tileSpec.spec), 129 { userActionInteractor }, <lambda>null130 { tileDataInteractor }, <lambda>null131 { mapper }, 132 disabledByPolicyInteractor, 133 userRepository, 134 falsingManager, 135 qsTileAnalytics, 136 qsTileLogger, 137 systemClock, 138 backgroundDispatcher, 139 coroutineScopeFactory.create(), 140 ) 141 } 142 } 143