1 /*
2 * 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.data.repository
18
19 import android.app.AutomaticZenRule
20 import android.app.NotificationManager
21 import android.provider.Settings
22 import com.android.settingslib.notification.modes.TestModeBuilder
23 import com.android.settingslib.notification.modes.ZenMode
24 import java.time.Duration
25 import kotlinx.coroutines.flow.Flow
26 import kotlinx.coroutines.flow.MutableStateFlow
27 import kotlinx.coroutines.flow.StateFlow
28 import kotlinx.coroutines.flow.asStateFlow
29
30 class FakeZenModeRepository : ZenModeRepository {
31
32 private val mutableNotificationPolicy = MutableStateFlow<NotificationManager.Policy?>(null)
33 override val consolidatedNotificationPolicy: StateFlow<NotificationManager.Policy?>
34 get() = mutableNotificationPolicy.asStateFlow()
35
36 private val mutableZenMode = MutableStateFlow(Settings.Global.ZEN_MODE_OFF)
37 override val globalZenMode: StateFlow<Int>
38 get() = mutableZenMode.asStateFlow()
39
<lambda>null40 private val mutableModesFlow: MutableStateFlow<List<ZenMode>> by lazy {
41 MutableStateFlow(listOf(TestModeBuilder.MANUAL_DND))
42 }
43 override val modes: Flow<List<ZenMode>>
44 get() = mutableModesFlow.asStateFlow()
45
getModesnull46 override fun getModes(): List<ZenMode> = mutableModesFlow.value
47
48 private val activeModesDurations = mutableMapOf<String, Duration?>()
49
50 init {
51 updateNotificationPolicy()
52 }
53
updateNotificationPolicynull54 fun updateNotificationPolicy(policy: NotificationManager.Policy?) {
55 mutableNotificationPolicy.value = policy
56 }
57
updateZenModenull58 fun updateZenMode(zenMode: Int) {
59 mutableZenMode.value = zenMode
60 }
61
addModesnull62 fun addModes(zenModes: List<ZenMode>) {
63 mutableModesFlow.value += zenModes
64 }
65
addModenull66 fun addMode(mode: ZenMode) {
67 mutableModesFlow.value += mode
68 }
69
addModenull70 fun addMode(
71 id: String,
72 @AutomaticZenRule.Type type: Int = AutomaticZenRule.TYPE_UNKNOWN,
73 active: Boolean = false,
74 ) {
75 mutableModesFlow.value += newMode(id, type, active)
76 }
77
removeModenull78 fun removeMode(id: String) {
79 mutableModesFlow.value = mutableModesFlow.value.filter { it.id != id }
80 }
81
clearModesnull82 fun clearModes() {
83 mutableModesFlow.value = listOf()
84 }
85
getModenull86 fun getMode(id: String): ZenMode? {
87 return mutableModesFlow.value.find { it.id == id }
88 }
89
activateModenull90 override fun activateMode(zenMode: ZenMode, duration: Duration?) {
91 activateMode(zenMode.id)
92 activeModesDurations[zenMode.id] = duration
93 }
94
getModeActiveDurationnull95 fun getModeActiveDuration(id: String): Duration? {
96 if (!activeModesDurations.containsKey(id)) {
97 throw IllegalArgumentException(
98 "mode $id not manually activated, you need to call activateMode"
99 )
100 }
101 return activeModesDurations[id]
102 }
103
deactivateModenull104 override fun deactivateMode(zenMode: ZenMode) {
105 deactivateMode(zenMode.id)
106 }
107
activateModenull108 fun activateMode(id: String) {
109 updateModeActiveState(id = id, isActive = true)
110 }
111
deactivateModenull112 fun deactivateMode(id: String) {
113 updateModeActiveState(id = id, isActive = false)
114 activeModesDurations.remove(id)
115 }
116
117 /** Updates a [ZenMode]'s active state, preserving its position in the list. */
updateModeActiveStatenull118 private fun updateModeActiveState(id: String, isActive: Boolean) {
119 updateMode(id) { TestModeBuilder(it).setActive(isActive).build() }
120 }
121
122 /** Updates a [ZenMode], preserving its position in the list. */
updateModenull123 fun updateMode(id: String, update: (original: ZenMode) -> ZenMode) {
124 val modes = mutableModesFlow.value.toMutableList()
125 val index = modes.indexOfFirst { it.id == id }
126 if (index < 0) {
127 throw IllegalArgumentException("mode $id not found")
128 }
129 modes[index] = update(modes[index])
130 mutableModesFlow.value = modes
131 }
132 }
133
FakeZenModeRepositorynull134 fun FakeZenModeRepository.updateNotificationPolicy(
135 priorityCategories: Int = 0,
136 priorityCallSenders: Int = NotificationManager.Policy.PRIORITY_SENDERS_ANY,
137 priorityMessageSenders: Int = NotificationManager.Policy.CONVERSATION_SENDERS_NONE,
138 suppressedVisualEffects: Int = NotificationManager.Policy.SUPPRESSED_EFFECTS_UNSET,
139 state: Int = NotificationManager.Policy.STATE_UNSET,
140 priorityConversationSenders: Int = NotificationManager.Policy.CONVERSATION_SENDERS_NONE,
141 ) =
142 updateNotificationPolicy(
143 NotificationManager.Policy(
144 priorityCategories,
145 priorityCallSenders,
146 priorityMessageSenders,
147 suppressedVisualEffects,
148 state,
149 priorityConversationSenders,
150 )
151 )
152
153 private fun newMode(id: String, @AutomaticZenRule.Type type: Int, active: Boolean): ZenMode {
154 return TestModeBuilder().setId(id).setName("Mode $id").setType(type).setActive(active).build()
155 }
156