• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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