1 /* 2 * Copyright (C) 2023 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.recents 18 19 import android.content.ComponentName 20 import android.content.Context 21 import android.content.pm.PackageManager 22 import android.content.pm.ResolveInfo 23 import android.os.PowerManager 24 import android.os.Process 25 import android.os.UserHandle 26 import android.os.UserManager 27 import android.testing.TestableContext 28 import android.testing.TestableLooper 29 import androidx.test.ext.junit.runners.AndroidJUnit4 30 import androidx.test.filters.SmallTest 31 import com.android.dx.mockito.inline.extended.ExtendedMockito 32 import com.android.internal.app.AssistUtils 33 import com.android.internal.logging.UiEventLogger 34 import com.android.systemui.SysuiTestCase 35 import com.android.systemui.broadcast.BroadcastDispatcher 36 import com.android.systemui.dagger.qualifiers.Main 37 import com.android.systemui.dump.DumpManager 38 import com.android.systemui.keyguard.KeyguardUnlockAnimationController 39 import com.android.systemui.keyguard.WakefulnessLifecycle 40 import com.android.systemui.keyguard.ui.view.InWindowLauncherUnlockAnimationManager 41 import com.android.systemui.model.SysUiState 42 import com.android.systemui.model.sceneContainerPlugin 43 import com.android.systemui.navigationbar.NavigationBarController 44 import com.android.systemui.navigationbar.NavigationModeController 45 import com.android.systemui.recents.OverviewProxyService.ACTION_QUICKSTEP 46 import com.android.systemui.settings.FakeDisplayTracker 47 import com.android.systemui.settings.UserTracker 48 import com.android.systemui.shade.ShadeViewController 49 import com.android.systemui.shared.recents.IOverviewProxy 50 import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_WAKEFULNESS_MASK 51 import com.android.systemui.shared.system.QuickStepContract.WAKEFULNESS_ASLEEP 52 import com.android.systemui.shared.system.QuickStepContract.WAKEFULNESS_AWAKE 53 import com.android.systemui.shared.system.QuickStepContract.WAKEFULNESS_GOING_TO_SLEEP 54 import com.android.systemui.shared.system.QuickStepContract.WAKEFULNESS_WAKING 55 import com.android.systemui.statusbar.CommandQueue 56 import com.android.systemui.statusbar.NotificationShadeWindowController 57 import com.android.systemui.testKosmos 58 import com.android.systemui.unfold.progress.UnfoldTransitionProgressForwarder 59 import com.android.systemui.util.mockito.mock 60 import com.android.systemui.util.mockito.whenever 61 import com.android.systemui.util.time.FakeSystemClock 62 import com.android.wm.shell.back.BackAnimation 63 import com.android.wm.shell.sysui.ShellInterface 64 import com.google.common.util.concurrent.MoreExecutors 65 import java.util.Optional 66 import java.util.concurrent.Executor 67 import org.junit.After 68 import org.junit.Before 69 import org.junit.Test 70 import org.junit.runner.RunWith 71 import org.mockito.ArgumentMatchers 72 import org.mockito.Mock 73 import org.mockito.Mockito.any 74 import org.mockito.Mockito.anyInt 75 import org.mockito.Mockito.atLeast 76 import org.mockito.Mockito.clearInvocations 77 import org.mockito.Mockito.longThat 78 import org.mockito.Mockito.mock 79 import org.mockito.Mockito.spy 80 import org.mockito.Mockito.times 81 import org.mockito.Mockito.verify 82 import org.mockito.Mockito.`when` 83 import org.mockito.MockitoAnnotations 84 85 @SmallTest 86 @RunWith(AndroidJUnit4::class) 87 @TestableLooper.RunWithLooper(setAsMainLooper = true) 88 class OverviewProxyServiceTest : SysuiTestCase() { 89 90 @Main private val executor: Executor = MoreExecutors.directExecutor() 91 92 private val kosmos = testKosmos() 93 private lateinit var subject: OverviewProxyService 94 @Mock private val dumpManager = DumpManager() 95 private val displayTracker = FakeDisplayTracker(mContext) 96 private val fakeSystemClock = FakeSystemClock() 97 private val sysUiState = SysUiState(displayTracker, kosmos.sceneContainerPlugin) 98 private val wakefulnessLifecycle = 99 WakefulnessLifecycle(mContext, null, fakeSystemClock, dumpManager) 100 101 @Mock private lateinit var overviewProxy: IOverviewProxy.Stub 102 @Mock private lateinit var packageManager: PackageManager 103 104 // The following mocks belong to not-yet-tested parts of OverviewProxyService. 105 @Mock private lateinit var commandQueue: CommandQueue 106 @Mock private lateinit var shellInterface: ShellInterface 107 @Mock private lateinit var navBarController: NavigationBarController 108 @Mock private lateinit var shadeViewController: ShadeViewController 109 @Mock private lateinit var screenPinningRequest: ScreenPinningRequest 110 @Mock private lateinit var navModeController: NavigationModeController 111 @Mock private lateinit var statusBarWinController: NotificationShadeWindowController 112 @Mock private lateinit var userTracker: UserTracker 113 @Mock private lateinit var userManager: UserManager 114 @Mock private lateinit var uiEventLogger: UiEventLogger 115 @Mock private lateinit var sysuiUnlockAnimationController: KeyguardUnlockAnimationController 116 @Mock 117 private lateinit var inWindowLauncherUnlockAnimationManager: 118 InWindowLauncherUnlockAnimationManager 119 @Mock private lateinit var assistUtils: AssistUtils 120 @Mock 121 private lateinit var unfoldTransitionProgressForwarder: 122 Optional<UnfoldTransitionProgressForwarder> 123 @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher 124 @Mock private lateinit var backAnimation: Optional<BackAnimation> 125 126 @Before setUpnull127 fun setUp() { 128 MockitoAnnotations.initMocks(this) 129 130 val serviceComponent = ComponentName("test_package", "service_provider") 131 context.addMockService(serviceComponent, overviewProxy) 132 context.addMockServiceResolver( 133 TestableContext.MockServiceResolver { 134 if (it.action == ACTION_QUICKSTEP) serviceComponent else null 135 } 136 ) 137 whenever(overviewProxy.queryLocalInterface(ArgumentMatchers.anyString())) 138 .thenReturn(overviewProxy) 139 whenever(overviewProxy.asBinder()).thenReturn(overviewProxy) 140 141 // packageManager.resolveServiceAsUser has to return non-null for 142 // OverviewProxyService#isEnabled to become true. 143 context.setMockPackageManager(packageManager) 144 whenever(packageManager.resolveServiceAsUser(any(), anyInt(), anyInt())) 145 .thenReturn(mock(ResolveInfo::class.java)) 146 147 mSetFlagsRule.disableFlags(com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR) 148 149 subject = createOverviewProxyService(context) 150 } 151 152 @After tearDownnull153 fun tearDown() { 154 subject.shutdownForTest() 155 } 156 157 @Test wakefulnessLifecycle_dispatchFinishedWakingUpSetsSysUIflagToAWAKEnull158 fun wakefulnessLifecycle_dispatchFinishedWakingUpSetsSysUIflagToAWAKE() { 159 // WakefulnessLifecycle is initialized to AWAKE initially, and won't emit a noop. 160 wakefulnessLifecycle.dispatchFinishedGoingToSleep() 161 clearInvocations(overviewProxy) 162 163 wakefulnessLifecycle.dispatchFinishedWakingUp() 164 165 verify(overviewProxy) 166 .onSystemUiStateChanged( 167 longThat { it and SYSUI_STATE_WAKEFULNESS_MASK == WAKEFULNESS_AWAKE } 168 ) 169 } 170 171 @Test wakefulnessLifecycle_dispatchStartedWakingUpSetsSysUIflagToWAKINGnull172 fun wakefulnessLifecycle_dispatchStartedWakingUpSetsSysUIflagToWAKING() { 173 wakefulnessLifecycle.dispatchStartedWakingUp(PowerManager.WAKE_REASON_UNKNOWN) 174 175 verify(overviewProxy) 176 .onSystemUiStateChanged( 177 longThat { it and SYSUI_STATE_WAKEFULNESS_MASK == WAKEFULNESS_WAKING } 178 ) 179 } 180 181 @Test wakefulnessLifecycle_dispatchFinishedGoingToSleepSetsSysUIflagToASLEEPnull182 fun wakefulnessLifecycle_dispatchFinishedGoingToSleepSetsSysUIflagToASLEEP() { 183 wakefulnessLifecycle.dispatchFinishedGoingToSleep() 184 185 verify(overviewProxy) 186 .onSystemUiStateChanged( 187 longThat { it and SYSUI_STATE_WAKEFULNESS_MASK == WAKEFULNESS_ASLEEP } 188 ) 189 } 190 191 @Test wakefulnessLifecycle_dispatchStartedGoingToSleepSetsSysUIflagToGOING_TO_SLEEPnull192 fun wakefulnessLifecycle_dispatchStartedGoingToSleepSetsSysUIflagToGOING_TO_SLEEP() { 193 wakefulnessLifecycle.dispatchStartedGoingToSleep( 194 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON 195 ) 196 197 verify(overviewProxy) 198 .onSystemUiStateChanged( 199 longThat { it and SYSUI_STATE_WAKEFULNESS_MASK == WAKEFULNESS_GOING_TO_SLEEP } 200 ) 201 } 202 203 @Test connectToOverviewService_primaryUserNoVisibleBgUsersSupported_expectBindServicenull204 fun connectToOverviewService_primaryUserNoVisibleBgUsersSupported_expectBindService() { 205 val mockitoSession = 206 ExtendedMockito.mockitoSession().spyStatic(Process::class.java).startMocking() 207 try { 208 `when`(Process.myUserHandle()).thenReturn(UserHandle.SYSTEM) 209 `when`(userManager.isVisibleBackgroundUsersSupported()).thenReturn(false) 210 val spyContext = spy(context) 211 val ops = createOverviewProxyService(spyContext) 212 ops.startConnectionToCurrentUser() 213 verify(spyContext, atLeast(1)).bindServiceAsUser(any(), any(), anyInt(), any()) 214 } finally { 215 mockitoSession.finishMocking() 216 } 217 } 218 219 @Test connectToOverviewService_nonPrimaryUserNoVisibleBgUsersSupported_expectNoBindServicenull220 fun connectToOverviewService_nonPrimaryUserNoVisibleBgUsersSupported_expectNoBindService() { 221 val mockitoSession = 222 ExtendedMockito.mockitoSession().spyStatic(Process::class.java).startMocking() 223 try { 224 `when`(Process.myUserHandle()).thenReturn(UserHandle.of(12345)) 225 `when`(userManager.isVisibleBackgroundUsersSupported()).thenReturn(false) 226 val spyContext = spy(context) 227 val ops = createOverviewProxyService(spyContext) 228 ops.startConnectionToCurrentUser() 229 verify(spyContext, times(0)).bindServiceAsUser(any(), any(), anyInt(), any()) 230 } finally { 231 mockitoSession.finishMocking() 232 } 233 } 234 235 @Test connectToOverviewService_nonPrimaryBgUserVisibleBgUsersSupported_expectBindServicenull236 fun connectToOverviewService_nonPrimaryBgUserVisibleBgUsersSupported_expectBindService() { 237 val mockitoSession = 238 ExtendedMockito.mockitoSession().spyStatic(Process::class.java).startMocking() 239 try { 240 `when`(Process.myUserHandle()).thenReturn(UserHandle.of(12345)) 241 `when`(userManager.isVisibleBackgroundUsersSupported()).thenReturn(true) 242 `when`(userManager.isUserForeground()).thenReturn(false) 243 val spyContext = spy(context) 244 val ops = createOverviewProxyService(spyContext) 245 ops.startConnectionToCurrentUser() 246 verify(spyContext, atLeast(1)).bindServiceAsUser(any(), any(), anyInt(), any()) 247 } finally { 248 mockitoSession.finishMocking() 249 } 250 } 251 252 @Test connectToOverviewService_nonPrimaryFgUserVisibleBgUsersSupported_expectNoBindServicenull253 fun connectToOverviewService_nonPrimaryFgUserVisibleBgUsersSupported_expectNoBindService() { 254 val mockitoSession = 255 ExtendedMockito.mockitoSession().spyStatic(Process::class.java).startMocking() 256 try { 257 `when`(Process.myUserHandle()).thenReturn(UserHandle.of(12345)) 258 `when`(userManager.isVisibleBackgroundUsersSupported()).thenReturn(true) 259 `when`(userManager.isUserForeground()).thenReturn(true) 260 val spyContext = spy(context) 261 val ops = createOverviewProxyService(spyContext) 262 ops.startConnectionToCurrentUser() 263 verify(spyContext, times(0)).bindServiceAsUser(any(), any(), anyInt(), any()) 264 } finally { 265 mockitoSession.finishMocking() 266 } 267 } 268 createOverviewProxyServicenull269 private fun createOverviewProxyService(ctx: Context): OverviewProxyService { 270 return OverviewProxyService( 271 ctx, 272 executor, 273 commandQueue, 274 shellInterface, 275 { navBarController }, 276 { shadeViewController }, 277 screenPinningRequest, 278 navModeController, 279 statusBarWinController, 280 sysUiState, 281 mock(), 282 mock(), 283 userTracker, 284 userManager, 285 wakefulnessLifecycle, 286 uiEventLogger, 287 displayTracker, 288 sysuiUnlockAnimationController, 289 inWindowLauncherUnlockAnimationManager, 290 assistUtils, 291 dumpManager, 292 unfoldTransitionProgressForwarder, 293 broadcastDispatcher, 294 backAnimation, 295 ) 296 } 297 } 298