1 /* <lambda>null2 * Copyright (C) 2022 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.ui 18 19 import com.android.systemui.CoreStartable 20 import com.android.systemui.dagger.SysUISingleton 21 import com.android.systemui.dagger.qualifiers.Application 22 import com.android.systemui.statusbar.phone.StatusBarIconController 23 import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags 24 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor 25 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel 26 import java.io.PrintWriter 27 import javax.inject.Inject 28 import kotlinx.coroutines.CoroutineScope 29 import kotlinx.coroutines.ExperimentalCoroutinesApi 30 import kotlinx.coroutines.flow.Flow 31 import kotlinx.coroutines.flow.SharingStarted 32 import kotlinx.coroutines.flow.StateFlow 33 import kotlinx.coroutines.flow.collectLatest 34 import kotlinx.coroutines.flow.distinctUntilChanged 35 import kotlinx.coroutines.flow.mapLatest 36 import kotlinx.coroutines.flow.onEach 37 import kotlinx.coroutines.flow.stateIn 38 import kotlinx.coroutines.launch 39 40 /** 41 * This class is intended to provide a context to collect on the 42 * [MobileIconsInteractor.filteredSubscriptions] data source and supply a state flow that can 43 * control [StatusBarIconController] to keep the old UI in sync with the new data source. 44 * 45 * It also provides a mechanism to create a top-level view model for each IconManager to know about 46 * the list of available mobile lines of service for which we want to show icons. 47 */ 48 @Suppress("EXPERIMENTAL_IS_NOT_ENABLED") 49 @OptIn(ExperimentalCoroutinesApi::class) 50 @SysUISingleton 51 class MobileUiAdapter 52 @Inject 53 constructor( 54 interactor: MobileIconsInteractor, 55 private val iconController: StatusBarIconController, 56 private val iconsViewModelFactory: MobileIconsViewModel.Factory, 57 private val logger: MobileViewLogger, 58 @Application private val scope: CoroutineScope, 59 private val statusBarPipelineFlags: StatusBarPipelineFlags, 60 ) : CoreStartable { 61 private val mobileSubIds: Flow<List<Int>> = 62 interactor.filteredSubscriptions.mapLatest { subscriptions -> 63 subscriptions.map { subscriptionModel -> subscriptionModel.subscriptionId } 64 } 65 66 /** 67 * We expose the list of tracked subscriptions as a flow of a list of ints, where each int is 68 * the subscriptionId of the relevant subscriptions. These act as a key into the layouts which 69 * house the mobile infos. 70 * 71 * NOTE: this should go away as the view presenter learns more about this data pipeline 72 */ 73 private val mobileSubIdsState: StateFlow<List<Int>> = 74 mobileSubIds 75 .distinctUntilChanged() 76 .onEach { logger.logUiAdapterSubIdsUpdated(it) } 77 .stateIn(scope, SharingStarted.WhileSubscribed(), listOf()) 78 79 /** In order to keep the logs tame, we will reuse the same top-level mobile icons view model */ 80 val mobileIconsViewModel = iconsViewModelFactory.create(mobileSubIdsState) 81 82 private var isCollecting: Boolean = false 83 private var lastValue: List<Int>? = null 84 85 override fun start() { 86 // Only notify the icon controller if we want to *render* the new icons. 87 // Note that this flow may still run if 88 // [statusBarPipelineFlags.runNewMobileIconsBackend] is true because we may want to 89 // get the logging data without rendering. 90 if (statusBarPipelineFlags.useNewMobileIcons()) { 91 scope.launch { 92 isCollecting = true 93 mobileSubIds.collectLatest { 94 logger.logUiAdapterSubIdsSentToIconController(it) 95 lastValue = it 96 iconController.setNewMobileIconSubIds(it) 97 } 98 } 99 } 100 } 101 102 override fun dump(pw: PrintWriter, args: Array<out String>) { 103 pw.println("isCollecting=$isCollecting") 104 pw.println("Last values sent to icon controller: $lastValue") 105 } 106 } 107