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