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.shade.data.repository
18 
19 import android.content.IntentFilter
20 import android.os.UserHandle
21 import android.safetycenter.SafetyCenterManager
22 import com.android.systemui.broadcast.BroadcastDispatcher
23 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
24 import com.android.systemui.dagger.SysUISingleton
25 import com.android.systemui.dagger.qualifiers.Application
26 import com.android.systemui.dagger.qualifiers.Background
27 import com.android.systemui.privacy.PrivacyConfig
28 import com.android.systemui.privacy.PrivacyItem
29 import com.android.systemui.privacy.PrivacyItemController
30 import javax.inject.Inject
31 import kotlinx.coroutines.CoroutineDispatcher
32 import kotlinx.coroutines.CoroutineScope
33 import kotlinx.coroutines.channels.awaitClose
34 import kotlinx.coroutines.flow.SharingStarted
35 import kotlinx.coroutines.flow.StateFlow
36 import kotlinx.coroutines.flow.flowOn
37 import kotlinx.coroutines.flow.onStart
38 import kotlinx.coroutines.flow.stateIn
39 
40 interface PrivacyChipRepository {
41     /** Whether or not the Safety Center is enabled. */
42     val isSafetyCenterEnabled: StateFlow<Boolean>
43 
44     /** The list of PrivacyItems to be displayed by the privacy chip. */
45     val privacyItems: StateFlow<List<PrivacyItem>>
46 
47     /** Whether or not mic & camera indicators are enabled in the device privacy config. */
48     val isMicCameraIndicationEnabled: StateFlow<Boolean>
49 
50     /** Whether or not location indicators are enabled in the device privacy config. */
51     val isLocationIndicationEnabled: StateFlow<Boolean>
52 }
53 
54 @SysUISingleton
55 class PrivacyChipRepositoryImpl
56 @Inject
57 constructor(
58     @Application applicationScope: CoroutineScope,
59     private val privacyConfig: PrivacyConfig,
60     private val privacyItemController: PrivacyItemController,
61     @Background private val backgroundDispatcher: CoroutineDispatcher,
62     broadcastDispatcher: BroadcastDispatcher,
63     private val safetyCenterManager: SafetyCenterManager,
64 ) : PrivacyChipRepository {
65     override val isSafetyCenterEnabled: StateFlow<Boolean> =
66         broadcastDispatcher
67             .broadcastFlow(
68                 filter =
<lambda>null69                     IntentFilter().apply {
70                         addAction(SafetyCenterManager.ACTION_SAFETY_CENTER_ENABLED_CHANGED)
71                     },
72                 user = UserHandle.SYSTEM,
_null73                 map = { _, _ -> safetyCenterManager.isSafetyCenterEnabled }
74             )
<lambda>null75             .onStart { emit(safetyCenterManager.isSafetyCenterEnabled) }
76             .flowOn(backgroundDispatcher)
77             .stateIn(
78                 scope = applicationScope,
79                 started = SharingStarted.WhileSubscribed(),
80                 initialValue = false,
81             )
82 
83     override val privacyItems: StateFlow<List<PrivacyItem>> =
<lambda>null84         conflatedCallbackFlow {
85                 val callback =
86                     object : PrivacyItemController.Callback {
87                         override fun onPrivacyItemsChanged(privacyItems: List<PrivacyItem>) {
88                             trySend(privacyItems)
89                         }
90                     }
91                 privacyItemController.addCallback(callback)
92                 awaitClose { privacyItemController.removeCallback(callback) }
93             }
94             .stateIn(
95                 scope = applicationScope,
96                 started = SharingStarted.Eagerly,
97                 initialValue = emptyList(),
98             )
99 
100     override val isMicCameraIndicationEnabled: StateFlow<Boolean> =
<lambda>null101         conflatedCallbackFlow {
102                 val callback =
103                     object : PrivacyConfig.Callback {
104                         override fun onFlagMicCameraChanged(flag: Boolean) {
105                             trySend(flag)
106                         }
107                     }
108                 privacyConfig.addCallback(callback)
109                 awaitClose { privacyConfig.removeCallback(callback) }
110             }
111             .stateIn(
112                 scope = applicationScope,
113                 started = SharingStarted.Eagerly,
114                 initialValue = privacyItemController.micCameraAvailable,
115             )
116 
117     override val isLocationIndicationEnabled: StateFlow<Boolean> =
<lambda>null118         conflatedCallbackFlow {
119                 val callback =
120                     object : PrivacyConfig.Callback {
121                         override fun onFlagLocationChanged(flag: Boolean) {
122                             trySend(flag)
123                         }
124                     }
125                 privacyConfig.addCallback(callback)
126                 awaitClose { privacyConfig.removeCallback(callback) }
127             }
128             .stateIn(
129                 scope = applicationScope,
130                 started = SharingStarted.Eagerly,
131                 initialValue = privacyItemController.locationAvailable,
132             )
133 }
134