1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package com.android.systemui.statusbar.disableflags.data.repository 16 17 import android.app.StatusBarManager.DISABLE2_NONE 18 import android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE 19 import android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS 20 import android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS 21 import android.app.StatusBarManager.DISABLE_CLOCK 22 import android.app.StatusBarManager.DISABLE_NONE 23 import android.app.StatusBarManager.DISABLE_NOTIFICATION_ALERTS 24 import android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS 25 import android.app.StatusBarManager.DISABLE_SYSTEM_INFO 26 import android.content.res.Configuration 27 import androidx.test.ext.junit.runners.AndroidJUnit4 28 import androidx.test.filters.SmallTest 29 import com.android.systemui.SysuiTestCase 30 import com.android.systemui.dump.DumpManager 31 import com.android.systemui.log.LogBufferFactory 32 import com.android.systemui.res.R 33 import com.android.systemui.statusbar.CommandQueue 34 import com.android.systemui.statusbar.disableflags.DisableFlagsLogger 35 import com.android.systemui.statusbar.disableflags.shared.model.DisableFlagsModel 36 import com.android.systemui.statusbar.policy.ConfigurationController 37 import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler 38 import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController 39 import com.android.systemui.util.mockito.any 40 import com.android.systemui.util.mockito.argumentCaptor 41 import com.android.systemui.util.mockito.mock 42 import com.google.common.truth.Truth.assertThat 43 import kotlinx.coroutines.ExperimentalCoroutinesApi 44 import kotlinx.coroutines.test.TestScope 45 import kotlinx.coroutines.test.UnconfinedTestDispatcher 46 import kotlinx.coroutines.test.runTest 47 import org.junit.Before 48 import org.junit.Test 49 import org.junit.runner.RunWith 50 import org.mockito.Mockito.verify 51 52 @SmallTest 53 @OptIn(ExperimentalCoroutinesApi::class) 54 @RunWith(AndroidJUnit4::class) 55 class DisableFlagsRepositoryTest : SysuiTestCase() { 56 57 private lateinit var underTest: DisableFlagsRepository 58 59 private val testScope = TestScope(UnconfinedTestDispatcher()) 60 private val commandQueue: CommandQueue = mock() 61 private val configurationController: ConfigurationController = mock() 62 private val remoteInputQuickSettingsDisabler = 63 RemoteInputQuickSettingsDisabler( 64 context, 65 commandQueue, 66 ResourcesSplitShadeStateController(), 67 configurationController, 68 ) 69 private val logBuffer = LogBufferFactory(DumpManager(), mock()).create("buffer", 10) 70 private val disableFlagsLogger = DisableFlagsLogger() 71 72 @Before setUpnull73 fun setUp() { 74 underTest = 75 DisableFlagsRepositoryImpl( 76 commandQueue, 77 DISPLAY_ID, 78 testScope.backgroundScope, 79 remoteInputQuickSettingsDisabler, 80 logBuffer, 81 disableFlagsLogger, 82 ) 83 } 84 85 @Test disableFlags_initialValue_nonenull86 fun disableFlags_initialValue_none() { 87 assertThat(underTest.disableFlags.value) 88 .isEqualTo(DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE, animate = false)) 89 } 90 91 @Test disableFlags_noSubscribers_callbackStillRegisterednull92 fun disableFlags_noSubscribers_callbackStillRegistered() = 93 testScope.runTest { verify(commandQueue).addCallback(any()) } 94 95 @Test disableFlags_notifAlertsNotDisabled_notifAlertsEnabledTruenull96 fun disableFlags_notifAlertsNotDisabled_notifAlertsEnabledTrue() = 97 testScope.runTest { 98 getCommandQueueCallback() 99 .disable(DISPLAY_ID, DISABLE_NONE, DISABLE2_NONE, /* animate= */ false) 100 101 assertThat(underTest.disableFlags.value.areNotificationAlertsEnabled()).isTrue() 102 } 103 104 @Test disableFlags_notifAlertsDisabled_notifAlertsEnabledFalsenull105 fun disableFlags_notifAlertsDisabled_notifAlertsEnabledFalse() = 106 testScope.runTest { 107 getCommandQueueCallback() 108 .disable( 109 DISPLAY_ID, 110 DISABLE_NOTIFICATION_ALERTS, 111 DISABLE2_NONE, 112 /* animate= */ false, 113 ) 114 115 assertThat(underTest.disableFlags.value.areNotificationAlertsEnabled()).isFalse() 116 } 117 118 @Test disableFlags_notifAlertsDisabled_differentDisplay_notifAlertsEnabledTruenull119 fun disableFlags_notifAlertsDisabled_differentDisplay_notifAlertsEnabledTrue() = 120 testScope.runTest { 121 val wrongDisplayId = DISPLAY_ID + 10 122 123 getCommandQueueCallback() 124 .disable( 125 wrongDisplayId, 126 DISABLE_NOTIFICATION_ALERTS, 127 DISABLE2_NONE, 128 /* animate= */ false, 129 ) 130 131 // THEN our repo reports them as still enabled 132 assertThat(underTest.disableFlags.value.areNotificationAlertsEnabled()).isTrue() 133 } 134 135 @Test disableFlags_shadeNotDisabled_shadeEnabledTruenull136 fun disableFlags_shadeNotDisabled_shadeEnabledTrue() = 137 testScope.runTest { 138 getCommandQueueCallback() 139 .disable(DISPLAY_ID, DISABLE_NONE, DISABLE2_NONE, /* animate= */ false) 140 141 assertThat(underTest.disableFlags.value.isShadeEnabled()).isTrue() 142 } 143 144 @Test disableFlags_shadeDisabled_shadeEnabledFalsenull145 fun disableFlags_shadeDisabled_shadeEnabledFalse() = 146 testScope.runTest { 147 getCommandQueueCallback() 148 .disable( 149 DISPLAY_ID, 150 DISABLE_NONE, 151 DISABLE2_NOTIFICATION_SHADE, 152 /* animate= */ false, 153 ) 154 155 assertThat(underTest.disableFlags.value.isShadeEnabled()).isFalse() 156 } 157 158 @Test disableFlags_shadeDisabled_differentDisplay_shadeEnabledTruenull159 fun disableFlags_shadeDisabled_differentDisplay_shadeEnabledTrue() = 160 testScope.runTest { 161 val wrongDisplayId = DISPLAY_ID + 10 162 163 getCommandQueueCallback() 164 .disable( 165 wrongDisplayId, 166 DISABLE_NONE, 167 DISABLE2_NOTIFICATION_SHADE, 168 /* animate= */ false, 169 ) 170 171 // THEN our repo reports them as still enabled 172 assertThat(underTest.disableFlags.value.isShadeEnabled()).isTrue() 173 } 174 175 @Test disableFlags_quickSettingsNotDisabled_quickSettingsEnabledTruenull176 fun disableFlags_quickSettingsNotDisabled_quickSettingsEnabledTrue() = 177 testScope.runTest { 178 getCommandQueueCallback() 179 .disable(DISPLAY_ID, DISABLE_NONE, DISABLE2_NONE, /* animate= */ false) 180 181 assertThat(underTest.disableFlags.value.isQuickSettingsEnabled()).isTrue() 182 } 183 184 @Test disableFlags_quickSettingsDisabled_quickSettingsEnabledFalsenull185 fun disableFlags_quickSettingsDisabled_quickSettingsEnabledFalse() = 186 testScope.runTest { 187 getCommandQueueCallback() 188 .disable(DISPLAY_ID, DISABLE_NONE, DISABLE2_QUICK_SETTINGS, /* animate= */ false) 189 190 assertThat(underTest.disableFlags.value.isQuickSettingsEnabled()).isFalse() 191 } 192 193 @Test disableFlags_quickSettingsDisabled_differentDisplay_quickSettingsEnabledTruenull194 fun disableFlags_quickSettingsDisabled_differentDisplay_quickSettingsEnabledTrue() = 195 testScope.runTest { 196 val wrongDisplayId = DISPLAY_ID + 10 197 198 getCommandQueueCallback() 199 .disable( 200 wrongDisplayId, 201 DISABLE_NONE, 202 DISABLE2_QUICK_SETTINGS, 203 /* animate= */ false, 204 ) 205 206 // THEN our repo reports them as still enabled 207 assertThat(underTest.disableFlags.value.isQuickSettingsEnabled()).isTrue() 208 } 209 210 @Test disableFlags_remoteInputActive_quickSettingsEnabledFalsenull211 fun disableFlags_remoteInputActive_quickSettingsEnabledFalse() = 212 testScope.runTest { 213 // WHEN remote input is set up to be active 214 val configuration = Configuration(mContext.resources.configuration) 215 configuration.orientation = Configuration.ORIENTATION_LANDSCAPE 216 mContext.orCreateTestableResources.addOverride( 217 R.bool.config_use_split_notification_shade, 218 /* value= */ false, 219 ) 220 remoteInputQuickSettingsDisabler.setRemoteInputActive(true) 221 remoteInputQuickSettingsDisabler.onConfigChanged(configuration) 222 223 getCommandQueueCallback() 224 .disable(DISPLAY_ID, DISABLE_NONE, DISABLE2_NONE, /* animate= */ false) 225 226 // THEN quick settings is disabled (even if the disable flags don't say so) 227 assertThat(underTest.disableFlags.value.isQuickSettingsEnabled()).isFalse() 228 } 229 230 @Test disableFlags_clockDisablednull231 fun disableFlags_clockDisabled() = 232 testScope.runTest { 233 getCommandQueueCallback() 234 .disable(DISPLAY_ID, DISABLE_CLOCK, DISABLE2_NONE, /* animate= */ false) 235 236 assertThat(underTest.disableFlags.value.isClockEnabled).isFalse() 237 } 238 239 @Test disableFlags_clockEnablednull240 fun disableFlags_clockEnabled() = 241 testScope.runTest { 242 getCommandQueueCallback() 243 .disable(DISPLAY_ID, DISABLE_NONE, DISABLE2_NONE, /* animate= */ false) 244 245 assertThat(underTest.disableFlags.value.isClockEnabled).isTrue() 246 } 247 248 @Test disableFlags_notificationIconsDisablednull249 fun disableFlags_notificationIconsDisabled() = 250 testScope.runTest { 251 getCommandQueueCallback() 252 .disable( 253 DISPLAY_ID, 254 DISABLE_NOTIFICATION_ICONS, 255 DISABLE2_NONE, 256 /* animate= */ false, 257 ) 258 259 assertThat(underTest.disableFlags.value.areNotificationIconsEnabled).isFalse() 260 } 261 262 @Test disableFlags_notificationIconsEnablednull263 fun disableFlags_notificationIconsEnabled() = 264 testScope.runTest { 265 getCommandQueueCallback() 266 .disable(DISPLAY_ID, DISABLE_NONE, DISABLE2_NONE, /* animate= */ false) 267 268 assertThat(underTest.disableFlags.value.areNotificationIconsEnabled).isTrue() 269 } 270 271 @Test disableFlags_systemInfoDisabled_viaDisable1null272 fun disableFlags_systemInfoDisabled_viaDisable1() = 273 testScope.runTest { 274 getCommandQueueCallback() 275 .disable(DISPLAY_ID, DISABLE_SYSTEM_INFO, DISABLE2_NONE, /* animate= */ false) 276 277 assertThat(underTest.disableFlags.value.isSystemInfoEnabled).isFalse() 278 } 279 280 @Test disableFlags_systemInfoDisabled_viaDisable2null281 fun disableFlags_systemInfoDisabled_viaDisable2() = 282 testScope.runTest { 283 getCommandQueueCallback() 284 .disable(DISPLAY_ID, DISABLE_NONE, DISABLE2_SYSTEM_ICONS, /* animate= */ false) 285 286 assertThat(underTest.disableFlags.value.isSystemInfoEnabled).isFalse() 287 } 288 289 @Test disableFlags_systemInfoEnablednull290 fun disableFlags_systemInfoEnabled() = 291 testScope.runTest { 292 getCommandQueueCallback() 293 .disable(DISPLAY_ID, DISABLE_NONE, DISABLE2_NONE, /* animate= */ false) 294 295 assertThat(underTest.disableFlags.value.isSystemInfoEnabled).isTrue() 296 } 297 298 @Test disableFlags_reactsToChangesnull299 fun disableFlags_reactsToChanges() = 300 testScope.runTest { 301 getCommandQueueCallback() 302 .disable( 303 DISPLAY_ID, 304 DISABLE_NOTIFICATION_ALERTS, 305 DISABLE2_NONE, 306 /* animate= */ false, 307 ) 308 assertThat(underTest.disableFlags.value.areNotificationAlertsEnabled()).isFalse() 309 310 getCommandQueueCallback() 311 .disable( 312 DISPLAY_ID, 313 DISABLE_CLOCK, // Unrelated to notifications 314 DISABLE2_NONE, 315 /* animate= */ false, 316 ) 317 assertThat(underTest.disableFlags.value.areNotificationAlertsEnabled()).isTrue() 318 319 getCommandQueueCallback() 320 .disable( 321 DISPLAY_ID, 322 DISABLE_NOTIFICATION_ALERTS, 323 DISABLE2_QUICK_SETTINGS or DISABLE2_NOTIFICATION_SHADE, 324 /* animate= */ false, 325 ) 326 assertThat(underTest.disableFlags.value.areNotificationAlertsEnabled()).isFalse() 327 assertThat(underTest.disableFlags.value.isShadeEnabled()).isFalse() 328 assertThat(underTest.disableFlags.value.isQuickSettingsEnabled()).isFalse() 329 } 330 331 @Test disableFlags_animateFalsenull332 fun disableFlags_animateFalse() = 333 testScope.runTest { 334 getCommandQueueCallback() 335 .disable( 336 DISPLAY_ID, 337 DISABLE_NOTIFICATION_ALERTS, 338 DISABLE2_NONE, 339 /* animate= */ false, 340 ) 341 342 assertThat(underTest.disableFlags.value.animate).isFalse() 343 } 344 345 @Test disableFlags_animateTruenull346 fun disableFlags_animateTrue() = 347 testScope.runTest { 348 getCommandQueueCallback() 349 .disable( 350 DISPLAY_ID, 351 DISABLE_NOTIFICATION_ALERTS, 352 DISABLE2_NONE, 353 /* animate= */ true, 354 ) 355 356 assertThat(underTest.disableFlags.value.animate).isTrue() 357 } 358 getCommandQueueCallbacknull359 private fun getCommandQueueCallback(): CommandQueue.Callbacks { 360 val callbackCaptor = argumentCaptor<CommandQueue.Callbacks>() 361 verify(commandQueue).addCallback(callbackCaptor.capture()) 362 return callbackCaptor.value 363 } 364 365 private companion object { 366 const val DISPLAY_ID = 1 367 } 368 } 369