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.pm.PackageManager 21 import android.content.pm.ResolveInfo 22 import android.os.PowerManager 23 import android.testing.AndroidTestingRunner 24 import android.testing.TestableContext 25 import android.testing.TestableLooper 26 import androidx.test.filters.SmallTest 27 import com.android.internal.app.AssistUtils 28 import com.android.internal.logging.UiEventLogger 29 import com.android.systemui.SysuiTestCase 30 import com.android.systemui.dagger.qualifiers.Main 31 import com.android.systemui.dump.DumpManager 32 import com.android.systemui.flags.FakeFeatureFlags 33 import com.android.systemui.keyguard.KeyguardUnlockAnimationController 34 import com.android.systemui.keyguard.WakefulnessLifecycle 35 import com.android.systemui.model.SysUiState 36 import com.android.systemui.navigationbar.NavigationBarController 37 import com.android.systemui.navigationbar.NavigationModeController 38 import com.android.systemui.recents.OverviewProxyService.ACTION_QUICKSTEP 39 import com.android.systemui.settings.FakeDisplayTracker 40 import com.android.systemui.settings.UserTracker 41 import com.android.systemui.shade.ShadeViewController 42 import com.android.systemui.shared.recents.IOverviewProxy 43 import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_WAKEFULNESS_MASK 44 import com.android.systemui.shared.system.QuickStepContract.WAKEFULNESS_ASLEEP 45 import com.android.systemui.shared.system.QuickStepContract.WAKEFULNESS_AWAKE 46 import com.android.systemui.shared.system.QuickStepContract.WAKEFULNESS_GOING_TO_SLEEP 47 import com.android.systemui.shared.system.QuickStepContract.WAKEFULNESS_WAKING 48 import com.android.systemui.statusbar.CommandQueue 49 import com.android.systemui.statusbar.NotificationShadeWindowController 50 import com.android.systemui.statusbar.phone.CentralSurfaces 51 import com.android.systemui.unfold.progress.UnfoldTransitionProgressForwarder 52 import com.android.systemui.util.mockito.mock 53 import com.android.systemui.util.mockito.whenever 54 import com.android.systemui.util.time.FakeSystemClock 55 import com.android.wm.shell.sysui.ShellInterface 56 import com.google.common.util.concurrent.MoreExecutors 57 import java.util.Optional 58 import java.util.concurrent.Executor 59 import org.junit.After 60 import org.junit.Before 61 import org.junit.Test 62 import org.junit.runner.RunWith 63 import org.mockito.ArgumentMatchers 64 import org.mockito.Mock 65 import org.mockito.Mockito.any 66 import org.mockito.Mockito.anyInt 67 import org.mockito.Mockito.clearInvocations 68 import org.mockito.Mockito.intThat 69 import org.mockito.Mockito.mock 70 import org.mockito.Mockito.verify 71 import org.mockito.MockitoAnnotations 72 73 @SmallTest 74 @RunWith(AndroidTestingRunner::class) 75 @TestableLooper.RunWithLooper(setAsMainLooper = true) 76 class OverviewProxyServiceTest : SysuiTestCase() { 77 78 @Main private val executor: Executor = MoreExecutors.directExecutor() 79 80 private lateinit var subject: OverviewProxyService 81 private val dumpManager = DumpManager() 82 private val displayTracker = FakeDisplayTracker(mContext) 83 private val fakeSystemClock = FakeSystemClock() 84 private val sysUiState = SysUiState(displayTracker) 85 private val featureFlags = FakeFeatureFlags() 86 private val wakefulnessLifecycle = 87 WakefulnessLifecycle(mContext, null, fakeSystemClock, dumpManager) 88 89 @Mock private lateinit var overviewProxy: IOverviewProxy.Stub 90 @Mock private lateinit var packageManager: PackageManager 91 92 // The following mocks belong to not-yet-tested parts of OverviewProxyService. 93 @Mock private lateinit var commandQueue: CommandQueue 94 @Mock private lateinit var shellInterface: ShellInterface 95 @Mock private lateinit var navBarController: NavigationBarController 96 @Mock private lateinit var centralSurfaces: CentralSurfaces 97 @Mock private lateinit var shadeViewController: ShadeViewController 98 @Mock private lateinit var navModeController: NavigationModeController 99 @Mock private lateinit var statusBarWinController: NotificationShadeWindowController 100 @Mock private lateinit var userTracker: UserTracker 101 @Mock private lateinit var uiEventLogger: UiEventLogger 102 @Mock private lateinit var sysuiUnlockAnimationController: KeyguardUnlockAnimationController 103 @Mock private lateinit var assistUtils: AssistUtils 104 @Mock 105 private lateinit var unfoldTransitionProgressForwarder: 106 Optional<UnfoldTransitionProgressForwarder> 107 108 @Before 109 fun setUp() { 110 MockitoAnnotations.initMocks(this) 111 112 val serviceComponent = ComponentName("test_package", "service_provider") 113 context.addMockService(serviceComponent, overviewProxy) 114 context.addMockServiceResolver( 115 TestableContext.MockServiceResolver { 116 if (it.action == ACTION_QUICKSTEP) serviceComponent else null 117 } 118 ) 119 whenever(overviewProxy.queryLocalInterface(ArgumentMatchers.anyString())) 120 .thenReturn(overviewProxy) 121 whenever(overviewProxy.asBinder()).thenReturn(overviewProxy) 122 123 // packageManager.resolveServiceAsUser has to return non-null for 124 // OverviewProxyService#isEnabled to become true. 125 context.setMockPackageManager(packageManager) 126 whenever(packageManager.resolveServiceAsUser(any(), anyInt(), anyInt())) 127 .thenReturn(mock(ResolveInfo::class.java)) 128 129 subject = 130 OverviewProxyService( 131 context, 132 executor, 133 commandQueue, 134 shellInterface, 135 { navBarController }, 136 { Optional.of(centralSurfaces) }, 137 { shadeViewController }, 138 navModeController, 139 statusBarWinController, 140 sysUiState, 141 mock(), 142 userTracker, 143 wakefulnessLifecycle, 144 uiEventLogger, 145 displayTracker, 146 sysuiUnlockAnimationController, 147 assistUtils, 148 featureFlags, 149 dumpManager, 150 unfoldTransitionProgressForwarder 151 ) 152 } 153 154 @After 155 fun tearDown() { 156 subject.shutdownForTest() 157 } 158 159 @Test 160 fun wakefulnessLifecycle_dispatchFinishedWakingUpSetsSysUIflagToAWAKE() { 161 // WakefulnessLifecycle is initialized to AWAKE initially, and won't emit a noop. 162 wakefulnessLifecycle.dispatchFinishedGoingToSleep() 163 clearInvocations(overviewProxy) 164 165 wakefulnessLifecycle.dispatchFinishedWakingUp() 166 167 verify(overviewProxy) 168 .onSystemUiStateChanged( 169 intThat { it and SYSUI_STATE_WAKEFULNESS_MASK == WAKEFULNESS_AWAKE } 170 ) 171 } 172 173 @Test 174 fun wakefulnessLifecycle_dispatchStartedWakingUpSetsSysUIflagToWAKING() { 175 wakefulnessLifecycle.dispatchStartedWakingUp(PowerManager.WAKE_REASON_UNKNOWN) 176 177 verify(overviewProxy) 178 .onSystemUiStateChanged( 179 intThat { it and SYSUI_STATE_WAKEFULNESS_MASK == WAKEFULNESS_WAKING } 180 ) 181 } 182 183 @Test 184 fun wakefulnessLifecycle_dispatchFinishedGoingToSleepSetsSysUIflagToASLEEP() { 185 wakefulnessLifecycle.dispatchFinishedGoingToSleep() 186 187 verify(overviewProxy) 188 .onSystemUiStateChanged( 189 intThat { it and SYSUI_STATE_WAKEFULNESS_MASK == WAKEFULNESS_ASLEEP } 190 ) 191 } 192 193 @Test 194 fun wakefulnessLifecycle_dispatchStartedGoingToSleepSetsSysUIflagToGOING_TO_SLEEP() { 195 wakefulnessLifecycle.dispatchStartedGoingToSleep( 196 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON 197 ) 198 199 verify(overviewProxy) 200 .onSystemUiStateChanged( 201 intThat { it and SYSUI_STATE_WAKEFULNESS_MASK == WAKEFULNESS_GOING_TO_SLEEP } 202 ) 203 } 204 } 205