1 /*
2  * Copyright 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 androidx.camera.camera2.pipe.compat
18 
19 import android.hardware.camera2.CameraDevice
20 import android.os.Build
21 import androidx.annotation.GuardedBy
22 import androidx.camera.camera2.pipe.AudioRestrictionMode
23 import androidx.camera.camera2.pipe.AudioRestrictionMode.Companion.AUDIO_RESTRICTION_NONE
24 import androidx.camera.camera2.pipe.AudioRestrictionMode.Companion.AUDIO_RESTRICTION_VIBRATION
25 import androidx.camera.camera2.pipe.AudioRestrictionMode.Companion.AUDIO_RESTRICTION_VIBRATION_SOUND
26 import androidx.camera.camera2.pipe.CameraGraph
27 import javax.inject.Inject
28 import javax.inject.Singleton
29 
30 /**
31  * AudioRestrictionController keeps the global audio restriction mode and audio restriction mode on
32  * each CameraGraph, and computes the final audio restriction mode based on the settings.
33  */
34 public interface AudioRestrictionController {
35     /** Public global audio restriction mode across all CameraGraph instances. */
36     public var globalAudioRestrictionMode: AudioRestrictionMode
37 
38     /** Update the audio restriction mode of the given CameraGraph. */
updateCameraGraphAudioRestrictionModenull39     public fun updateCameraGraphAudioRestrictionMode(
40         cameraGraph: CameraGraph,
41         mode: AudioRestrictionMode
42     )
43 
44     /** Removes the CameraGraph from the local CameraGraph to audio restriction mode mapping. */
45     public fun removeCameraGraph(cameraGraph: CameraGraph)
46 
47     /** Adds the listener to the controller's stored collection of listeners. */
48     public fun addListener(listener: Listener)
49 
50     /** Removes the listener to the controller's stored collection of listeners. */
51     public fun removeListener(listener: Listener)
52 
53     /**
54      * [CameraDeviceWrapper] extends the [Listener]. When audio restriction mode changes, the
55      * listener's update method would be invoked.
56      */
57     public interface Listener {
58         /** @see CameraDevice.getCameraAudioRestriction */
59         public fun onCameraAudioRestrictionUpdated(mode: AudioRestrictionMode)
60     }
61 }
62 
63 @Singleton
64 public class AudioRestrictionControllerImpl @Inject constructor() : AudioRestrictionController {
65     private val lock = Any()
66     override var globalAudioRestrictionMode: AudioRestrictionMode = AUDIO_RESTRICTION_NONE
<lambda>null67         get() = synchronized(lock) { field }
68         set(value: AudioRestrictionMode) {
<lambda>null69             synchronized(lock) {
70                 val previousMode = computeAudioRestrictionMode()
71                 field = value
72                 updateListenersMode(previousMode)
73             }
74         }
75 
76     private val audioRestrictionModeMap = mutableMapOf<CameraGraph, AudioRestrictionMode>()
77     private val activeListeners = mutableSetOf<AudioRestrictionController.Listener>()
78 
updateCameraGraphAudioRestrictionModenull79     override fun updateCameraGraphAudioRestrictionMode(
80         cameraGraph: CameraGraph,
81         mode: AudioRestrictionMode
82     ) {
83         synchronized(lock) {
84             val previousMode = computeAudioRestrictionMode()
85             audioRestrictionModeMap[cameraGraph] = mode
86             updateListenersMode(previousMode)
87         }
88     }
89 
removeCameraGraphnull90     override fun removeCameraGraph(cameraGraph: CameraGraph) {
91         synchronized(lock) {
92             val previousMode = computeAudioRestrictionMode()
93             audioRestrictionModeMap.remove(cameraGraph)
94             updateListenersMode(previousMode)
95         }
96     }
97 
98     @GuardedBy("lock")
computeAudioRestrictionModenull99     private fun computeAudioRestrictionMode(): AudioRestrictionMode {
100         if (
101             audioRestrictionModeMap.containsValue(AUDIO_RESTRICTION_VIBRATION_SOUND) ||
102                 globalAudioRestrictionMode == AUDIO_RESTRICTION_VIBRATION_SOUND
103         ) {
104             return AUDIO_RESTRICTION_VIBRATION_SOUND
105         }
106         if (
107             audioRestrictionModeMap.containsValue(AUDIO_RESTRICTION_VIBRATION) ||
108                 globalAudioRestrictionMode == AUDIO_RESTRICTION_VIBRATION
109         ) {
110             return AUDIO_RESTRICTION_VIBRATION
111         }
112         return AUDIO_RESTRICTION_NONE
113     }
114 
addListenernull115     override fun addListener(listener: AudioRestrictionController.Listener) {
116         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
117             return
118         }
119         synchronized(lock) {
120             activeListeners.add(listener)
121             val mode = computeAudioRestrictionMode()
122             listener.onCameraAudioRestrictionUpdated(mode)
123         }
124     }
125 
removeListenernull126     override fun removeListener(listener: AudioRestrictionController.Listener) {
127         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
128             return
129         }
130         synchronized(lock) { activeListeners.remove(listener) }
131     }
132 
133     @GuardedBy("lock")
updateListenersModenull134     private fun updateListenersMode(previousMode: AudioRestrictionMode? = null) {
135         val mode = computeAudioRestrictionMode()
136         if (previousMode != null && mode != previousMode) {
137             for (listener in activeListeners) {
138                 listener.onCameraAudioRestrictionUpdated(mode)
139             }
140         }
141     }
142 }
143