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.settingslib.notification.domain.interactor
18 
19 import android.app.NotificationManager
20 import android.media.AudioManager
21 import android.provider.Settings
22 import android.service.notification.ZenModeConfig
23 import com.android.settingslib.notification.data.repository.ZenModeRepository
24 import com.android.settingslib.volume.shared.model.AudioStream
25 import kotlinx.coroutines.flow.Flow
26 import kotlinx.coroutines.flow.StateFlow
27 import kotlinx.coroutines.flow.combine
28 import kotlinx.coroutines.flow.filterNotNull
29 import kotlinx.coroutines.flow.map
30 
31 /** Determines notification sounds state and limitations. */
32 class NotificationsSoundPolicyInteractor(private val repository: ZenModeRepository) {
33 
34     /** @see NotificationManager.getNotificationPolicy */
35     private val notificationPolicy: StateFlow<NotificationManager.Policy?>
36         get() = repository.consolidatedNotificationPolicy
37 
38     /** @see NotificationManager.getZenMode */
39     val zenMode: StateFlow<Int?>
40         get() = repository.globalZenMode
41 
42     /** Checks if [notificationPolicy] allows alarms. */
43     val areAlarmsAllowed: Flow<Boolean?> = notificationPolicy.map { it?.allowAlarms() }
44 
45     /** Checks if [notificationPolicy] allows media. */
46     val isMediaAllowed: Flow<Boolean?> = notificationPolicy.map { it?.allowMedia() }
47 
48     /** Checks if [notificationPolicy] allows system sounds. */
49     val isSystemAllowed: Flow<Boolean?> = notificationPolicy.map { it?.allowSystem() }
50 
51     /** Checks if [notificationPolicy] allows ringer. */
52     val isRingerAllowed: Flow<Boolean?> =
53         notificationPolicy.map { policy ->
54             policy ?: return@map null
55             !ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(policy)
56         }
57 
58     /** Checks if the [stream] is muted by either [zenMode] or [notificationPolicy]. */
59     fun isZenMuted(stream: AudioStream): Flow<Boolean> {
60         return combine(
61             zenMode.filterNotNull(),
62             areAlarmsAllowed.filterNotNull(),
63             isMediaAllowed.filterNotNull(),
64             isRingerAllowed.filterNotNull(),
65             isSystemAllowed.filterNotNull(),
66         ) { zenMode, areAlarmsAllowed, isMediaAllowed, isRingerAllowed, isSystemAllowed ->
67             when (zenMode) {
68                 // Everything is muted
69                 Settings.Global.ZEN_MODE_NO_INTERRUPTIONS -> return@combine true
70                 Settings.Global.ZEN_MODE_ALARMS ->
71                     return@combine stream.value == AudioManager.STREAM_RING ||
72                         stream.value == AudioManager.STREAM_NOTIFICATION ||
73                         stream.value == AudioManager.STREAM_SYSTEM
74                 Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS -> {
75                     when {
76                         stream.value == AudioManager.STREAM_ALARM && !areAlarmsAllowed ->
77                             return@combine true
78                         stream.value == AudioManager.STREAM_MUSIC && !isMediaAllowed ->
79                             return@combine true
80                         stream.value == AudioManager.STREAM_SYSTEM && !isSystemAllowed ->
81                             return@combine true
82                         (stream.value == AudioManager.STREAM_RING ||
83                             stream.value == AudioManager.STREAM_NOTIFICATION) && !isRingerAllowed ->
84                             return@combine true
85                     }
86                 }
87             }
88             return@combine false
89         }
90     }
91 }
92