• 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.camera.data.repository
18 
19 import android.hardware.SensorPrivacyManager
20 import android.hardware.SensorPrivacyManager.Sensors.CAMERA
21 import android.os.UserHandle
22 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
23 import com.android.systemui.dagger.SysUISingleton
24 import com.android.systemui.dagger.qualifiers.Application
25 import com.android.systemui.dagger.qualifiers.Background
26 import javax.inject.Inject
27 import kotlin.coroutines.CoroutineContext
28 import kotlinx.coroutines.CoroutineScope
29 import kotlinx.coroutines.channels.awaitClose
30 import kotlinx.coroutines.flow.Flow
31 import kotlinx.coroutines.flow.SharingStarted
32 import kotlinx.coroutines.flow.StateFlow
33 import kotlinx.coroutines.flow.distinctUntilChanged
34 import kotlinx.coroutines.flow.flowOn
35 import kotlinx.coroutines.flow.onStart
36 import kotlinx.coroutines.flow.stateIn
37 
38 interface CameraSensorPrivacyRepository {
39     /** Tracks whether camera sensor privacy is enabled. */
40     fun isEnabled(userHandle: UserHandle): StateFlow<Boolean>
41 }
42 
43 @SysUISingleton
44 class CameraSensorPrivacyRepositoryImpl
45 @Inject
46 constructor(
47     @Background private val bgCoroutineContext: CoroutineContext,
48     @Application private val scope: CoroutineScope,
49     private val privacyManager: SensorPrivacyManager,
50 ) : CameraSensorPrivacyRepository {
51     private val userMap = mutableMapOf<Int, StateFlow<Boolean>>()
52 
53     /** Whether camera sensor privacy is enabled */
isEnablednull54     override fun isEnabled(userHandle: UserHandle): StateFlow<Boolean> =
55         userMap.getOrPut(userHandle.identifier) {
56             privacyManager
57                 .isEnabled(userHandle)
58                 .flowOn(bgCoroutineContext)
59                 .stateIn(scope, SharingStarted.WhileSubscribed(), false)
60         }
61 }
62 
SensorPrivacyManagernull63 fun SensorPrivacyManager.isEnabled(userHandle: UserHandle): Flow<Boolean> {
64     return conflatedCallbackFlow {
65             val privacyCallback =
66                 SensorPrivacyManager.OnSensorPrivacyChangedListener { sensor, enabled ->
67                     if (sensor == CAMERA) {
68                         trySend(enabled)
69                     }
70                 }
71             addSensorPrivacyListener(CAMERA, userHandle.identifier, privacyCallback)
72             awaitClose { removeSensorPrivacyListener(privacyCallback) }
73         }
74         .onStart { emit(isSensorPrivacyEnabled(SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE, CAMERA)) }
75         .distinctUntilChanged()
76 }
77