1 /*
2  * Copyright (C) 2022 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.statusbar.disableflags
18 
19 import android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS
20 import android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS
21 import android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS
22 import android.app.StatusBarManager.DISABLE_CLOCK
23 import android.app.StatusBarManager.DISABLE_EXPAND
24 import android.app.StatusBarManager.DISABLE_NAVIGATION
25 import android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS
26 import android.app.StatusBarManager.DISABLE_NOTIFICATION_TICKER
27 import androidx.test.filters.SmallTest
28 import com.android.systemui.SysuiTestCase
29 import com.android.systemui.statusbar.CommandQueue
30 import com.google.common.truth.Truth.assertThat
31 import org.junit.Before
32 import org.junit.Test
33 import org.mockito.Mock
34 import org.mockito.Mockito.verify
35 import org.mockito.MockitoAnnotations
36 
37 @SmallTest
38 class DisableStateTrackerTest : SysuiTestCase() {
39 
40     private lateinit var underTest: DisableStateTracker
41 
42     @Mock private lateinit var commandQueue: CommandQueue
43 
44     @Before
45     fun setUp() {
46         MockitoAnnotations.initMocks(this)
47     }
48 
49     @Test
50     fun startTracking_commandQueueGetsCallback() {
51         underTest = DisableStateTracker(0, 0) { }
52 
53         underTest.startTracking(commandQueue, displayId = 0)
54 
55         verify(commandQueue).addCallback(underTest)
56     }
57 
58     @Test
59     fun stopTracking_commandQueueLosesCallback() {
60         underTest = DisableStateTracker(0, 0) { }
61 
62         underTest.stopTracking(commandQueue)
63 
64         verify(commandQueue).removeCallback(underTest)
65     }
66 
67     @Test
68     fun disable_hadNotStartedTracking_isDisabledFalse() {
69         underTest = DisableStateTracker(DISABLE_CLOCK, 0) { }
70 
71         underTest.disable(displayId = 0, state1 = DISABLE_CLOCK, state2 = 0, animate = false)
72 
73         assertThat(underTest.isDisabled).isFalse()
74     }
75 
76     @Test
77     fun disable_wrongDisplayId_isDisabledFalse() {
78         underTest = DisableStateTracker(DISABLE_CLOCK, 0) { }
79         underTest.startTracking(commandQueue, displayId = 15)
80 
81         underTest.disable(displayId = 20, state1 = DISABLE_CLOCK, state2 = 0, animate = false)
82 
83         assertThat(underTest.isDisabled).isFalse()
84     }
85 
86     @Test
87     fun disable_irrelevantFlagsUpdated_isDisabledFalse() {
88         underTest = DisableStateTracker(DISABLE_CLOCK, DISABLE2_GLOBAL_ACTIONS) { }
89         underTest.startTracking(commandQueue, DISPLAY_ID)
90 
91         underTest.disable(
92             DISPLAY_ID, state1 = DISABLE_EXPAND, state2 = DISABLE2_QUICK_SETTINGS, animate = false
93         )
94 
95         assertThat(underTest.isDisabled).isFalse()
96     }
97 
98     @Test
99     fun disable_partOfMask1True_isDisabledTrue() {
100         underTest = DisableStateTracker(
101             mask1 = DISABLE_CLOCK or DISABLE_EXPAND or DISABLE_NAVIGATION,
102             mask2 = DISABLE2_GLOBAL_ACTIONS
103         ) { }
104         underTest.startTracking(commandQueue, DISPLAY_ID)
105 
106         underTest.disable(DISPLAY_ID, state1 = DISABLE_EXPAND, state2 = 0, animate = false)
107 
108         assertThat(underTest.isDisabled).isTrue()
109     }
110 
111     @Test
112     fun disable_partOfMask2True_isDisabledTrue() {
113         underTest = DisableStateTracker(
114             mask1 = DISABLE_CLOCK,
115             mask2 = DISABLE2_GLOBAL_ACTIONS or DISABLE2_SYSTEM_ICONS
116         ) { }
117         underTest.startTracking(commandQueue, DISPLAY_ID)
118 
119         underTest.disable(DISPLAY_ID, state1 = 0, state2 = DISABLE2_SYSTEM_ICONS, animate = false)
120 
121         assertThat(underTest.isDisabled).isTrue()
122     }
123 
124     @Test
125     fun disable_isDisabledChangesFromFalseToTrue_callbackNotified() {
126         var callbackCalled = false
127 
128         underTest = DisableStateTracker(
129             mask1 = DISABLE_CLOCK,
130             mask2 = DISABLE2_GLOBAL_ACTIONS
131         ) { callbackCalled = true }
132         underTest.startTracking(commandQueue, DISPLAY_ID)
133 
134         underTest.disable(DISPLAY_ID, state1 = DISABLE_CLOCK, state2 = 0, animate = false)
135 
136         assertThat(callbackCalled).isTrue()
137     }
138 
139     @Test
140     fun disable_isDisabledChangesFromTrueToFalse_callbackNotified() {
141         var callbackCalled: Boolean
142 
143         underTest = DisableStateTracker(
144             mask1 = DISABLE_CLOCK,
145             mask2 = DISABLE2_GLOBAL_ACTIONS
146         ) { callbackCalled = true }
147         underTest.startTracking(commandQueue, DISPLAY_ID)
148 
149         // First, update isDisabled to true
150         underTest.disable(DISPLAY_ID, state1 = DISABLE_CLOCK, state2 = 0, animate = false)
151         assertThat(underTest.isDisabled).isTrue()
152 
153         // WHEN isDisabled updates back to false
154         callbackCalled = false
155         underTest.disable(DISPLAY_ID, state1 = 0, state2 = 0, animate = false)
156 
157         // THEN the callback is called again
158         assertThat(callbackCalled).isTrue()
159     }
160 
161     @Test
162     fun disable_manyUpdates_isDisabledUpdatesAppropriately() {
163         underTest = DisableStateTracker(
164             mask1 = DISABLE_CLOCK or DISABLE_EXPAND or DISABLE_NAVIGATION,
165             mask2 = DISABLE2_GLOBAL_ACTIONS or DISABLE2_SYSTEM_ICONS
166         ) { }
167         underTest.startTracking(commandQueue, DISPLAY_ID)
168 
169         // All flags from mask1 -> isDisabled = true
170         underTest.disable(
171             DISPLAY_ID,
172             state1 = DISABLE_CLOCK or DISABLE_EXPAND or DISABLE_NAVIGATION,
173             state2 = 0,
174             animate = false
175         )
176         assertThat(underTest.isDisabled).isTrue()
177 
178         // Irrelevant flags from mask1 -> isDisabled = false
179         underTest.disable(
180             DISPLAY_ID,
181             state1 = DISABLE_NOTIFICATION_ICONS or DISABLE_NOTIFICATION_TICKER,
182             state2 = 0,
183             animate = false
184         )
185         assertThat(underTest.isDisabled).isFalse()
186 
187         // All flags from mask1 & all flags from mask2 -> isDisabled = true
188         underTest.disable(
189             DISPLAY_ID,
190             state1 = DISABLE_CLOCK or DISABLE_EXPAND or DISABLE_NAVIGATION,
191             state2 = DISABLE2_GLOBAL_ACTIONS or DISABLE2_SYSTEM_ICONS,
192             animate = false
193         )
194         assertThat(underTest.isDisabled).isTrue()
195 
196         // No flags -> isDisabled = false
197         underTest.disable(DISPLAY_ID, state1 = 0, state2 = 0, animate = false)
198         assertThat(underTest.isDisabled).isFalse()
199 
200         // 1 flag from mask1 & 1 flag from mask2 -> isDisabled = true
201         underTest.disable(
202             DISPLAY_ID,
203             state1 = DISABLE_NAVIGATION,
204             state2 = DISABLE2_SYSTEM_ICONS,
205             animate = false
206         )
207         assertThat(underTest.isDisabled).isTrue()
208     }
209 
210     companion object {
211         private const val DISPLAY_ID = 3
212     }
213 }
214