1 /*
2  * Copyright (C) 2020 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.navigationbar;
18 
19 import static android.view.Display.DEFAULT_DISPLAY;
20 import static android.view.Display.INVALID_DISPLAY;
21 
22 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
23 
24 import static org.mockito.ArgumentMatchers.any;
25 import static org.mockito.ArgumentMatchers.anyBoolean;
26 import static org.mockito.ArgumentMatchers.anyInt;
27 import static org.mockito.ArgumentMatchers.anyLong;
28 import static org.mockito.ArgumentMatchers.argThat;
29 import static org.mockito.ArgumentMatchers.eq;
30 import static org.mockito.Mockito.doNothing;
31 import static org.mockito.Mockito.doReturn;
32 import static org.mockito.Mockito.mock;
33 import static org.mockito.Mockito.never;
34 import static org.mockito.Mockito.spy;
35 import static org.mockito.Mockito.times;
36 import static org.mockito.Mockito.verify;
37 import static org.mockito.Mockito.when;
38 
39 import android.content.res.Configuration;
40 import android.testing.AndroidTestingRunner;
41 import android.testing.TestableLooper.RunWithLooper;
42 import android.util.SparseArray;
43 
44 import androidx.test.filters.SmallTest;
45 
46 import com.android.dx.mockito.inline.extended.StaticMockitoSession;
47 import com.android.systemui.Dependency;
48 import com.android.systemui.SysuiTestCase;
49 import com.android.systemui.dump.DumpManager;
50 import com.android.systemui.flags.FeatureFlags;
51 import com.android.systemui.model.SysUiState;
52 import com.android.systemui.recents.OverviewProxyService;
53 import com.android.systemui.settings.FakeDisplayTracker;
54 import com.android.systemui.shared.recents.utilities.Utilities;
55 import com.android.systemui.shared.system.TaskStackChangeListeners;
56 import com.android.systemui.statusbar.CommandQueue;
57 import com.android.systemui.statusbar.phone.AutoHideController;
58 import com.android.systemui.statusbar.phone.LightBarController;
59 import com.android.systemui.statusbar.policy.ConfigurationController;
60 import com.android.systemui.util.settings.SecureSettings;
61 import com.android.wm.shell.back.BackAnimation;
62 import com.android.wm.shell.pip.Pip;
63 
64 import org.junit.After;
65 import org.junit.Before;
66 import org.junit.Test;
67 import org.junit.runner.RunWith;
68 import org.mockito.Mock;
69 import org.mockito.MockitoAnnotations;
70 
71 import java.util.Optional;
72 
73 /** atest NavigationBarControllerTest */
74 @RunWith(AndroidTestingRunner.class)
75 @RunWithLooper
76 @SmallTest
77 public class NavigationBarControllerTest extends SysuiTestCase {
78 
79     private static final int SECONDARY_DISPLAY = 1;
80 
81     private NavigationBarController mNavigationBarController;
82     private NavigationBar mDefaultNavBar;
83     private NavigationBar mSecondaryNavBar;
84     private StaticMockitoSession mMockitoSession;
85     private FakeDisplayTracker mDisplayTracker = new FakeDisplayTracker(mContext);
86 
87     @Mock
88     private CommandQueue mCommandQueue;
89     @Mock
90     private NavigationBarComponent.Factory mNavigationBarFactory;
91     @Mock
92     TaskbarDelegate mTaskbarDelegate;
93 
94     @Before
setUp()95     public void setUp() {
96         MockitoAnnotations.initMocks(this);
97         mNavigationBarController = spy(
98                 new NavigationBarController(mContext,
99                         mock(OverviewProxyService.class),
100                         mock(NavigationModeController.class),
101                         mock(SysUiState.class),
102                         mCommandQueue,
103                         Dependency.get(Dependency.MAIN_HANDLER),
104                         mock(ConfigurationController.class),
105                         mock(NavBarHelper.class),
106                         mTaskbarDelegate,
107                         mNavigationBarFactory,
108                         mock(DumpManager.class),
109                         mock(AutoHideController.class),
110                         mock(LightBarController.class),
111                         TaskStackChangeListeners.getTestInstance(),
112                         Optional.of(mock(Pip.class)),
113                         Optional.of(mock(BackAnimation.class)),
114                         mock(FeatureFlags.class),
115                         mock(SecureSettings.class),
116                         mDisplayTracker));
117         initializeNavigationBars();
118         mMockitoSession = mockitoSession().mockStatic(Utilities.class).startMocking();
119     }
120 
initializeNavigationBars()121     private void initializeNavigationBars() {
122         mNavigationBarController.mNavigationBars = mock(SparseArray.class);
123         mDefaultNavBar = mock(NavigationBar.class);
124         mDefaultNavBar.mDisplayId = DEFAULT_DISPLAY;
125         doReturn(mDefaultNavBar)
126                 .when(mNavigationBarController.mNavigationBars).get(DEFAULT_DISPLAY);
127 
128         mSecondaryNavBar = mock(NavigationBar.class);
129         mSecondaryNavBar.mDisplayId = SECONDARY_DISPLAY;
130         doReturn(mSecondaryNavBar)
131                 .when(mNavigationBarController.mNavigationBars).get(SECONDARY_DISPLAY);
132     }
133 
134     @After
tearDown()135     public void tearDown() {
136         mNavigationBarController = null;
137         mDefaultNavBar = null;
138         mSecondaryNavBar = null;
139         mMockitoSession.finishMocking();
140     }
141 
142     @Test
testCreateNavigationBarsIncludeDefaultTrue()143     public void testCreateNavigationBarsIncludeDefaultTrue() {
144         // Large screens may be using taskbar and the logic is different
145         mNavigationBarController.mIsLargeScreen = false;
146         doNothing().when(mNavigationBarController).createNavigationBar(any(), any(), any());
147 
148         mNavigationBarController.createNavigationBars(true, null);
149 
150         verify(mNavigationBarController).createNavigationBar(
151                 argThat(display -> display.getDisplayId() == DEFAULT_DISPLAY), any(), any());
152     }
153 
154     @Test
testCreateNavigationBarsIncludeDefaultFalse()155     public void testCreateNavigationBarsIncludeDefaultFalse() {
156         doNothing().when(mNavigationBarController).createNavigationBar(any(), any(), any());
157 
158         mNavigationBarController.createNavigationBars(false, null);
159 
160         verify(mNavigationBarController, never()).createNavigationBar(
161                 argThat(display -> display.getDisplayId() == DEFAULT_DISPLAY), any(), any());
162     }
163 
164     // Tests if NPE occurs when call checkNavBarModes() with invalid display.
165     @Test
testCheckNavBarModesWithInvalidDisplay()166     public void testCheckNavBarModesWithInvalidDisplay() {
167         mNavigationBarController.checkNavBarModes(INVALID_DISPLAY);
168     }
169 
170     @Test
testCheckNavBarModesWithDefaultDisplay()171     public void testCheckNavBarModesWithDefaultDisplay() {
172         doNothing().when(mDefaultNavBar).checkNavBarModes();
173 
174         mNavigationBarController.checkNavBarModes(DEFAULT_DISPLAY);
175 
176         verify(mDefaultNavBar).checkNavBarModes();
177     }
178 
179     @Test
testCheckNavBarModesWithSecondaryDisplay()180     public void testCheckNavBarModesWithSecondaryDisplay() {
181         doNothing().when(mSecondaryNavBar).checkNavBarModes();
182 
183         mNavigationBarController.checkNavBarModes(SECONDARY_DISPLAY);
184 
185         verify(mSecondaryNavBar).checkNavBarModes();
186     }
187 
188     // Tests if NPE occurs when call finishBarAnimations() with invalid display.
189     @Test
testFinishBarAnimationsWithInvalidDisplay()190     public void testFinishBarAnimationsWithInvalidDisplay() {
191         mNavigationBarController.finishBarAnimations(INVALID_DISPLAY);
192     }
193 
194     @Test
testFinishBarAnimationsWithDefaultDisplay()195     public void testFinishBarAnimationsWithDefaultDisplay() {
196         doNothing().when(mDefaultNavBar).finishBarAnimations();
197 
198         mNavigationBarController.finishBarAnimations(DEFAULT_DISPLAY);
199 
200         verify(mDefaultNavBar).finishBarAnimations();
201     }
202 
203     @Test
testFinishBarAnimationsWithSecondaryDisplay()204     public void testFinishBarAnimationsWithSecondaryDisplay() {
205         doNothing().when(mSecondaryNavBar).finishBarAnimations();
206 
207         mNavigationBarController.finishBarAnimations(SECONDARY_DISPLAY);
208 
209         verify(mSecondaryNavBar).finishBarAnimations();
210     }
211 
212     // Tests if NPE occurs when call touchAutoDim() with invalid display.
213     @Test
testTouchAutoDimWithInvalidDisplay()214     public void testTouchAutoDimWithInvalidDisplay() {
215         mNavigationBarController.touchAutoDim(INVALID_DISPLAY);
216     }
217 
218     @Test
testTouchAutoDimWithDefaultDisplay()219     public void testTouchAutoDimWithDefaultDisplay() {
220         doNothing().when(mDefaultNavBar).touchAutoDim();
221 
222         mNavigationBarController.touchAutoDim(DEFAULT_DISPLAY);
223 
224         verify(mDefaultNavBar).touchAutoDim();
225     }
226 
227     @Test
testTouchAutoDimWithSecondaryDisplay()228     public void testTouchAutoDimWithSecondaryDisplay() {
229         doNothing().when(mSecondaryNavBar).touchAutoDim();
230 
231         mNavigationBarController.touchAutoDim(SECONDARY_DISPLAY);
232 
233         verify(mSecondaryNavBar).touchAutoDim();
234     }
235 
236     // Tests if NPE occurs when call transitionTo() with invalid display.
237     @Test
testTransitionToWithInvalidDisplay()238     public void testTransitionToWithInvalidDisplay() {
239         mNavigationBarController.transitionTo(INVALID_DISPLAY, 3, true);
240     }
241 
242     @Test
testTransitionToWithDefaultDisplay()243     public void testTransitionToWithDefaultDisplay() {
244         doNothing().when(mDefaultNavBar).transitionTo(anyInt(), anyBoolean());
245 
246         mNavigationBarController.transitionTo(DEFAULT_DISPLAY, 3, true);
247 
248         verify(mDefaultNavBar).transitionTo(eq(3), eq(true));
249     }
250 
251     @Test
testTransitionToWithSecondaryDisplay()252     public void testTransitionToWithSecondaryDisplay() {
253         doNothing().when(mSecondaryNavBar).transitionTo(anyInt(), anyBoolean());
254 
255         mNavigationBarController.transitionTo(SECONDARY_DISPLAY, 3, true);
256 
257         verify(mSecondaryNavBar).transitionTo(eq(3), eq(true));
258     }
259 
260     // Tests if NPE occurs when call disableAnimationsDuringHide() with invalid display.
261     @Test
testDisableAnimationsDuringHideWithInvalidDisplay()262     public void testDisableAnimationsDuringHideWithInvalidDisplay() {
263         mNavigationBarController.disableAnimationsDuringHide(INVALID_DISPLAY, 500L);
264     }
265 
266     @Test
testDisableAnimationsDuringHideWithDefaultDisplay()267     public void testDisableAnimationsDuringHideWithDefaultDisplay() {
268         doNothing().when(mDefaultNavBar).disableAnimationsDuringHide(anyLong());
269 
270         mNavigationBarController.disableAnimationsDuringHide(DEFAULT_DISPLAY, 500L);
271 
272         verify(mDefaultNavBar).disableAnimationsDuringHide(eq(500L));
273     }
274 
275     @Test
testDisableAnimationsDuringHideWithSecondaryDisplay()276     public void testDisableAnimationsDuringHideWithSecondaryDisplay() {
277         doNothing().when(mSecondaryNavBar).disableAnimationsDuringHide(anyLong());
278 
279         mNavigationBarController.disableAnimationsDuringHide(SECONDARY_DISPLAY, 500L);
280 
281         verify(mSecondaryNavBar).disableAnimationsDuringHide(eq(500L));
282     }
283 
284     @Test
test3ButtonTaskbarFlagDisabledNoRegister()285     public void test3ButtonTaskbarFlagDisabledNoRegister() {
286         verify(mCommandQueue, never()).addCallback(any(TaskbarDelegate.class));
287     }
288 
289 
290     @Test
testConfigurationChange_taskbarNotInitialized()291     public void testConfigurationChange_taskbarNotInitialized() {
292         Configuration configuration = mContext.getResources().getConfiguration();
293         when(Utilities.isLargeScreen(any())).thenReturn(true);
294         mNavigationBarController.onConfigChanged(configuration);
295         verify(mTaskbarDelegate, never()).onConfigurationChanged(configuration);
296     }
297 
298     @Test
testConfigurationChange_taskbarInitialized()299     public void testConfigurationChange_taskbarInitialized() {
300         Configuration configuration = mContext.getResources().getConfiguration();
301         when(Utilities.isLargeScreen(any())).thenReturn(true);
302         when(mTaskbarDelegate.isInitialized()).thenReturn(true);
303         mNavigationBarController.onConfigChanged(configuration);
304         verify(mTaskbarDelegate, times(1)).onConfigurationChanged(configuration);
305     }
306 }
307