blob: f01c0b421ef7b8143c0f9fe80d5ab73ba6294b68 [file] [log] [blame]
Kunhung Li29007e62018-07-30 19:30:25 +08001/*
2 * Copyright (C) 2018 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
17package com.android.keyguard;
18
19import static android.view.View.GONE;
20import static android.view.View.VISIBLE;
21
22import static com.google.common.truth.Truth.assertThat;
23
24import static org.mockito.Mockito.doReturn;
25import static org.mockito.Mockito.mock;
Robert Snoeberger33ce6d92018-10-26 10:52:38 -040026import static org.mockito.Mockito.never;
Kunhung Li29007e62018-07-30 19:30:25 +080027import static org.mockito.Mockito.verify;
Kunhung Li29007e62018-07-30 19:30:25 +080028import static org.mockito.Mockito.when;
29
30import android.graphics.Color;
31import android.graphics.Paint.Style;
32import android.test.suitebuilder.annotation.SmallTest;
33import android.testing.AndroidTestingRunner;
34import android.testing.TestableLooper.RunWithLooper;
35import android.text.TextPaint;
36import android.view.LayoutInflater;
Robert Snoeberger60854082019-01-04 13:13:17 -050037import android.view.View;
Robert Snoebergere3b3e782018-12-17 13:32:15 -050038import android.widget.FrameLayout;
Kunhung Li29007e62018-07-30 19:30:25 +080039import android.widget.TextClock;
40
Robert Snoeberger15b4af12019-01-18 15:37:27 -050041import com.android.keyguard.clock.ClockManager;
Robert Snoebergerbe35b762019-03-15 14:33:02 -040042import com.android.systemui.SystemUIFactory;
Kunhung Li29007e62018-07-30 19:30:25 +080043import com.android.systemui.SysuiTestCase;
44import com.android.systemui.plugins.ClockPlugin;
Beverly8fdb5332019-02-04 14:29:49 -050045import com.android.systemui.plugins.statusbar.StatusBarStateController;
Robert Snoeberger60854082019-01-04 13:13:17 -050046import com.android.systemui.statusbar.StatusBarState;
Robert Snoebergerbe35b762019-03-15 14:33:02 -040047import com.android.systemui.util.InjectionInflationController;
Kunhung Li29007e62018-07-30 19:30:25 +080048
49import org.junit.Before;
50import org.junit.Test;
51import org.junit.runner.RunWith;
Kunhung Li29007e62018-07-30 19:30:25 +080052import org.mockito.InjectMocks;
53import org.mockito.Mock;
54import org.mockito.MockitoAnnotations;
55
56@SmallTest
Kunhung Li29007e62018-07-30 19:30:25 +080057@RunWith(AndroidTestingRunner.class)
Robert Snoebergere3b3e782018-12-17 13:32:15 -050058// Need to run on the main thread because KeyguardSliceView$Row init checks for
59// the main thread before acquiring a wake lock. This class is constructed when
60// the keyguard_clcok_switch layout is inflated.
61@RunWithLooper(setAsMainLooper = true)
Kunhung Li29007e62018-07-30 19:30:25 +080062public class KeyguardClockSwitchTest extends SysuiTestCase {
Robert Snoebergere3b3e782018-12-17 13:32:15 -050063 private FrameLayout mClockContainer;
Robert Snoebergera1df7fb2019-02-11 14:00:14 -050064 private FrameLayout mBigClockContainer;
65 private TextClock mBigClock;
Robert Snoeberger60854082019-01-04 13:13:17 -050066 private StatusBarStateController.StateListener mStateListener;
Kunhung Li29007e62018-07-30 19:30:25 +080067
68 @Mock
69 TextClock mClockView;
70 @InjectMocks
71 KeyguardClockSwitch mKeyguardClockSwitch;
72
73 @Before
74 public void setUp() {
Robert Snoebergerbe35b762019-03-15 14:33:02 -040075 InjectionInflationController inflationController = new InjectionInflationController(
76 SystemUIFactory.getInstance().getRootComponent());
77 LayoutInflater layoutInflater = inflationController
78 .injectable(LayoutInflater.from(getContext()));
Kunhung Li29007e62018-07-30 19:30:25 +080079 mKeyguardClockSwitch =
80 (KeyguardClockSwitch) layoutInflater.inflate(R.layout.keyguard_clock_switch, null);
Robert Snoebergere3b3e782018-12-17 13:32:15 -050081 mClockContainer = mKeyguardClockSwitch.findViewById(R.id.clock_view);
Robert Snoebergera1df7fb2019-02-11 14:00:14 -050082 mBigClockContainer = new FrameLayout(getContext());
83 mBigClock = new TextClock(getContext());
Kunhung Li29007e62018-07-30 19:30:25 +080084 MockitoAnnotations.initMocks(this);
Robert Snoeberger33ce6d92018-10-26 10:52:38 -040085 when(mClockView.getPaint()).thenReturn(mock(TextPaint.class));
Robert Snoeberger60854082019-01-04 13:13:17 -050086 mStateListener = mKeyguardClockSwitch.getStateListener();
Kunhung Li29007e62018-07-30 19:30:25 +080087 }
88
89 @Test
Kunhung Li29007e62018-07-30 19:30:25 +080090 public void onPluginConnected_showPluginClock() {
91 ClockPlugin plugin = mock(ClockPlugin.class);
92 TextClock pluginView = new TextClock(getContext());
93 when(plugin.getView()).thenReturn(pluginView);
Kunhung Li29007e62018-07-30 19:30:25 +080094
Robert Snoeberger15b4af12019-01-18 15:37:27 -050095 mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
Kunhung Li29007e62018-07-30 19:30:25 +080096
97 verify(mClockView).setVisibility(GONE);
Robert Snoebergere3b3e782018-12-17 13:32:15 -050098 assertThat(plugin.getView().getParent()).isEqualTo(mClockContainer);
Kunhung Li29007e62018-07-30 19:30:25 +080099 }
100
101 @Test
Robert Snoeberger6a0140a2018-12-20 12:46:17 -0500102 public void onPluginConnected_showPluginBigClock() {
103 // GIVEN that the container for the big clock has visibility GONE
Robert Snoebergera1df7fb2019-02-11 14:00:14 -0500104 mBigClockContainer.setVisibility(GONE);
105 mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
Robert Snoeberger6a0140a2018-12-20 12:46:17 -0500106 // AND the plugin returns a view for the big clock
107 ClockPlugin plugin = mock(ClockPlugin.class);
Robert Snoebergera1df7fb2019-02-11 14:00:14 -0500108 when(plugin.getBigClockView()).thenReturn(mBigClock);
Robert Snoeberger98312392019-03-15 16:53:51 -0400109 // AND in the keyguard state
110 mStateListener.onStateChanged(StatusBarState.KEYGUARD);
Robert Snoeberger6a0140a2018-12-20 12:46:17 -0500111 // WHEN the plugin is connected
Robert Snoeberger15b4af12019-01-18 15:37:27 -0500112 mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
Robert Snoeberger6a0140a2018-12-20 12:46:17 -0500113 // THEN the big clock container is visible and it is the parent of the
114 // big clock view.
Robert Snoebergera1df7fb2019-02-11 14:00:14 -0500115 assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.VISIBLE);
116 assertThat(mBigClock.getParent()).isEqualTo(mBigClockContainer);
Robert Snoeberger6a0140a2018-12-20 12:46:17 -0500117 }
118
119 @Test
Robert Snoeberger33ce6d92018-10-26 10:52:38 -0400120 public void onPluginConnected_nullView() {
121 ClockPlugin plugin = mock(ClockPlugin.class);
Robert Snoeberger15b4af12019-01-18 15:37:27 -0500122 mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
Robert Snoeberger33ce6d92018-10-26 10:52:38 -0400123 verify(mClockView, never()).setVisibility(GONE);
124 }
125
126 @Test
127 public void onPluginConnected_showSecondPluginClock() {
128 // GIVEN a plugin has already connected
129 ClockPlugin plugin1 = mock(ClockPlugin.class);
130 when(plugin1.getView()).thenReturn(new TextClock(getContext()));
Robert Snoeberger15b4af12019-01-18 15:37:27 -0500131 mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin1);
Robert Snoeberger33ce6d92018-10-26 10:52:38 -0400132 // WHEN a second plugin is connected
133 ClockPlugin plugin2 = mock(ClockPlugin.class);
134 when(plugin2.getView()).thenReturn(new TextClock(getContext()));
Robert Snoeberger15b4af12019-01-18 15:37:27 -0500135 mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin2);
Robert Snoeberger33ce6d92018-10-26 10:52:38 -0400136 // THEN only the view from the second plugin should be a child of KeyguardClockSwitch.
Robert Snoebergere3b3e782018-12-17 13:32:15 -0500137 assertThat(plugin2.getView().getParent()).isEqualTo(mClockContainer);
Robert Snoeberger33ce6d92018-10-26 10:52:38 -0400138 assertThat(plugin1.getView().getParent()).isNull();
139 }
140
141 @Test
Robert Snoeberger58f23152019-01-10 15:51:32 -0500142 public void onPluginConnected_darkAmountInitialized() {
143 // GIVEN that the dark amount has already been set
144 mKeyguardClockSwitch.setDarkAmount(0.5f);
145 // WHEN a plugin is connected
146 ClockPlugin plugin = mock(ClockPlugin.class);
Robert Snoeberger15b4af12019-01-18 15:37:27 -0500147 mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
Robert Snoeberger58f23152019-01-10 15:51:32 -0500148 // THEN dark amount should be initalized on the plugin.
149 verify(plugin).setDarkAmount(0.5f);
150 }
151
152 @Test
Kunhung Li29007e62018-07-30 19:30:25 +0800153 public void onPluginDisconnected_showDefaultClock() {
154 ClockPlugin plugin = mock(ClockPlugin.class);
155 TextClock pluginView = new TextClock(getContext());
156 when(plugin.getView()).thenReturn(pluginView);
157 mClockView.setVisibility(GONE);
Kunhung Li29007e62018-07-30 19:30:25 +0800158
Robert Snoeberger15b4af12019-01-18 15:37:27 -0500159 mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
160 mKeyguardClockSwitch.getClockChangedListener().onClockChanged(null);
Kunhung Li29007e62018-07-30 19:30:25 +0800161
162 verify(mClockView).setVisibility(VISIBLE);
163 assertThat(plugin.getView().getParent()).isNull();
164 }
165
166 @Test
Robert Snoeberger6a0140a2018-12-20 12:46:17 -0500167 public void onPluginDisconnected_hidePluginBigClock() {
168 // GIVEN that the big clock container is visible
169 FrameLayout bigClockContainer = new FrameLayout(getContext());
170 bigClockContainer.setVisibility(VISIBLE);
171 mKeyguardClockSwitch.setBigClockContainer(bigClockContainer);
172 // AND the plugin returns a view for the big clock
173 ClockPlugin plugin = mock(ClockPlugin.class);
174 TextClock pluginView = new TextClock(getContext());
175 when(plugin.getBigClockView()).thenReturn(pluginView);
Robert Snoeberger98312392019-03-15 16:53:51 -0400176 // AND in the keyguard state
177 mStateListener.onStateChanged(StatusBarState.KEYGUARD);
Robert Snoeberger8bf1a3c2019-01-10 10:30:09 -0500178 // WHEN the plugin is connected and then disconnected
Robert Snoeberger15b4af12019-01-18 15:37:27 -0500179 mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
180 mKeyguardClockSwitch.getClockChangedListener().onClockChanged(null);
Robert Snoeberger6a0140a2018-12-20 12:46:17 -0500181 // THEN the big lock container is GONE and the big clock view doesn't have
182 // a parent.
183 assertThat(bigClockContainer.getVisibility()).isEqualTo(GONE);
184 assertThat(pluginView.getParent()).isNull();
185 }
186
187 @Test
Robert Snoeberger33ce6d92018-10-26 10:52:38 -0400188 public void onPluginDisconnected_nullView() {
189 ClockPlugin plugin = mock(ClockPlugin.class);
Robert Snoeberger15b4af12019-01-18 15:37:27 -0500190 mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
191 mKeyguardClockSwitch.getClockChangedListener().onClockChanged(null);
Robert Snoeberger33ce6d92018-10-26 10:52:38 -0400192 verify(mClockView, never()).setVisibility(GONE);
193 }
194
195 @Test
Robert Snoeberger33ce6d92018-10-26 10:52:38 -0400196 public void onPluginDisconnected_secondOfTwoDisconnected() {
197 // GIVEN two plugins are connected
198 ClockPlugin plugin1 = mock(ClockPlugin.class);
199 when(plugin1.getView()).thenReturn(new TextClock(getContext()));
Robert Snoeberger15b4af12019-01-18 15:37:27 -0500200 ClockManager.ClockChangedListener listener = mKeyguardClockSwitch.getClockChangedListener();
201 listener.onClockChanged(plugin1);
Robert Snoeberger33ce6d92018-10-26 10:52:38 -0400202 ClockPlugin plugin2 = mock(ClockPlugin.class);
203 when(plugin2.getView()).thenReturn(new TextClock(getContext()));
Robert Snoeberger15b4af12019-01-18 15:37:27 -0500204 listener.onClockChanged(plugin2);
Robert Snoeberger33ce6d92018-10-26 10:52:38 -0400205 // WHEN the second plugin is disconnected
Robert Snoeberger15b4af12019-01-18 15:37:27 -0500206 listener.onClockChanged(null);
Robert Snoeberger33ce6d92018-10-26 10:52:38 -0400207 // THEN the default clock should be shown.
208 verify(mClockView).setVisibility(VISIBLE);
209 assertThat(plugin1.getView().getParent()).isNull();
210 assertThat(plugin2.getView().getParent()).isNull();
211 }
212
213 @Test
Robert Snoeberger3358cfb2019-04-03 13:09:55 -0400214 public void onPluginDisconnected_onDestroyView() {
215 // GIVEN a plugin is connected
216 ClockPlugin clockPlugin = mock(ClockPlugin.class);
217 when(clockPlugin.getView()).thenReturn(new TextClock(getContext()));
218 ClockManager.ClockChangedListener listener = mKeyguardClockSwitch.getClockChangedListener();
219 listener.onClockChanged(clockPlugin);
220 // WHEN the plugin is disconnected
221 listener.onClockChanged(null);
222 // THEN onDestroyView is called on the plugin
223 verify(clockPlugin).onDestroyView();
224 }
225
226 @Test
Kunhung Li29007e62018-07-30 19:30:25 +0800227 public void setTextColor_defaultClockSetTextColor() {
228 mKeyguardClockSwitch.setTextColor(Color.YELLOW);
229
230 verify(mClockView).setTextColor(Color.YELLOW);
231 }
232
233 @Test
234 public void setTextColor_pluginClockSetTextColor() {
235 ClockPlugin plugin = mock(ClockPlugin.class);
236 TextClock pluginView = new TextClock(getContext());
237 when(plugin.getView()).thenReturn(pluginView);
Robert Snoeberger15b4af12019-01-18 15:37:27 -0500238 mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
Kunhung Li29007e62018-07-30 19:30:25 +0800239
240 mKeyguardClockSwitch.setTextColor(Color.WHITE);
241
242 verify(plugin).setTextColor(Color.WHITE);
243 }
244
245 @Test
246 public void setStyle_defaultClockSetStyle() {
247 TextPaint paint = mock(TextPaint.class);
248 Style style = mock(Style.class);
249 doReturn(paint).when(mClockView).getPaint();
250
251 mKeyguardClockSwitch.setStyle(style);
252
253 verify(paint).setStyle(style);
254 }
255
256 @Test
257 public void setStyle_pluginClockSetStyle() {
258 ClockPlugin plugin = mock(ClockPlugin.class);
259 TextClock pluginView = new TextClock(getContext());
260 when(plugin.getView()).thenReturn(pluginView);
Kunhung Li29007e62018-07-30 19:30:25 +0800261 Style style = mock(Style.class);
Robert Snoeberger15b4af12019-01-18 15:37:27 -0500262 mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
Kunhung Li29007e62018-07-30 19:30:25 +0800263
264 mKeyguardClockSwitch.setStyle(style);
265
266 verify(plugin).setStyle(style);
267 }
Robert Snoeberger60854082019-01-04 13:13:17 -0500268
269 @Test
Robert Snoeberger98312392019-03-15 16:53:51 -0400270 public void onStateChanged_GoneInShade() {
Robert Snoeberger60854082019-01-04 13:13:17 -0500271 // GIVEN that the big clock container is visible
Robert Snoebergera1df7fb2019-02-11 14:00:14 -0500272 mBigClockContainer.setVisibility(View.VISIBLE);
273 mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
Robert Snoeberger60854082019-01-04 13:13:17 -0500274 // WHEN transitioned to SHADE state
275 mStateListener.onStateChanged(StatusBarState.SHADE);
Robert Snoeberger98312392019-03-15 16:53:51 -0400276 // THEN the container is gone.
277 assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.GONE);
Robert Snoeberger60854082019-01-04 13:13:17 -0500278 }
279
280 @Test
281 public void onStateChanged_VisibleInKeyguard() {
Robert Snoeberger98312392019-03-15 16:53:51 -0400282 // GIVEN that the big clock container is gone
283 mBigClockContainer.setVisibility(View.GONE);
Robert Snoebergera1df7fb2019-02-11 14:00:14 -0500284 mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
Robert Snoeberger98312392019-03-15 16:53:51 -0400285 // AND GIVEN that a plugin is active.
286 ClockPlugin plugin = mock(ClockPlugin.class);
287 when(plugin.getBigClockView()).thenReturn(mBigClock);
288 mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
Robert Snoeberger60854082019-01-04 13:13:17 -0500289 // WHEN transitioned to KEYGUARD state
290 mStateListener.onStateChanged(StatusBarState.KEYGUARD);
291 // THEN the container is visible.
Robert Snoebergera1df7fb2019-02-11 14:00:14 -0500292 assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.VISIBLE);
293 }
294
295 @Test
296 public void setBigClockContainer_visible() {
297 // GIVEN that the big clock container is visible
298 mBigClockContainer.setVisibility(View.VISIBLE);
299 // AND GIVEN that a plugin is active.
300 ClockPlugin plugin = mock(ClockPlugin.class);
301 when(plugin.getBigClockView()).thenReturn(mBigClock);
302 mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
Robert Snoeberger98312392019-03-15 16:53:51 -0400303 // AND in the keyguard state
304 mStateListener.onStateChanged(StatusBarState.KEYGUARD);
Robert Snoebergera1df7fb2019-02-11 14:00:14 -0500305 // WHEN the container is associated with the clock switch
306 mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
307 // THEN the container remains visible.
308 assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.VISIBLE);
309 }
310
311 @Test
Robert Snoebergera1df7fb2019-02-11 14:00:14 -0500312 public void setBigClockContainer_gone() {
313 // GIVEN that the big clock container is gone
314 mBigClockContainer.setVisibility(View.GONE);
315 // AND GIVEN that a plugin is active.
316 ClockPlugin plugin = mock(ClockPlugin.class);
317 when(plugin.getBigClockView()).thenReturn(mBigClock);
318 mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
Robert Snoeberger98312392019-03-15 16:53:51 -0400319 // AND in the keyguard state
320 mStateListener.onStateChanged(StatusBarState.KEYGUARD);
Robert Snoebergera1df7fb2019-02-11 14:00:14 -0500321 // WHEN the container is associated with the clock switch
322 mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
323 // THEN the container is made visible.
324 assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.VISIBLE);
Robert Snoeberger60854082019-01-04 13:13:17 -0500325 }
Kunhung Li29007e62018-07-30 19:30:25 +0800326}