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.shade;
18 
19 import static org.mockito.ArgumentMatchers.any;
20 import static org.mockito.ArgumentMatchers.anyInt;
21 import static org.mockito.Mockito.doAnswer;
22 import static org.mockito.Mockito.mock;
23 import static org.mockito.Mockito.when;
24 
25 import android.content.res.Resources;
26 import android.os.Handler;
27 import android.os.Looper;
28 import android.view.ViewGroup;
29 import android.view.ViewParent;
30 import android.view.accessibility.AccessibilityManager;
31 
32 import com.android.internal.jank.InteractionJankMonitor;
33 import com.android.internal.logging.MetricsLogger;
34 import com.android.internal.logging.UiEventLogger;
35 import com.android.keyguard.KeyguardStatusView;
36 import com.android.keyguard.KeyguardUpdateMonitor;
37 import com.android.keyguard.TestScopeProvider;
38 import com.android.systemui.R;
39 import com.android.systemui.SysuiTestCase;
40 import com.android.systemui.classifier.FalsingCollector;
41 import com.android.systemui.dump.DumpManager;
42 import com.android.systemui.flags.FeatureFlags;
43 import com.android.systemui.fragments.FragmentHostManager;
44 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
45 import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
46 import com.android.systemui.media.controls.pipeline.MediaDataManager;
47 import com.android.systemui.media.controls.ui.MediaHierarchyManager;
48 import com.android.systemui.plugins.FalsingManager;
49 import com.android.systemui.plugins.qs.QS;
50 import com.android.systemui.qs.QSFragment;
51 import com.android.systemui.screenrecord.RecordingController;
52 import com.android.systemui.shade.data.repository.ShadeRepository;
53 import com.android.systemui.shade.domain.interactor.ShadeInteractor;
54 import com.android.systemui.shade.transition.ShadeTransitionController;
55 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
56 import com.android.systemui.statusbar.NotificationRemoteInputManager;
57 import com.android.systemui.statusbar.NotificationShadeDepthController;
58 import com.android.systemui.statusbar.PulseExpansionHandler;
59 import com.android.systemui.statusbar.QsFrameTranslateController;
60 import com.android.systemui.statusbar.StatusBarStateControllerImpl;
61 import com.android.systemui.statusbar.SysuiStatusBarStateController;
62 import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository;
63 import com.android.systemui.statusbar.notification.stack.AmbientState;
64 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
65 import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
66 import com.android.systemui.statusbar.phone.KeyguardBypassController;
67 import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
68 import com.android.systemui.statusbar.phone.LightBarController;
69 import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
70 import com.android.systemui.statusbar.phone.ScrimController;
71 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
72 import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
73 import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository;
74 import com.android.systemui.statusbar.policy.CastController;
75 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
76 import com.android.systemui.statusbar.policy.KeyguardStateController;
77 import com.android.systemui.user.domain.interactor.UserInteractor;
78 import com.android.systemui.util.kotlin.JavaAdapter;
79 
80 import dagger.Lazy;
81 
82 import org.junit.After;
83 import org.junit.Before;
84 import org.mockito.Mock;
85 import org.mockito.MockitoAnnotations;
86 
87 import kotlinx.coroutines.test.TestScope;
88 
89 public class QuickSettingsControllerBaseTest extends SysuiTestCase {
90     protected static final float QS_FRAME_START_X = 0f;
91     protected static final int QS_FRAME_WIDTH = 1000;
92     protected static final int QS_FRAME_TOP = 0;
93     protected static final int QS_FRAME_BOTTOM = 1000;
94     protected static final int DEFAULT_HEIGHT = 1000;
95     // In split shade min = max
96     protected static final int DEFAULT_MIN_HEIGHT_SPLIT_SHADE = DEFAULT_HEIGHT;
97     protected static final int DEFAULT_MIN_HEIGHT = 300;
98 
99     protected QuickSettingsController mQsController;
100 
101     protected TestScope mTestScope = TestScopeProvider.getTestScope();
102 
103     @Mock
104     protected Resources mResources;
105     @Mock protected KeyguardBottomAreaView mQsFrame;
106     @Mock protected KeyguardStatusBarView mKeyguardStatusBar;
107     @Mock protected QS mQs;
108     @Mock protected QSFragment mQSFragment;
109     @Mock protected Lazy<NotificationPanelViewController> mPanelViewControllerLazy;
110     @Mock protected NotificationPanelViewController mNotificationPanelViewController;
111     @Mock protected NotificationPanelView mPanelView;
112     @Mock protected ViewGroup mQsHeader;
113     @Mock protected ViewParent mPanelViewParent;
114     @Mock protected QsFrameTranslateController mQsFrameTranslateController;
115     @Mock protected ShadeTransitionController mShadeTransitionController;
116     @Mock protected PulseExpansionHandler mPulseExpansionHandler;
117     @Mock protected NotificationRemoteInputManager mNotificationRemoteInputManager;
118     @Mock protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
119     @Mock protected LightBarController mLightBarController;
120     @Mock protected NotificationStackScrollLayoutController
121             mNotificationStackScrollLayoutController;
122     @Mock protected LockscreenShadeTransitionController mLockscreenShadeTransitionController;
123     @Mock protected NotificationShadeDepthController mNotificationShadeDepthController;
124     @Mock protected ShadeHeaderController mShadeHeaderController;
125     @Mock protected StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
126     @Mock protected KeyguardStateController mKeyguardStateController;
127     @Mock protected KeyguardBypassController mKeyguardBypassController;
128     @Mock protected KeyguardUpdateMonitor mKeyguardUpdateMonitor;
129     @Mock protected ScrimController mScrimController;
130     @Mock protected MediaDataManager mMediaDataManager;
131     @Mock protected MediaHierarchyManager mMediaHierarchyManager;
132     @Mock protected AmbientState mAmbientState;
133     @Mock protected RecordingController mRecordingController;
134     @Mock protected FalsingManager mFalsingManager;
135     @Mock protected FalsingCollector mFalsingCollector;
136     @Mock protected AccessibilityManager mAccessibilityManager;
137     @Mock protected LockscreenGestureLogger mLockscreenGestureLogger;
138     @Mock protected MetricsLogger mMetricsLogger;
139     @Mock protected FeatureFlags mFeatureFlags;
140     @Mock protected InteractionJankMonitor mInteractionJankMonitor;
141     @Mock protected ShadeLogger mShadeLogger;
142     @Mock protected DumpManager mDumpManager;
143     @Mock protected UiEventLogger mUiEventLogger;
144     @Mock protected CastController mCastController;
145     @Mock protected DeviceProvisionedController mDeviceProvisionedController;
146     @Mock protected UserInteractor mUserInteractor;
147     protected FakeDisableFlagsRepository mDisableFlagsRepository =
148             new FakeDisableFlagsRepository();
149     protected FakeKeyguardRepository mKeyguardRepository = new FakeKeyguardRepository();
150 
151     protected SysuiStatusBarStateController mStatusBarStateController;
152     protected ShadeInteractor mShadeInteractor;
153 
154     protected Handler mMainHandler;
155     protected LockscreenShadeTransitionController.Callback mLockscreenShadeTransitionCallback;
156 
157     protected final ShadeExpansionStateManager mShadeExpansionStateManager =
158             new ShadeExpansionStateManager();
159 
160     protected FragmentHostManager.FragmentListener mFragmentListener;
161 
162     @Before
setup()163     public void setup() {
164         MockitoAnnotations.initMocks(this);
165         when(mPanelViewControllerLazy.get()).thenReturn(mNotificationPanelViewController);
166         mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, mDumpManager,
167                 mInteractionJankMonitor, mShadeExpansionStateManager);
168 
169         when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
170         mShadeInteractor =
171                 new ShadeInteractor(
172                         mTestScope.getBackgroundScope(),
173                         mDisableFlagsRepository,
174                         mKeyguardRepository,
175                         new FakeUserSetupRepository(),
176                         mDeviceProvisionedController,
177                         mUserInteractor
178                 );
179 
180         KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext);
181         keyguardStatusView.setId(R.id.keyguard_status_view);
182 
183         when(mResources.getDimensionPixelSize(
184                 R.dimen.lockscreen_shade_qs_transition_distance)).thenReturn(DEFAULT_HEIGHT);
185         when(mPanelView.getResources()).thenReturn(mResources);
186         when(mPanelView.getContext()).thenReturn(getContext());
187         when(mPanelView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
188         when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(1000);
189         when(mPanelView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame);
190         when(mQsFrame.getX()).thenReturn(QS_FRAME_START_X);
191         when(mQsFrame.getWidth()).thenReturn(QS_FRAME_WIDTH);
192         when(mQsHeader.getTop()).thenReturn(QS_FRAME_TOP);
193         when(mQsHeader.getBottom()).thenReturn(QS_FRAME_BOTTOM);
194         when(mPanelView.getY()).thenReturn((float) QS_FRAME_TOP);
195         when(mPanelView.getHeight()).thenReturn(QS_FRAME_BOTTOM);
196         when(mPanelView.findViewById(R.id.keyguard_status_view))
197                 .thenReturn(mock(KeyguardStatusView.class));
198         when(mQs.getView()).thenReturn(mPanelView);
199         when(mQSFragment.getView()).thenReturn(mPanelView);
200 
201         when(mNotificationRemoteInputManager.isRemoteInputActive())
202                 .thenReturn(false);
203         when(mInteractionJankMonitor.begin(any(), anyInt()))
204                 .thenReturn(true);
205         when(mInteractionJankMonitor.end(anyInt()))
206                 .thenReturn(true);
207 
208         when(mPanelView.getParent()).thenReturn(mPanelViewParent);
209         when(mQs.getHeader()).thenReturn(mQsHeader);
210 
211         doAnswer(invocation -> {
212             mLockscreenShadeTransitionCallback = invocation.getArgument(0);
213             return null;
214         }).when(mLockscreenShadeTransitionController).addCallback(any());
215 
216 
217         mMainHandler = new Handler(Looper.getMainLooper());
218 
219         mQsController = new QuickSettingsController(
220                 mPanelViewControllerLazy,
221                 mPanelView,
222                 mQsFrameTranslateController,
223                 mShadeTransitionController,
224                 mPulseExpansionHandler,
225                 mNotificationRemoteInputManager,
226                 mShadeExpansionStateManager,
227                 mStatusBarKeyguardViewManager,
228                 mLightBarController,
229                 mNotificationStackScrollLayoutController,
230                 mLockscreenShadeTransitionController,
231                 mNotificationShadeDepthController,
232                 mShadeHeaderController,
233                 mStatusBarTouchableRegionManager,
234                 mKeyguardStateController,
235                 mKeyguardBypassController,
236                 mKeyguardUpdateMonitor,
237                 mScrimController,
238                 mMediaDataManager,
239                 mMediaHierarchyManager,
240                 mAmbientState,
241                 mRecordingController,
242                 mFalsingManager,
243                 mFalsingCollector,
244                 mAccessibilityManager,
245                 mLockscreenGestureLogger,
246                 mMetricsLogger,
247                 mFeatureFlags,
248                 mInteractionJankMonitor,
249                 mShadeLogger,
250                 mDumpManager,
251                 mock(KeyguardFaceAuthInteractor.class),
252                 mock(ShadeRepository.class),
253                 mShadeInteractor,
254                 new JavaAdapter(mTestScope.getBackgroundScope()),
255                 mCastController
256         );
257         mQsController.init();
258 
259         mFragmentListener = mQsController.getQsFragmentListener();
260     }
261 
262     @After
tearDown()263     public void tearDown() {
264         mMainHandler.removeCallbacksAndMessages(null);
265     }
266 }
267