xref: /aosp_15_r20/frameworks/base/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 /*
2  * Copyright (C) 2021 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.qs.tiles
18 
19 import android.app.Dialog
20 import android.content.ContextWrapper
21 import android.content.SharedPreferences
22 import android.os.Handler
23 import android.platform.test.annotations.DisableFlags
24 import android.platform.test.flag.junit.FlagsParameterization
25 import android.platform.test.flag.junit.FlagsParameterization.allCombinationsOf
26 import android.provider.Settings
27 import android.provider.Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
28 import android.provider.Settings.Global.ZEN_MODE_OFF
29 import android.testing.TestableLooper
30 import android.view.ContextThemeWrapper
31 import androidx.test.filters.SmallTest
32 import com.android.internal.logging.MetricsLogger
33 import com.android.systemui.SysuiTestCase
34 import com.android.systemui.animation.DialogTransitionAnimator
35 import com.android.systemui.animation.Expandable
36 import com.android.systemui.classifier.FalsingManagerFake
37 import com.android.systemui.plugins.ActivityStarter
38 import com.android.systemui.plugins.qs.QSTile
39 import com.android.systemui.plugins.statusbar.StatusBarStateController
40 import com.android.systemui.qs.QSHost
41 import com.android.systemui.qs.QsEventLogger
42 import com.android.systemui.qs.flags.QSComposeFragment
43 import com.android.systemui.qs.flags.QsInCompose.isEnabled
44 import com.android.systemui.qs.logging.QSLogger
45 import com.android.systemui.qs.tileimpl.QSTileImpl
46 import com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIconWithRes
47 import com.android.systemui.res.R
48 import com.android.systemui.statusbar.policy.ZenModeController
49 import com.android.systemui.util.mockito.any
50 import com.android.systemui.util.mockito.nullable
51 import com.android.systemui.util.settings.FakeSettings
52 import com.android.systemui.util.settings.SecureSettings
53 import com.google.common.truth.Truth.assertThat
54 import java.io.File
55 import org.junit.After
56 import org.junit.Before
57 import org.junit.Test
58 import org.junit.runner.RunWith
59 import org.mockito.Mock
60 import org.mockito.Mockito.anyBoolean
61 import org.mockito.Mockito.never
62 import org.mockito.Mockito.verify
63 import org.mockito.Mockito.`when` as whenever
64 import org.mockito.MockitoAnnotations
65 import platform.test.runner.parameterized.ParameterizedAndroidJunit4
66 import platform.test.runner.parameterized.Parameters
67 
68 @SmallTest
69 @RunWith(ParameterizedAndroidJunit4::class)
70 @TestableLooper.RunWithLooper(setAsMainLooper = true)
71 @DisableFlags(android.app.Flags.FLAG_MODES_UI)
72 class DndTileTest(flags: FlagsParameterization) : SysuiTestCase() {
73 
74     companion object {
75         private const val DEFAULT_USER = 0
76         private const val KEY = Settings.Secure.ZEN_DURATION
77 
78         @JvmStatic
79         @Parameters(name = "{0}")
getParamsnull80         fun getParams(): List<FlagsParameterization> {
81             return allCombinationsOf(QSComposeFragment.FLAG_NAME)
82         }
83     }
84 
85     init {
86         mSetFlagsRule.setFlagsParameterization(flags)
87     }
88 
89     @Mock private lateinit var qsHost: QSHost
90 
91     @Mock private lateinit var metricsLogger: MetricsLogger
92 
93     @Mock private lateinit var statusBarStateController: StatusBarStateController
94 
95     @Mock private lateinit var activityStarter: ActivityStarter
96 
97     @Mock private lateinit var qsLogger: QSLogger
98 
99     @Mock private lateinit var uiEventLogger: QsEventLogger
100 
101     @Mock private lateinit var zenModeController: ZenModeController
102 
103     @Mock private lateinit var sharedPreferences: SharedPreferences
104 
105     @Mock private lateinit var mDialogTransitionAnimator: DialogTransitionAnimator
106 
107     @Mock private lateinit var hostDialog: Dialog
108 
109     @Mock private lateinit var expandable: Expandable
110 
111     @Mock private lateinit var controller: DialogTransitionAnimator.Controller
112 
113     private lateinit var secureSettings: SecureSettings
114     private lateinit var testableLooper: TestableLooper
115     private lateinit var tile: DndTile
116 
117     @Before
setUpnull118     fun setUp() {
119         MockitoAnnotations.initMocks(this)
120         testableLooper = TestableLooper.get(this)
121         secureSettings = FakeSettings()
122 
123         whenever(qsHost.userId).thenReturn(DEFAULT_USER)
124 
125         val wrappedContext =
126             object :
127                 ContextWrapper(ContextThemeWrapper(context, R.style.Theme_SystemUI_QuickSettings)) {
128                 override fun getSharedPreferences(file: File?, mode: Int): SharedPreferences {
129                     return sharedPreferences
130                 }
131             }
132         whenever(qsHost.context).thenReturn(wrappedContext)
133         whenever(expandable.dialogTransitionController(any())).thenReturn(controller)
134 
135         tile =
136             DndTile(
137                 qsHost,
138                 uiEventLogger,
139                 testableLooper.looper,
140                 Handler(testableLooper.looper),
141                 FalsingManagerFake(),
142                 metricsLogger,
143                 statusBarStateController,
144                 activityStarter,
145                 qsLogger,
146                 zenModeController,
147                 sharedPreferences,
148                 secureSettings,
149                 mDialogTransitionAnimator,
150             )
151     }
152 
153     @After
tearDownnull154     fun tearDown() {
155         tile.destroy()
156         testableLooper.processAllMessages()
157     }
158 
159     @Test
testForceExpandIcon_durationAskAlways_truenull160     fun testForceExpandIcon_durationAskAlways_true() {
161         secureSettings.putIntForUser(KEY, Settings.Secure.ZEN_DURATION_PROMPT, DEFAULT_USER)
162 
163         tile.refreshState()
164         testableLooper.processAllMessages()
165 
166         assertThat(tile.state.forceExpandIcon).isTrue()
167     }
168 
169     @Test
testForceExpandIcon_durationNotAskAlways_falsenull170     fun testForceExpandIcon_durationNotAskAlways_false() {
171         secureSettings.putIntForUser(KEY, 60, DEFAULT_USER)
172 
173         tile.refreshState()
174         testableLooper.processAllMessages()
175 
176         assertThat(tile.state.forceExpandIcon).isFalse()
177     }
178 
179     @Test
testForceExpandIcon_changeWhileListeningnull180     fun testForceExpandIcon_changeWhileListening() {
181         secureSettings.putIntForUser(KEY, 60, DEFAULT_USER)
182 
183         tile.refreshState()
184         testableLooper.processAllMessages()
185 
186         assertThat(tile.state.forceExpandIcon).isFalse()
187 
188         tile.handleSetListening(true)
189 
190         secureSettings.putIntForUser(KEY, Settings.Secure.ZEN_DURATION_PROMPT, DEFAULT_USER)
191         testableLooper.processAllMessages()
192 
193         assertThat(tile.state.forceExpandIcon).isTrue()
194     }
195 
196     @Test
testLaunchDialogFromViewWhenPromptnull197     fun testLaunchDialogFromViewWhenPrompt() {
198         whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
199 
200         secureSettings.putIntForUser(KEY, Settings.Secure.ZEN_DURATION_PROMPT, DEFAULT_USER)
201         testableLooper.processAllMessages()
202 
203         tile.handleClick(expandable)
204         testableLooper.processAllMessages()
205 
206         verify(mDialogTransitionAnimator).show(any(), any(), anyBoolean())
207     }
208 
209     @Test
testNoLaunchDialogWhenNotPromptnull210     fun testNoLaunchDialogWhenNotPrompt() {
211         whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
212 
213         secureSettings.putIntForUser(KEY, 60, DEFAULT_USER)
214         testableLooper.processAllMessages()
215 
216         tile.handleClick(expandable)
217         testableLooper.processAllMessages()
218 
219         verify(mDialogTransitionAnimator, never())
220             .showFromView(any(), any(), nullable(), anyBoolean())
221     }
222 
223     @Test
testIcon_whenDndModeOff_isOffStatenull224     fun testIcon_whenDndModeOff_isOffState() {
225         whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
226         val state = QSTile.BooleanState()
227 
228         tile.handleUpdateState(state, /* arg= */ null)
229 
230         assertThat(state.icon).isEqualTo(createExpectedIcon(R.drawable.qs_dnd_icon_off))
231     }
232 
233     @Test
testIcon_whenDndModeOn_isOnStatenull234     fun testIcon_whenDndModeOn_isOnState() {
235         whenever(zenModeController.zen).thenReturn(ZEN_MODE_NO_INTERRUPTIONS)
236         val state = QSTile.BooleanState()
237 
238         tile.handleUpdateState(state, /* arg= */ null)
239 
240         assertThat(state.icon).isEqualTo(createExpectedIcon(R.drawable.qs_dnd_icon_on))
241     }
242 
createExpectedIconnull243     private fun createExpectedIcon(resId: Int): QSTile.Icon {
244         return if (isEnabled) {
245             DrawableIconWithRes(mContext.getDrawable(resId), resId)
246         } else {
247             QSTileImpl.ResourceIcon.get(resId)
248         }
249     }
250 }
251