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 package com.android.systemui.notetask 17 18 import android.app.role.RoleManager 19 import android.app.role.RoleManager.ROLE_NOTES 20 import android.os.UserHandle 21 import android.os.UserManager 22 import android.view.KeyEvent 23 import android.view.KeyEvent.ACTION_DOWN 24 import android.view.KeyEvent.ACTION_UP 25 import android.view.KeyEvent.KEYCODE_N 26 import android.view.KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL 27 import androidx.test.ext.junit.runners.AndroidJUnit4 28 import androidx.test.filters.SmallTest 29 import com.android.keyguard.KeyguardUpdateMonitor 30 import com.android.systemui.SysuiTestCase 31 import com.android.systemui.settings.FakeUserTracker 32 import com.android.systemui.statusbar.CommandQueue 33 import com.android.systemui.util.concurrency.FakeExecutor 34 import com.android.systemui.util.mockito.any 35 import com.android.systemui.util.mockito.eq 36 import com.android.systemui.util.mockito.mock 37 import com.android.systemui.util.mockito.whenever 38 import com.android.systemui.util.mockito.withArgCaptor 39 import com.android.systemui.util.time.FakeSystemClock 40 import com.android.wm.shell.bubbles.Bubbles 41 import com.google.common.truth.Truth.assertThat 42 import java.util.Optional 43 import kotlinx.coroutines.ExperimentalCoroutinesApi 44 import org.junit.Before 45 import org.junit.Test 46 import org.junit.runner.RunWith 47 import org.mockito.Mock 48 import org.mockito.Mockito.never 49 import org.mockito.Mockito.times 50 import org.mockito.Mockito.verify 51 import org.mockito.Mockito.verifyZeroInteractions 52 import org.mockito.MockitoAnnotations.initMocks 53 54 /** atest SystemUITests:NoteTaskInitializerTest */ 55 @OptIn(ExperimentalCoroutinesApi::class, InternalNoteTaskApi::class) 56 @SmallTest 57 @RunWith(AndroidJUnit4::class) 58 internal class NoteTaskInitializerTest : SysuiTestCase() { 59 60 @Mock lateinit var commandQueue: CommandQueue 61 @Mock lateinit var bubbles: Bubbles 62 @Mock lateinit var controller: NoteTaskController 63 @Mock lateinit var roleManager: RoleManager 64 @Mock lateinit var userManager: UserManager 65 @Mock lateinit var keyguardMonitor: KeyguardUpdateMonitor 66 67 private val executor = FakeExecutor(FakeSystemClock()) 68 private val userTracker = FakeUserTracker() 69 private val handlerCallbacks = mutableListOf<Runnable>() 70 71 @Before setUpnull72 fun setUp() { 73 initMocks(this) 74 whenever(keyguardMonitor.isUserUnlocked(userTracker.userId)).thenReturn(true) 75 } 76 createUnderTestnull77 private fun createUnderTest( 78 isEnabled: Boolean, 79 bubbles: Bubbles?, 80 ): NoteTaskInitializer = 81 NoteTaskInitializer( 82 controller = controller, 83 commandQueue = commandQueue, 84 optionalBubbles = Optional.ofNullable(bubbles), 85 isEnabled = isEnabled, 86 roleManager = roleManager, 87 userTracker = userTracker, 88 keyguardUpdateMonitor = keyguardMonitor, 89 backgroundExecutor = executor, 90 ) 91 92 private fun createKeyEvent( 93 action: Int, 94 code: Int, 95 downTime: Long = 0L, 96 eventTime: Long = 0L, 97 metaState: Int = 0 98 ): KeyEvent = KeyEvent(downTime, eventTime, action, code, 0 /*repeat*/, metaState) 99 100 @Test 101 fun initialize_withUserUnlocked() { 102 whenever(keyguardMonitor.isUserUnlocked(userTracker.userId)).thenReturn(true) 103 104 createUnderTest(isEnabled = true, bubbles = bubbles).initialize() 105 106 verify(commandQueue).addCallback(any()) 107 verify(roleManager).addOnRoleHoldersChangedListenerAsUser(any(), any(), any()) 108 verify(controller).updateNoteTaskForCurrentUserAndManagedProfiles() 109 verify(keyguardMonitor).registerCallback(any()) 110 } 111 112 @Test initialize_withUserLockednull113 fun initialize_withUserLocked() { 114 whenever(keyguardMonitor.isUserUnlocked(userTracker.userId)).thenReturn(false) 115 116 createUnderTest(isEnabled = true, bubbles = bubbles).initialize() 117 118 verify(commandQueue).addCallback(any()) 119 verify(roleManager).addOnRoleHoldersChangedListenerAsUser(any(), any(), any()) 120 verify(controller, never()).setNoteTaskShortcutEnabled(any(), any()) 121 verify(keyguardMonitor).registerCallback(any()) 122 assertThat(userTracker.callbacks).isNotEmpty() 123 } 124 125 @Test initialize_flagDisablednull126 fun initialize_flagDisabled() { 127 val underTest = createUnderTest(isEnabled = false, bubbles = bubbles) 128 129 underTest.initialize() 130 131 verifyZeroInteractions( 132 commandQueue, 133 bubbles, 134 controller, 135 roleManager, 136 userManager, 137 keyguardMonitor, 138 ) 139 } 140 141 @Test initialize_bubblesNotPresentnull142 fun initialize_bubblesNotPresent() { 143 val underTest = createUnderTest(isEnabled = true, bubbles = null) 144 145 underTest.initialize() 146 147 verifyZeroInteractions( 148 commandQueue, 149 bubbles, 150 controller, 151 roleManager, 152 userManager, 153 keyguardMonitor, 154 ) 155 } 156 157 @Test initialize_handleSystemKeynull158 fun initialize_handleSystemKey() { 159 val expectedKeyEvent = 160 createKeyEvent( 161 ACTION_DOWN, 162 KEYCODE_N, 163 metaState = KeyEvent.META_META_ON or KeyEvent.META_CTRL_ON 164 ) 165 val underTest = createUnderTest(isEnabled = true, bubbles = bubbles) 166 underTest.initialize() 167 val callback = withArgCaptor { verify(commandQueue).addCallback(capture()) } 168 169 callback.handleSystemKey(expectedKeyEvent) 170 171 verify(controller).showNoteTask(any()) 172 } 173 174 @Test initialize_userUnlocked_shouldUpdateNoteTasknull175 fun initialize_userUnlocked_shouldUpdateNoteTask() { 176 whenever(keyguardMonitor.isUserUnlocked(userTracker.userId)).thenReturn(false) 177 val underTest = createUnderTest(isEnabled = true, bubbles = bubbles) 178 underTest.initialize() 179 val callback = withArgCaptor { verify(keyguardMonitor).registerCallback(capture()) } 180 whenever(keyguardMonitor.isUserUnlocked(userTracker.userId)).thenReturn(true) 181 182 callback.onUserUnlocked() 183 184 verify(controller).updateNoteTaskForCurrentUserAndManagedProfiles() 185 } 186 187 @Test initialize_onRoleHoldersChanged_shouldRunOnRoleHoldersChangednull188 fun initialize_onRoleHoldersChanged_shouldRunOnRoleHoldersChanged() { 189 val underTest = createUnderTest(isEnabled = true, bubbles = bubbles) 190 underTest.initialize() 191 val callback = withArgCaptor { 192 verify(roleManager) 193 .addOnRoleHoldersChangedListenerAsUser(any(), capture(), eq(UserHandle.ALL)) 194 } 195 196 callback.onRoleHoldersChanged(ROLE_NOTES, userTracker.userHandle) 197 198 verify(controller).onRoleHoldersChanged(ROLE_NOTES, userTracker.userHandle) 199 } 200 201 @Test initialize_onProfilesChanged_shouldUpdateNoteTasknull202 fun initialize_onProfilesChanged_shouldUpdateNoteTask() { 203 val underTest = createUnderTest(isEnabled = true, bubbles = bubbles) 204 underTest.initialize() 205 206 userTracker.callbacks.first().onProfilesChanged(emptyList()) 207 208 verify(controller, times(2)).updateNoteTaskForCurrentUserAndManagedProfiles() 209 } 210 211 @Test initialize_onUserChanged_shouldUpdateNoteTasknull212 fun initialize_onUserChanged_shouldUpdateNoteTask() { 213 val underTest = createUnderTest(isEnabled = true, bubbles = bubbles) 214 underTest.initialize() 215 216 userTracker.callbacks.first().onUserChanged(0, mock()) 217 218 verify(controller, times(2)).updateNoteTaskForCurrentUserAndManagedProfiles() 219 } 220 221 @Test tailButtonGestureDetection_singlePress_shouldShowNoteTaskOnUpnull222 fun tailButtonGestureDetection_singlePress_shouldShowNoteTaskOnUp() { 223 val underTest = createUnderTest(isEnabled = true, bubbles = bubbles) 224 underTest.initialize() 225 val callback = withArgCaptor { verify(commandQueue).addCallback(capture()) } 226 227 callback.handleSystemKey( 228 createKeyEvent(ACTION_DOWN, KEYCODE_STYLUS_BUTTON_TAIL, downTime = 0, eventTime = 0) 229 ) 230 verify(controller, never()).showNoteTask(any()) 231 232 callback.handleSystemKey( 233 createKeyEvent(ACTION_UP, KEYCODE_STYLUS_BUTTON_TAIL, downTime = 0, eventTime = 50) 234 ) 235 236 verify(controller).showNoteTask(any()) 237 } 238 239 @Test tailButtonGestureDetection_doublePress_shouldNotShowNoteTaskTwicenull240 fun tailButtonGestureDetection_doublePress_shouldNotShowNoteTaskTwice() { 241 val underTest = createUnderTest(isEnabled = true, bubbles = bubbles) 242 underTest.initialize() 243 val callback = withArgCaptor { verify(commandQueue).addCallback(capture()) } 244 245 callback.handleSystemKey( 246 createKeyEvent(ACTION_DOWN, KEYCODE_STYLUS_BUTTON_TAIL, downTime = 0, eventTime = 0) 247 ) 248 callback.handleSystemKey( 249 createKeyEvent(ACTION_UP, KEYCODE_STYLUS_BUTTON_TAIL, downTime = 0, eventTime = 50) 250 ) 251 callback.handleSystemKey( 252 createKeyEvent(ACTION_DOWN, KEYCODE_STYLUS_BUTTON_TAIL, downTime = 99, eventTime = 99) 253 ) 254 callback.handleSystemKey( 255 createKeyEvent(ACTION_UP, KEYCODE_STYLUS_BUTTON_TAIL, downTime = 99, eventTime = 150) 256 ) 257 258 verify(controller, times(1)).showNoteTask(any()) 259 } 260 261 @Test tailButtonGestureDetection_longPress_shouldNotShowNoteTasknull262 fun tailButtonGestureDetection_longPress_shouldNotShowNoteTask() { 263 val underTest = createUnderTest(isEnabled = true, bubbles = bubbles) 264 underTest.initialize() 265 val callback = withArgCaptor { verify(commandQueue).addCallback(capture()) } 266 267 callback.handleSystemKey( 268 createKeyEvent(ACTION_DOWN, KEYCODE_STYLUS_BUTTON_TAIL, downTime = 0, eventTime = 0) 269 ) 270 callback.handleSystemKey( 271 createKeyEvent(ACTION_UP, KEYCODE_STYLUS_BUTTON_TAIL, downTime = 0, eventTime = 1000) 272 ) 273 274 verify(controller, never()).showNoteTask(any()) 275 } 276 } 277