Home | History | Annotate | Download | only in keyguard
      1 /*
      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 
     17 package com.android.keyguard;
     18 
     19 import static android.view.View.GONE;
     20 import static android.view.View.VISIBLE;
     21 
     22 import static com.google.common.truth.Truth.assertThat;
     23 
     24 import static org.mockito.Mockito.doReturn;
     25 import static org.mockito.Mockito.mock;
     26 import static org.mockito.Mockito.never;
     27 import static org.mockito.Mockito.verify;
     28 import static org.mockito.Mockito.when;
     29 
     30 import android.graphics.Color;
     31 import android.graphics.Paint.Style;
     32 import android.test.suitebuilder.annotation.SmallTest;
     33 import android.testing.AndroidTestingRunner;
     34 import android.testing.TestableLooper.RunWithLooper;
     35 import android.text.TextPaint;
     36 import android.view.LayoutInflater;
     37 import android.view.View;
     38 import android.widget.FrameLayout;
     39 import android.widget.TextClock;
     40 
     41 import com.android.keyguard.clock.ClockManager;
     42 import com.android.systemui.SystemUIFactory;
     43 import com.android.systemui.SysuiTestCase;
     44 import com.android.systemui.plugins.ClockPlugin;
     45 import com.android.systemui.plugins.statusbar.StatusBarStateController;
     46 import com.android.systemui.statusbar.StatusBarState;
     47 import com.android.systemui.util.InjectionInflationController;
     48 
     49 import org.junit.Before;
     50 import org.junit.Test;
     51 import org.junit.runner.RunWith;
     52 import org.mockito.InjectMocks;
     53 import org.mockito.Mock;
     54 import org.mockito.MockitoAnnotations;
     55 
     56 @SmallTest
     57 @RunWith(AndroidTestingRunner.class)
     58 // 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)
     62 public class KeyguardClockSwitchTest extends SysuiTestCase {
     63     private FrameLayout mClockContainer;
     64     private FrameLayout mBigClockContainer;
     65     private TextClock mBigClock;
     66     private StatusBarStateController.StateListener mStateListener;
     67 
     68     @Mock
     69     TextClock mClockView;
     70     @InjectMocks
     71     KeyguardClockSwitch mKeyguardClockSwitch;
     72 
     73     @Before
     74     public void setUp() {
     75         InjectionInflationController inflationController = new InjectionInflationController(
     76                 SystemUIFactory.getInstance().getRootComponent());
     77         LayoutInflater layoutInflater = inflationController
     78                 .injectable(LayoutInflater.from(getContext()));
     79         mKeyguardClockSwitch =
     80                 (KeyguardClockSwitch) layoutInflater.inflate(R.layout.keyguard_clock_switch, null);
     81         mClockContainer = mKeyguardClockSwitch.findViewById(R.id.clock_view);
     82         mBigClockContainer = new FrameLayout(getContext());
     83         mBigClock = new TextClock(getContext());
     84         MockitoAnnotations.initMocks(this);
     85         when(mClockView.getPaint()).thenReturn(mock(TextPaint.class));
     86         mStateListener = mKeyguardClockSwitch.getStateListener();
     87     }
     88 
     89     @Test
     90     public void onPluginConnected_showPluginClock() {
     91         ClockPlugin plugin = mock(ClockPlugin.class);
     92         TextClock pluginView = new TextClock(getContext());
     93         when(plugin.getView()).thenReturn(pluginView);
     94 
     95         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
     96 
     97         verify(mClockView).setVisibility(GONE);
     98         assertThat(plugin.getView().getParent()).isEqualTo(mClockContainer);
     99     }
    100 
    101     @Test
    102     public void onPluginConnected_showPluginBigClock() {
    103         // GIVEN that the container for the big clock has visibility GONE
    104         mBigClockContainer.setVisibility(GONE);
    105         mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
    106         // AND the plugin returns a view for the big clock
    107         ClockPlugin plugin = mock(ClockPlugin.class);
    108         when(plugin.getBigClockView()).thenReturn(mBigClock);
    109         // AND in the keyguard state
    110         mStateListener.onStateChanged(StatusBarState.KEYGUARD);
    111         // WHEN the plugin is connected
    112         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
    113         // THEN the big clock container is visible and it is the parent of the
    114         // big clock view.
    115         assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.VISIBLE);
    116         assertThat(mBigClock.getParent()).isEqualTo(mBigClockContainer);
    117     }
    118 
    119     @Test
    120     public void onPluginConnected_nullView() {
    121         ClockPlugin plugin = mock(ClockPlugin.class);
    122         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
    123         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()));
    131         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin1);
    132         // WHEN a second plugin is connected
    133         ClockPlugin plugin2 = mock(ClockPlugin.class);
    134         when(plugin2.getView()).thenReturn(new TextClock(getContext()));
    135         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin2);
    136         // THEN only the view from the second plugin should be a child of KeyguardClockSwitch.
    137         assertThat(plugin2.getView().getParent()).isEqualTo(mClockContainer);
    138         assertThat(plugin1.getView().getParent()).isNull();
    139     }
    140 
    141     @Test
    142     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);
    147         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
    148         // THEN dark amount should be initalized on the plugin.
    149         verify(plugin).setDarkAmount(0.5f);
    150     }
    151 
    152     @Test
    153     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);
    158 
    159         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
    160         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(null);
    161 
    162         verify(mClockView).setVisibility(VISIBLE);
    163         assertThat(plugin.getView().getParent()).isNull();
    164     }
    165 
    166     @Test
    167     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);
    176         // AND in the keyguard state
    177         mStateListener.onStateChanged(StatusBarState.KEYGUARD);
    178         // WHEN the plugin is connected and then disconnected
    179         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
    180         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(null);
    181         // 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
    188     public void onPluginDisconnected_nullView() {
    189         ClockPlugin plugin = mock(ClockPlugin.class);
    190         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
    191         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(null);
    192         verify(mClockView, never()).setVisibility(GONE);
    193     }
    194 
    195     @Test
    196     public void onPluginDisconnected_secondOfTwoDisconnected() {
    197         // GIVEN two plugins are connected
    198         ClockPlugin plugin1 = mock(ClockPlugin.class);
    199         when(plugin1.getView()).thenReturn(new TextClock(getContext()));
    200         ClockManager.ClockChangedListener listener = mKeyguardClockSwitch.getClockChangedListener();
    201         listener.onClockChanged(plugin1);
    202         ClockPlugin plugin2 = mock(ClockPlugin.class);
    203         when(plugin2.getView()).thenReturn(new TextClock(getContext()));
    204         listener.onClockChanged(plugin2);
    205         // WHEN the second plugin is disconnected
    206         listener.onClockChanged(null);
    207         // 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
    214     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
    227     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);
    238         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
    239 
    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);
    261         Style style = mock(Style.class);
    262         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
    263 
    264         mKeyguardClockSwitch.setStyle(style);
    265 
    266         verify(plugin).setStyle(style);
    267     }
    268 
    269     @Test
    270     public void onStateChanged_GoneInShade() {
    271         // GIVEN that the big clock container is visible
    272         mBigClockContainer.setVisibility(View.VISIBLE);
    273         mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
    274         // WHEN transitioned to SHADE state
    275         mStateListener.onStateChanged(StatusBarState.SHADE);
    276         // THEN the container is gone.
    277         assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.GONE);
    278     }
    279 
    280     @Test
    281     public void onStateChanged_VisibleInKeyguard() {
    282         // GIVEN that the big clock container is gone
    283         mBigClockContainer.setVisibility(View.GONE);
    284         mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
    285         // AND GIVEN that a plugin is active.
    286         ClockPlugin plugin = mock(ClockPlugin.class);
    287         when(plugin.getBigClockView()).thenReturn(mBigClock);
    288         mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
    289         // WHEN transitioned to KEYGUARD state
    290         mStateListener.onStateChanged(StatusBarState.KEYGUARD);
    291         // THEN the container is visible.
    292         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);
    303         // AND in the keyguard state
    304         mStateListener.onStateChanged(StatusBarState.KEYGUARD);
    305         // 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
    312     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);
    319         // AND in the keyguard state
    320         mStateListener.onStateChanged(StatusBarState.KEYGUARD);
    321         // 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);
    325     }
    326 }
    327