• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.car.statusicon;
18 
19 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
20 
21 import static com.google.common.truth.Truth.assertThat;
22 
23 import static org.mockito.ArgumentMatchers.any;
24 import static org.mockito.Mockito.eq;
25 import static org.mockito.Mockito.mock;
26 import static org.mockito.Mockito.reset;
27 import static org.mockito.Mockito.spy;
28 import static org.mockito.Mockito.verify;
29 import static org.mockito.Mockito.when;
30 import static org.testng.Assert.assertThrows;
31 
32 import android.app.PendingIntent;
33 import android.content.Context;
34 import android.content.Intent;
35 import android.content.IntentFilter;
36 import android.os.UserHandle;
37 import android.test.suitebuilder.annotation.SmallTest;
38 import android.testing.AndroidTestingRunner;
39 import android.testing.TestableLooper;
40 import android.widget.ImageView;
41 
42 import com.android.car.qc.QCItem;
43 import com.android.car.ui.FocusParkingView;
44 import com.android.systemui.R;
45 import com.android.systemui.SysuiTestCase;
46 import com.android.systemui.broadcast.BroadcastDispatcher;
47 import com.android.systemui.car.CarServiceProvider;
48 import com.android.systemui.car.CarSystemUiTest;
49 import com.android.systemui.car.qc.SystemUIQCViewController;
50 import com.android.systemui.settings.UserTracker;
51 import com.android.systemui.statusbar.policy.ConfigurationController;
52 
53 import org.junit.After;
54 import org.junit.Before;
55 import org.junit.Test;
56 import org.junit.runner.RunWith;
57 import org.mockito.ArgumentCaptor;
58 import org.mockito.Mock;
59 import org.mockito.MockitoAnnotations;
60 
61 @CarSystemUiTest
62 @RunWith(AndroidTestingRunner.class)
63 @TestableLooper.RunWithLooper
64 @SmallTest
65 public class StatusIconPanelControllerTest extends SysuiTestCase {
66     private StatusIconPanelController mStatusIconPanelController;
67     private ImageView mAnchorView;
68     private String mIconTag;
69     private UserHandle mUserHandle;
70 
71     @Mock
72     private UserTracker mUserTracker;
73     @Mock
74     private CarServiceProvider mCarServiceProvider;
75     @Mock
76     private BroadcastDispatcher mBroadcastDispatcher;
77     @Mock
78     private ConfigurationController mConfigurationController;
79     @Mock
80     private SystemUIQCViewController mSystemUIQCViewController;
81 
82     @Before
setUp()83     public void setUp() {
84         MockitoAnnotations.initMocks(this);
85 
86         mContext = spy(mContext);
87         mIconTag = mContext.getResources().getString(R.string.qc_icon_tag);
88         mUserHandle = UserHandle.of(1000);
89         when(mUserTracker.getUserHandle()).thenReturn(mUserHandle);
90 
91         mStatusIconPanelController = new StatusIconPanelController(mContext, mUserTracker,
92                 mCarServiceProvider, mBroadcastDispatcher, mConfigurationController,
93                 () -> mSystemUIQCViewController);
94         spyOn(mStatusIconPanelController);
95         mAnchorView = spy(new ImageView(mContext));
96         mAnchorView.setTag(mIconTag);
97         mAnchorView.setImageDrawable(mContext.getDrawable(R.drawable.ic_bluetooth_status_off));
98         mAnchorView.setColorFilter(mStatusIconPanelController.getIconHighlightedColor());
99         reset(mAnchorView);
100         mStatusIconPanelController.attachPanel(mAnchorView, R.layout.qc_display_panel,
101                 R.dimen.car_status_icon_panel_default_width);
102     }
103 
104     @After
tearDown()105     public void tearDown() {
106         mStatusIconPanelController.destroyPanel();
107     }
108 
109     @Test
onPanelAnchorViewClicked_panelShowing()110     public void onPanelAnchorViewClicked_panelShowing() {
111         clickAnchorView();
112         waitForIdleSync();
113 
114         assertThat(mStatusIconPanelController.getPanel().isShowing()).isTrue();
115     }
116 
117     @Test
onPanelAnchorViewClicked_statusIconHighlighted()118     public void onPanelAnchorViewClicked_statusIconHighlighted() {
119         clickAnchorView();
120         waitForIdleSync();
121 
122         verify(mAnchorView).setColorFilter(mStatusIconPanelController.getIconHighlightedColor());
123     }
124 
125     @Test
onPanelAnchorViewClicked_panelShowing_panelDismissed()126     public void onPanelAnchorViewClicked_panelShowing_panelDismissed() {
127         clickAnchorView();
128 
129         clickAnchorView();
130         waitForIdleSync();
131 
132         assertThat(mStatusIconPanelController.getPanel().isShowing()).isFalse();
133     }
134 
135     @Test
onPanelAnchorViewClicked_panelShowing_statusIconNotHighlighted()136     public void onPanelAnchorViewClicked_panelShowing_statusIconNotHighlighted() {
137         clickAnchorView();
138 
139         clickAnchorView();
140         waitForIdleSync();
141 
142         verify(mAnchorView).setColorFilter(mStatusIconPanelController.getIconNotHighlightedColor());
143     }
144 
145     @Test
onPanelAnchorViewClicked_sendsIntentToDismissSystemDialogsWithIdentifier()146     public void onPanelAnchorViewClicked_sendsIntentToDismissSystemDialogsWithIdentifier() {
147         ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
148 
149         clickAnchorView();
150         waitForIdleSync();
151 
152         verify(mContext).sendBroadcastAsUser(argumentCaptor.capture(), eq(mUserHandle));
153         assertThat(argumentCaptor.getValue().getAction()).isEqualTo(
154                 Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
155         assertThat(argumentCaptor.getValue().getIdentifier()).isEqualTo(
156                 mStatusIconPanelController.getIdentifier());
157     }
158 
159     @Test
onDismissSystemDialogReceived_fromSelf_panelOpen_doesNotDismissPanel()160     public void onDismissSystemDialogReceived_fromSelf_panelOpen_doesNotDismissPanel() {
161         Intent intent = new Intent();
162         intent.setAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
163         intent.setIdentifier(mStatusIconPanelController.getIdentifier());
164         clickAnchorView();
165         waitForIdleSync();
166 
167         mStatusIconPanelController.getBroadcastReceiver().onReceive(mContext, intent);
168 
169         assertThat(mStatusIconPanelController.getPanel().isShowing()).isTrue();
170     }
171 
172     @Test
onDismissSystemDialogReceived_fromSelf_panelOpen_statusIconHighlighted()173     public void onDismissSystemDialogReceived_fromSelf_panelOpen_statusIconHighlighted() {
174         Intent intent = new Intent();
175         intent.setAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
176         intent.setIdentifier(mStatusIconPanelController.getIdentifier());
177         clickAnchorView();
178         waitForIdleSync();
179 
180         mStatusIconPanelController.getBroadcastReceiver().onReceive(mContext, intent);
181 
182         verify(mAnchorView).setColorFilter(mStatusIconPanelController.getIconHighlightedColor());
183     }
184 
185     @Test
onDismissSystemDialogReceived_notFromSelf_panelOpen_dismissesPanel()186     public void onDismissSystemDialogReceived_notFromSelf_panelOpen_dismissesPanel() {
187         Intent intent = new Intent();
188         intent.setAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
189         clickAnchorView();
190         waitForIdleSync();
191 
192         mStatusIconPanelController.getBroadcastReceiver().onReceive(mContext, intent);
193 
194         assertThat(mStatusIconPanelController.getPanel().isShowing()).isFalse();
195     }
196 
197     @Test
onDismissSystemDialogReceived_notFromSelf_panelOpen_statusIconNotHighlighted()198     public void onDismissSystemDialogReceived_notFromSelf_panelOpen_statusIconNotHighlighted() {
199         Intent intent = new Intent();
200         intent.setAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
201         clickAnchorView();
202         waitForIdleSync();
203 
204         mStatusIconPanelController.getBroadcastReceiver().onReceive(mContext, intent);
205 
206         verify(mAnchorView).setColorFilter(mStatusIconPanelController.getIconNotHighlightedColor());
207     }
208 
209     @Test
onDestroy_unregistersListeners()210     public void onDestroy_unregistersListeners() {
211         mStatusIconPanelController.destroyPanel();
212 
213         verify(mConfigurationController).removeCallback(any());
214         verify(mBroadcastDispatcher).unregisterReceiver(any());
215     }
216 
217     @Test
onDestroy_reAttach_throwsException()218     public void onDestroy_reAttach_throwsException() {
219         mStatusIconPanelController.destroyPanel();
220 
221         assertThrows(IllegalStateException.class, () -> mStatusIconPanelController.attachPanel(
222                 mAnchorView, R.layout.qc_display_panel,
223                 R.dimen.car_status_icon_panel_default_width));
224     }
225 
226     @Test
onLayoutDirectionChanged_recreatePanel()227     public void onLayoutDirectionChanged_recreatePanel() {
228         mStatusIconPanelController.getConfigurationListener()
229                 .onLayoutDirectionChanged(/* isLayoutRtl= */ true);
230 
231         assertThat(mStatusIconPanelController.getPanel()).isNotNull();
232     }
233 
234     @Test
onUserChanged_unregisterRegisterReceiver()235     public void onUserChanged_unregisterRegisterReceiver() {
236         int newUser = 999;
237         Context userContext = mock(Context.class);
238         reset(mBroadcastDispatcher);
239 
240         mStatusIconPanelController.getUserTrackerCallback()
241                 .onUserChanged(newUser, userContext);
242 
243         verify(mBroadcastDispatcher).unregisterReceiver(
244                 eq(mStatusIconPanelController.getBroadcastReceiver()));
245         verify(mBroadcastDispatcher).registerReceiver(
246                 eq(mStatusIconPanelController.getBroadcastReceiver()),
247                 any(IntentFilter.class), eq(null), eq(mUserHandle));
248     }
249 
250     @Test
onGlobalFocusChanged_panelShowing_panelDismissed()251     public void onGlobalFocusChanged_panelShowing_panelDismissed() {
252         FocusParkingView newFocusView = mock(FocusParkingView.class);
253         clickAnchorView();
254         waitForIdleSync();
255 
256         mStatusIconPanelController.getFocusChangeListener()
257                 .onGlobalFocusChanged(mAnchorView, newFocusView);
258 
259         assertThat(mStatusIconPanelController.getPanel().isShowing()).isFalse();
260     }
261 
262     @Test
onQCAction_pendingIntentAction_panelDismissed()263     public void onQCAction_pendingIntentAction_panelDismissed() {
264         QCItem qcItem = mock(QCItem.class);
265         PendingIntent action = mock(PendingIntent.class);
266         when(action.isActivity()).thenReturn(true);
267         clickAnchorView();
268         waitForIdleSync();
269 
270         mStatusIconPanelController.getQCActionListener().onQCAction(qcItem, action);
271 
272         assertThat(mStatusIconPanelController.getPanel().isShowing()).isFalse();
273     }
274 
275     @Test
onQCAction_actionHandler_panelDismissed()276     public void onQCAction_actionHandler_panelDismissed() {
277         QCItem qcItem = mock(QCItem.class);
278         QCItem.ActionHandler action = mock(QCItem.ActionHandler.class);
279         when(action.isActivity()).thenReturn(true);
280         clickAnchorView();
281         waitForIdleSync();
282 
283         mStatusIconPanelController.getQCActionListener().onQCAction(qcItem, action);
284 
285         assertThat(mStatusIconPanelController.getPanel().isShowing()).isFalse();
286     }
287 
clickAnchorView()288     private void clickAnchorView() {
289         mStatusIconPanelController.getOnClickListener().onClick(mAnchorView);
290     }
291 }
292