• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2024 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.statusbar.pipeline.mobile.domain.interactor
18 
19 import android.content.Context
20 import com.android.settingslib.SignalIcon
21 import com.android.settingslib.mobile.MobileMappings
22 import com.android.systemui.Flags
23 import com.android.systemui.KairosActivatable
24 import com.android.systemui.KairosBuilder
25 import com.android.systemui.dagger.SysUISingleton
26 import com.android.systemui.dagger.qualifiers.Application
27 import com.android.systemui.kairos.ExperimentalKairosApi
28 import com.android.systemui.kairos.KairosNetwork
29 import com.android.systemui.kairos.buildSpec
30 import com.android.systemui.kairos.combine
31 import com.android.systemui.kairos.map
32 import com.android.systemui.kairos.mapValues
33 import com.android.systemui.kairos.toColdConflatedFlow
34 import com.android.systemui.kairosBuilder
35 import com.android.systemui.log.table.TableLogBuffer
36 import com.android.systemui.log.table.TableLogBufferFactory
37 import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
38 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
39 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
40 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepositoryKairos
41 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Factory.Companion.MOBILE_CONNECTION_BUFFER_SIZE
42 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Factory.Companion.tableBufferLogName
43 import com.android.systemui.statusbar.pipeline.mobile.domain.model.NetworkTypeIconModel
44 import com.android.systemui.statusbar.pipeline.mobile.domain.model.SignalIconModel
45 import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
46 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
47 import com.android.systemui.statusbar.policy.data.repository.UserSetupRepository
48 import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated
49 import dagger.Provides
50 import dagger.multibindings.ElementsIntoSet
51 import javax.inject.Inject
52 import javax.inject.Provider
53 import kotlinx.coroutines.CoroutineScope
54 import kotlinx.coroutines.flow.Flow
55 import kotlinx.coroutines.flow.SharingStarted
56 import kotlinx.coroutines.flow.StateFlow
57 import kotlinx.coroutines.flow.emptyFlow
58 import kotlinx.coroutines.flow.map
59 import kotlinx.coroutines.flow.stateIn
60 
61 @ExperimentalKairosApi
62 @SysUISingleton
63 class MobileIconsInteractorKairosAdapter
64 @Inject
65 constructor(
66     private val kairosInteractor: MobileIconsInteractorKairos,
67     private val repo: MobileConnectionsRepository,
68     repoK: MobileConnectionsRepositoryKairos,
69     kairosNetwork: KairosNetwork,
70     @Application scope: CoroutineScope,
71     context: Context,
72     mobileMappingsProxy: MobileMappingsProxy,
73     private val userSetupRepo: UserSetupRepository,
74     private val logFactory: TableLogBufferFactory,
75 ) : MobileIconsInteractor, KairosBuilder by kairosBuilder() {
76 
77     private val interactorsBySubIdK = buildIncremental {
78         kairosInteractor.icons
79             .mapValues { (subId, interactor) ->
80                 buildSpec { MobileIconInteractorKairosAdapter(interactor) }
81             }
82             .applyLatestSpecForKey()
83     }
84 
85     private val interactorsBySubId =
86         interactorsBySubIdK
87             .toColdConflatedFlow(kairosNetwork)
88             .stateIn(scope, SharingStarted.Eagerly, emptyMap())
89 
90     override val defaultDataSubId: Flow<Int?>
91         get() = repo.defaultDataSubId
92 
93     override val mobileIsDefault: StateFlow<Boolean> =
94         kairosInteractor.mobileIsDefault
95             .toColdConflatedFlow(kairosNetwork)
96             .stateIn(scope, SharingStarted.WhileSubscribed(), repo.mobileIsDefault.value)
97 
98     override val filteredSubscriptions: Flow<List<SubscriptionModel>> =
99         kairosInteractor.filteredSubscriptions.toColdConflatedFlow(kairosNetwork)
100 
101     override val icons: StateFlow<List<MobileIconInteractor>> =
102         interactorsBySubIdK
103             .map { it.values.toList() }
104             .toColdConflatedFlow(kairosNetwork)
105             .stateIn(scope, SharingStarted.WhileSubscribed(), emptyList())
106 
107     override val isStackable: StateFlow<Boolean> =
108         kairosInteractor.isStackable
109             .toColdConflatedFlow(kairosNetwork)
110             .stateIn(scope, SharingStarted.WhileSubscribed(), false)
111 
112     override val activeMobileDataSubscriptionId: StateFlow<Int?>
113         get() = repo.activeMobileDataSubscriptionId
114 
115     override val activeDataConnectionHasDataEnabled: StateFlow<Boolean> =
116         kairosInteractor.activeDataConnectionHasDataEnabled
117             .toColdConflatedFlow(kairosNetwork)
118             .stateIn(scope, SharingStarted.WhileSubscribed(), false)
119 
120     override val activeDataIconInteractor: StateFlow<MobileIconInteractor?> =
121         combine(repoK.activeMobileDataSubscriptionId, interactorsBySubIdK) { subId, interactors ->
122                 interactors[subId]
123             }
124             .toColdConflatedFlow(kairosNetwork)
125             .stateIn(scope, SharingStarted.WhileSubscribed(), null)
126 
127     override val alwaysShowDataRatIcon: StateFlow<Boolean> =
128         kairosInteractor.alwaysShowDataRatIcon
129             .toColdConflatedFlow(kairosNetwork)
130             .stateIn(scope, SharingStarted.WhileSubscribed(), false)
131 
132     override val alwaysUseCdmaLevel: StateFlow<Boolean> =
133         kairosInteractor.alwaysUseCdmaLevel
134             .toColdConflatedFlow(kairosNetwork)
135             .stateIn(scope, SharingStarted.WhileSubscribed(), false)
136 
137     override val isSingleCarrier: StateFlow<Boolean> =
138         kairosInteractor.isSingleCarrier
139             .toColdConflatedFlow(kairosNetwork)
140             .stateIn(scope, SharingStarted.WhileSubscribed(), false)
141 
142     override val defaultMobileIconMapping: StateFlow<Map<String, SignalIcon.MobileIconGroup>> =
143         kairosInteractor.defaultMobileIconMapping
144             .toColdConflatedFlow(kairosNetwork)
145             .stateIn(scope, SharingStarted.WhileSubscribed(), emptyMap())
146 
147     override val defaultMobileIconGroup: StateFlow<SignalIcon.MobileIconGroup> =
148         kairosInteractor.defaultMobileIconGroup
149             .toColdConflatedFlow(kairosNetwork)
150             .stateIn(
151                 scope,
152                 SharingStarted.WhileSubscribed(),
153                 mobileMappingsProxy.getDefaultIcons(MobileMappings.Config.readConfig(context)),
154             )
155 
156     override val isDefaultConnectionFailed: StateFlow<Boolean> =
157         kairosInteractor.isDefaultConnectionFailed
158             .toColdConflatedFlow(kairosNetwork)
159             .stateIn(scope, SharingStarted.WhileSubscribed(), false)
160 
161     override val isUserSetUp: StateFlow<Boolean>
162         get() = userSetupRepo.isUserSetUp
163 
164     override val isForceHidden: Flow<Boolean> =
165         kairosInteractor.isForceHidden
166             .toColdConflatedFlow(kairosNetwork)
167             .stateIn(scope, SharingStarted.WhileSubscribed(), false)
168 
169     override val isDeviceInEmergencyCallsOnlyMode: Flow<Boolean>
170         get() = repo.isDeviceEmergencyCallCapable
171 
172     override fun getMobileConnectionInteractorForSubId(subId: Int): MobileIconInteractor =
173         object : MobileIconInteractor {
174             override val tableLogBuffer: TableLogBuffer =
175                 logFactory.getOrCreate(tableBufferLogName(subId), MOBILE_CONNECTION_BUFFER_SIZE)
176             override val activity: Flow<DataActivityModel> = latest { activity }
177             override val mobileIsDefault: Flow<Boolean> = latest { mobileIsDefault }
178             override val isDataConnected: Flow<Boolean> = latest { isDataConnected }
179             override val isInService: Flow<Boolean> = latest { isInService }
180             override val isEmergencyOnly: Flow<Boolean> = latest { isEmergencyOnly }
181             override val isDataEnabled: Flow<Boolean> = latest { isDataEnabled }
182             override val alwaysShowDataRatIcon: Flow<Boolean> = latest { alwaysShowDataRatIcon }
183             override val signalLevelIcon: Flow<SignalIconModel> = latest { signalLevelIcon }
184             override val networkTypeIconGroup: Flow<NetworkTypeIconModel> = latest {
185                 networkTypeIconGroup
186             }
187             override val showSliceAttribution: Flow<Boolean> = latest { showSliceAttribution }
188             override val isNonTerrestrial: Flow<Boolean> = latest { isNonTerrestrial }
189             override val networkName: Flow<NetworkNameModel> = latest { networkName }
190             override val carrierName: Flow<String> = latest { carrierName }
191             override val isSingleCarrier: Flow<Boolean> = latest { isSingleCarrier }
192             override val isRoaming: Flow<Boolean> = latest { isRoaming }
193             override val isForceHidden: Flow<Boolean> = latest { isForceHidden }
194             override val isAllowedDuringAirplaneMode: Flow<Boolean> = latest {
195                 isAllowedDuringAirplaneMode
196             }
197             override val carrierNetworkChangeActive: Flow<Boolean> = latest {
198                 carrierNetworkChangeActive
199             }
200 
201             private fun <T> latest(block: MobileIconInteractor.() -> Flow<T>): Flow<T> =
202                 interactorsBySubId.flatMapLatestConflated { it[subId]?.block() ?: emptyFlow() }
203         }
204 
205     @dagger.Module
206     object Module {
207         @Provides
208         @ElementsIntoSet
209         fun kairosActivatable(
210             impl: Provider<MobileIconsInteractorKairosAdapter>
211         ): Set<@JvmSuppressWildcards KairosActivatable> =
212             if (Flags.statusBarMobileIconKairos()) setOf(impl.get()) else emptySet()
213     }
214 }
215