Remove View Injection from KeyguardClockSwitch.

Adds a controller for the KeyguardClockSwitch, and
moves some of its logic over.

Fixes: 162500959
Test: atest SystemUITests
Change-Id: Ib606ec727e5d005a0668a96dc823a7d1d1a53c79
This commit is contained in:
Dave Mankoff
2020-07-30 15:18:11 -04:00
parent b9045b33ba
commit 9705b01b4d
7 changed files with 350 additions and 165 deletions

View File

@@ -1,10 +1,7 @@
package com.android.keyguard;
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.Paint.Style;
@@ -24,16 +21,10 @@ import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.TextClock;
import androidx.annotation.VisibleForTesting;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.internal.colorextraction.ColorExtractor.OnColorsChangedListener;
import com.android.keyguard.clock.ClockManager;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.ClockPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.util.wakelock.KeepAwakeAnimationListener;
@@ -42,37 +33,18 @@ import java.io.PrintWriter;
import java.util.Arrays;
import java.util.TimeZone;
import javax.inject.Inject;
import javax.inject.Named;
/**
* Switch to show plugin clock when plugin is connected, otherwise it will show default clock.
*/
public class KeyguardClockSwitch extends RelativeLayout {
private static final String TAG = "KeyguardClockSwitch";
private static final boolean CUSTOM_CLOCKS_ENABLED = true;
/**
* Animation fraction when text is transitioned to/from bold.
*/
private static final float TO_BOLD_TRANSITION_FRACTION = 0.7f;
/**
* Controller used to track StatusBar state to know when to show the big_clock_container.
*/
private final StatusBarStateController mStatusBarStateController;
/**
* Color extractor used to apply colors from wallpaper to custom clock faces.
*/
private final SysuiColorExtractor mSysuiColorExtractor;
/**
* Manager used to know when to show a custom clock face.
*/
private final ClockManager mClockManager;
/**
* Layout transition that scales the default clock face.
*/
@@ -130,42 +102,8 @@ public class KeyguardClockSwitch extends RelativeLayout {
private boolean mSupportsDarkText;
private int[] mColorPalette;
/**
* Track the state of the status bar to know when to hide the big_clock_container.
*/
private int mStatusBarState;
private final StatusBarStateController.StateListener mStateListener =
new StatusBarStateController.StateListener() {
@Override
public void onStateChanged(int newState) {
mStatusBarState = newState;
updateBigClockVisibility();
}
};
private ClockManager.ClockChangedListener mClockChangedListener = this::setClockPlugin;
/**
* Listener for changes to the color palette.
*
* The color palette changes when the wallpaper is changed.
*/
private final OnColorsChangedListener mColorsListener = (extractor, which) -> {
if ((which & WallpaperManager.FLAG_LOCK) != 0) {
updateColors();
}
};
@Inject
public KeyguardClockSwitch(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
StatusBarStateController statusBarStateController, SysuiColorExtractor colorExtractor,
ClockManager clockManager) {
public KeyguardClockSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
mStatusBarStateController = statusBarStateController;
mStatusBarState = mStatusBarStateController.getState();
mSysuiColorExtractor = colorExtractor;
mClockManager = clockManager;
mClockTransition = new ClockVisibilityTransition().setCutoff(
1 - TO_BOLD_TRANSITION_FRACTION);
@@ -197,29 +135,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
mKeyguardStatusArea = findViewById(R.id.keyguard_status_area);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (CUSTOM_CLOCKS_ENABLED) {
mClockManager.addOnClockChangedListener(mClockChangedListener);
}
mStatusBarStateController.addCallback(mStateListener);
mSysuiColorExtractor.addOnColorsChangedListener(mColorsListener);
updateColors();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (CUSTOM_CLOCKS_ENABLED) {
mClockManager.removeOnClockChangedListener(mClockChangedListener);
}
mStatusBarStateController.removeCallback(mStateListener);
mSysuiColorExtractor.removeOnColorsChangedListener(mColorsListener);
setClockPlugin(null);
}
private void setClockPlugin(ClockPlugin plugin) {
void setClockPlugin(ClockPlugin plugin, int statusBarState) {
// Disconnect from existing plugin.
if (mClockPlugin != null) {
View smallClockView = mClockPlugin.getView();
@@ -228,7 +144,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
}
if (mBigClockContainer != null) {
mBigClockContainer.removeAllViews();
updateBigClockVisibility();
updateBigClockVisibility(statusBarState);
}
mClockPlugin.onDestroyView();
mClockPlugin = null;
@@ -256,7 +172,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
View bigClockView = plugin.getBigClockView();
if (bigClockView != null && mBigClockContainer != null) {
mBigClockContainer.addView(bigClockView);
updateBigClockVisibility();
updateBigClockVisibility(statusBarState);
}
// Hide default clock.
if (!plugin.shouldShowStatusArea()) {
@@ -275,7 +191,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
/**
* Set container for big clock face appearing behind NSSL and KeyguardStatusView.
*/
public void setBigClockContainer(ViewGroup container) {
public void setBigClockContainer(ViewGroup container, int statusBarState) {
if (mClockPlugin != null && container != null) {
View bigClockView = mClockPlugin.getBigClockView();
if (bigClockView != null) {
@@ -283,7 +199,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
}
}
mBigClockContainer = container;
updateBigClockVisibility();
updateBigClockVisibility(statusBarState);
}
/**
@@ -407,9 +323,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
}
}
private void updateColors() {
ColorExtractor.GradientColors colors = mSysuiColorExtractor.getColors(
WallpaperManager.FLAG_LOCK);
void updateColors(ColorExtractor.GradientColors colors) {
mSupportsDarkText = colors.supportsDarkText();
mColorPalette = colors.getColorPalette();
if (mClockPlugin != null) {
@@ -417,12 +331,12 @@ public class KeyguardClockSwitch extends RelativeLayout {
}
}
private void updateBigClockVisibility() {
void updateBigClockVisibility(int statusBarState) {
if (mBigClockContainer == null) {
return;
}
final boolean inDisplayState = mStatusBarState == StatusBarState.KEYGUARD
|| mStatusBarState == StatusBarState.SHADE_LOCKED;
final boolean inDisplayState = statusBarState == StatusBarState.KEYGUARD
|| statusBarState == StatusBarState.SHADE_LOCKED;
final int visibility = !mShowingHeader && inDisplayState
&& mBigClockContainer.getChildCount() != 0 ? View.VISIBLE : View.GONE;
if (mBigClockContainer.getVisibility() != visibility) {
@@ -506,16 +420,6 @@ public class KeyguardClockSwitch extends RelativeLayout {
}
}
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
ClockManager.ClockChangedListener getClockChangedListener() {
return mClockChangedListener;
}
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
StatusBarStateController.StateListener getStateListener() {
return mStateListener;
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("KeyguardClockSwitch:");
pw.println(" mClockPlugin: " + mClockPlugin);

View File

@@ -0,0 +1,119 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.keyguard;
import android.app.WallpaperManager;
import android.view.View;
import android.view.ViewGroup;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.keyguard.clock.ClockManager;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.ClockPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import javax.inject.Inject;
/**
* Injectable controller for {@link KeyguardClockSwitch}.
*/
public class KeyguardClockSwitchController {
private static final boolean CUSTOM_CLOCKS_ENABLED = true;
private final StatusBarStateController mStatusBarStateController;
private final SysuiColorExtractor mColorExtractor;
private final ClockManager mClockManager;
private KeyguardClockSwitch mView;
private final StatusBarStateController.StateListener mStateListener =
new StatusBarStateController.StateListener() {
@Override
public void onStateChanged(int newState) {
mView.updateBigClockVisibility(newState);
}
};
/**
* Listener for changes to the color palette.
*
* The color palette changes when the wallpaper is changed.
*/
private final ColorExtractor.OnColorsChangedListener mColorsListener = (extractor, which) -> {
if ((which & WallpaperManager.FLAG_LOCK) != 0) {
mView.updateColors(getGradientColors());
}
};
private ClockManager.ClockChangedListener mClockChangedListener = this::setClockPlugin;
private final View.OnAttachStateChangeListener mOnAttachStateChangeListener =
new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
if (CUSTOM_CLOCKS_ENABLED) {
mClockManager.addOnClockChangedListener(mClockChangedListener);
}
mStatusBarStateController.addCallback(mStateListener);
mColorExtractor.addOnColorsChangedListener(mColorsListener);
mView.updateColors(getGradientColors());
}
@Override
public void onViewDetachedFromWindow(View v) {
if (CUSTOM_CLOCKS_ENABLED) {
mClockManager.removeOnClockChangedListener(mClockChangedListener);
}
mStatusBarStateController.removeCallback(mStateListener);
mColorExtractor.removeOnColorsChangedListener(mColorsListener);
mView.setClockPlugin(null, mStatusBarStateController.getState());
}
};
@Inject
public KeyguardClockSwitchController(StatusBarStateController statusBarStateController,
SysuiColorExtractor colorExtractor, ClockManager clockManager) {
mStatusBarStateController = statusBarStateController;
mColorExtractor = colorExtractor;
mClockManager = clockManager;
}
/**
* Attach the controller to the view it relates to.
*/
public void attach(KeyguardClockSwitch view) {
mView = view;
if (mView.isAttachedToWindow()) {
mOnAttachStateChangeListener.onViewAttachedToWindow(mView);
}
mView.addOnAttachStateChangeListener(mOnAttachStateChangeListener);
}
/**
* Set container for big clock face appearing behind NSSL and KeyguardStatusView.
*/
public void setBigClockContainer(ViewGroup bigClockContainer) {
mView.setBigClockContainer(bigClockContainer, mStatusBarStateController.getState());
}
private void setClockPlugin(ClockPlugin plugin) {
mView.setClockPlugin(plugin, mStatusBarStateController.getState());
}
private ColorExtractor.GradientColors getGradientColors() {
return mColorExtractor.getColors(WallpaperManager.FLAG_LOCK);
}
}

View File

@@ -62,7 +62,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.LatencyTracker;
import com.android.keyguard.KeyguardClockSwitch;
import com.android.keyguard.KeyguardClockSwitchController;
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
@@ -124,6 +124,7 @@ import java.util.function.Consumer;
import java.util.function.Function;
import javax.inject.Inject;
import javax.inject.Provider;
@StatusBarComponent.StatusBarScope
public class NotificationPanelViewController extends PanelViewController {
@@ -252,6 +253,7 @@ public class NotificationPanelViewController extends PanelViewController {
private final ConversationNotificationManager mConversationNotificationManager;
private final MediaHierarchyManager mMediaHierarchyManager;
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private final Provider<KeyguardClockSwitchController> mKeyguardClockSwitchControllerProvider;
private KeyguardAffordanceHelper mAffordanceHelper;
private KeyguardUserSwitcher mKeyguardUserSwitcher;
@@ -495,7 +497,8 @@ public class NotificationPanelViewController extends PanelViewController {
ConversationNotificationManager conversationNotificationManager,
MediaHierarchyManager mediaHierarchyManager,
BiometricUnlockController biometricUnlockController,
StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
Provider<KeyguardClockSwitchController> keyguardClockSwitchControllerProvider) {
super(view, falsingManager, dozeLog, keyguardStateController,
(SysuiStatusBarStateController) statusBarStateController, vibratorHelper,
latencyTracker, flingAnimationUtilsBuilder, statusBarTouchableRegionManager);
@@ -507,6 +510,7 @@ public class NotificationPanelViewController extends PanelViewController {
mFlingAnimationUtilsBuilder = flingAnimationUtilsBuilder;
mMediaHierarchyManager = mediaHierarchyManager;
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mKeyguardClockSwitchControllerProvider = keyguardClockSwitchControllerProvider;
mView.setWillNotDraw(!DEBUG);
mInjectionInflationController = injectionInflationController;
mFalsingManager = falsingManager;
@@ -579,9 +583,11 @@ public class NotificationPanelViewController extends PanelViewController {
mKeyguardStatusBar = mView.findViewById(R.id.keyguard_header);
mKeyguardStatusView = mView.findViewById(R.id.keyguard_status_view);
KeyguardClockSwitch keyguardClockSwitch = mView.findViewById(R.id.keyguard_clock_container);
KeyguardClockSwitchController keyguardClockSwitchController =
mKeyguardClockSwitchControllerProvider.get();
keyguardClockSwitchController.attach(mView.findViewById(R.id.keyguard_clock_container));
mBigClockContainer = mView.findViewById(R.id.big_clock_container);
keyguardClockSwitch.setBigClockContainer(mBigClockContainer);
keyguardClockSwitchController.setBigClockContainer(mBigClockContainer);
mNotificationContainerParent = mView.findViewById(R.id.notification_container_parent);
mNotificationStackScroller = mView.findViewById(R.id.notification_stack_scroller);
@@ -703,8 +709,10 @@ public class NotificationPanelViewController extends PanelViewController {
// Re-associate the clock container with the keyguard clock switch.
mBigClockContainer.removeAllViews();
KeyguardClockSwitch keyguardClockSwitch = mView.findViewById(R.id.keyguard_clock_container);
keyguardClockSwitch.setBigClockContainer(mBigClockContainer);
KeyguardClockSwitchController keyguardClockSwitchController =
mKeyguardClockSwitchControllerProvider.get();
keyguardClockSwitchController.attach(mView.findViewById(R.id.keyguard_clock_container));
keyguardClockSwitchController.setBigClockContainer(mBigClockContainer);
// Update keyguard bottom area
index = mView.indexOfChild(mKeyguardBottomArea);

View File

@@ -23,7 +23,6 @@ import android.view.InflateException;
import android.view.LayoutInflater;
import android.view.View;
import com.android.keyguard.KeyguardClockSwitch;
import com.android.keyguard.KeyguardMessageArea;
import com.android.keyguard.KeyguardSliceView;
import com.android.systemui.dagger.SystemUIRootComponent;
@@ -131,11 +130,6 @@ public class InjectionInflationController {
*/
NotificationShelf creatNotificationShelf();
/**
* Creates the KeyguardClockSwitch.
*/
KeyguardClockSwitch createKeyguardClockSwitch();
/**
* Creates the KeyguardSliceView.
*/

View File

@@ -0,0 +1,162 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.keyguard;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.keyguard.clock.ClockManager;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.ClockPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.verification.VerificationMode;
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
@Mock
private StatusBarStateController mStatusBarStateController;
@Mock
private SysuiColorExtractor mColorExtractor;
@Mock
private ClockManager mClockManager;
@Mock
private KeyguardClockSwitch mView;
@Mock
private ClockPlugin mClockPlugin;
@Mock
ColorExtractor.GradientColors mGradientColors;
private KeyguardClockSwitchController mController;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mController = new KeyguardClockSwitchController(
mStatusBarStateController, mColorExtractor, mClockManager);
when(mView.isAttachedToWindow()).thenReturn(true);
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
when(mColorExtractor.getColors(anyInt())).thenReturn(mGradientColors);
}
@Test
public void testAttach_viewAlreadyAttached() {
mController.attach(mView);
verifyAttachment(times(1));
}
@Test
public void testAttach_viewNotYetAttached() {
ArgumentCaptor<View.OnAttachStateChangeListener> listenerArgumentCaptor =
ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
when(mView.isAttachedToWindow()).thenReturn(false);
mController.attach(mView);
verify(mView).addOnAttachStateChangeListener(listenerArgumentCaptor.capture());
verifyAttachment(never());
listenerArgumentCaptor.getValue().onViewAttachedToWindow(mView);
verifyAttachment(times(1));
}
@Test
public void testAttach_viewDetached() {
ArgumentCaptor<View.OnAttachStateChangeListener> listenerArgumentCaptor =
ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
mController.attach(mView);
verify(mView).addOnAttachStateChangeListener(listenerArgumentCaptor.capture());
verifyAttachment(times(1));
listenerArgumentCaptor.getValue().onViewDetachedFromWindow(mView);
verify(mStatusBarStateController).removeCallback(
any(StatusBarStateController.StateListener.class));
verify(mColorExtractor).removeOnColorsChangedListener(
any(ColorExtractor.OnColorsChangedListener.class));
}
@Test
public void testBigClockPassesStatusBarState() {
ViewGroup testView = new FrameLayout(mContext);
mController.attach(mView);
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
mController.setBigClockContainer(testView);
verify(mView).setBigClockContainer(testView, StatusBarState.SHADE);
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
mController.setBigClockContainer(testView);
verify(mView).setBigClockContainer(testView, StatusBarState.KEYGUARD);
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE_LOCKED);
mController.setBigClockContainer(testView);
verify(mView).setBigClockContainer(testView, StatusBarState.SHADE_LOCKED);
}
@Test
public void testPluginPassesStatusBarState() {
ArgumentCaptor<ClockManager.ClockChangedListener> listenerArgumentCaptor =
ArgumentCaptor.forClass(ClockManager.ClockChangedListener.class);
mController.attach(mView);
verify(mClockManager).addOnClockChangedListener(listenerArgumentCaptor.capture());
listenerArgumentCaptor.getValue().onClockChanged(mClockPlugin);
verify(mView).setClockPlugin(mClockPlugin, StatusBarState.SHADE);
}
private void verifyAttachment(VerificationMode times) {
verify(mClockManager, times).addOnClockChangedListener(
any(ClockManager.ClockChangedListener.class));
verify(mStatusBarStateController, times).addCallback(
any(StatusBarStateController.StateListener.class));
verify(mColorExtractor, times).addOnColorsChangedListener(
any(ColorExtractor.OnColorsChangedListener.class));
verify(mView, times).updateColors(mGradientColors);
}
}

View File

@@ -40,12 +40,10 @@ import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextClock;
import com.android.keyguard.clock.ClockManager;
import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.ClockPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.util.InjectionInflationController;
@@ -66,7 +64,6 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
private FrameLayout mClockContainer;
private FrameLayout mBigClockContainer;
private TextClock mBigClock;
private StatusBarStateController.StateListener mStateListener;
@Mock
TextClock mClockView;
@@ -108,7 +105,6 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
mBigClock = new TextClock(getContext());
MockitoAnnotations.initMocks(this);
when(mClockView.getPaint()).thenReturn(mock(TextPaint.class));
mStateListener = mKeyguardClockSwitch.getStateListener();
}
@Test
@@ -117,7 +113,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
TextClock pluginView = new TextClock(getContext());
when(plugin.getView()).thenReturn(pluginView);
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
verify(mClockView).setVisibility(GONE);
assertThat(plugin.getView().getParent()).isEqualTo(mClockContainer);
@@ -127,14 +123,14 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
public void onPluginConnected_showPluginBigClock() {
// GIVEN that the container for the big clock has visibility GONE
mBigClockContainer.setVisibility(GONE);
mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
// AND the plugin returns a view for the big clock
ClockPlugin plugin = mock(ClockPlugin.class);
when(plugin.getBigClockView()).thenReturn(mBigClock);
// AND in the keyguard state
mStateListener.onStateChanged(StatusBarState.KEYGUARD);
mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
// WHEN the plugin is connected
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
// THEN the big clock container is visible and it is the parent of the
// big clock view.
assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.VISIBLE);
@@ -144,7 +140,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
@Test
public void onPluginConnected_nullView() {
ClockPlugin plugin = mock(ClockPlugin.class);
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
verify(mClockView, never()).setVisibility(GONE);
}
@@ -153,11 +149,11 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
// GIVEN a plugin has already connected
ClockPlugin plugin1 = mock(ClockPlugin.class);
when(plugin1.getView()).thenReturn(new TextClock(getContext()));
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin1);
mKeyguardClockSwitch.setClockPlugin(plugin1, StatusBarState.KEYGUARD);
// WHEN a second plugin is connected
ClockPlugin plugin2 = mock(ClockPlugin.class);
when(plugin2.getView()).thenReturn(new TextClock(getContext()));
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin2);
mKeyguardClockSwitch.setClockPlugin(plugin2, StatusBarState.KEYGUARD);
// THEN only the view from the second plugin should be a child of KeyguardClockSwitch.
assertThat(plugin2.getView().getParent()).isEqualTo(mClockContainer);
assertThat(plugin1.getView().getParent()).isNull();
@@ -169,7 +165,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
mKeyguardClockSwitch.setDarkAmount(0.5f);
// WHEN a plugin is connected
ClockPlugin plugin = mock(ClockPlugin.class);
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
// THEN dark amount should be initalized on the plugin.
verify(plugin).setDarkAmount(0.5f);
}
@@ -181,8 +177,8 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
when(plugin.getView()).thenReturn(pluginView);
mClockView.setVisibility(GONE);
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(null);
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
verify(mClockView).setVisibility(VISIBLE);
assertThat(plugin.getView().getParent()).isNull();
@@ -193,16 +189,16 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
// GIVEN that the big clock container is visible
FrameLayout bigClockContainer = new FrameLayout(getContext());
bigClockContainer.setVisibility(VISIBLE);
mKeyguardClockSwitch.setBigClockContainer(bigClockContainer);
mKeyguardClockSwitch.setBigClockContainer(bigClockContainer, StatusBarState.KEYGUARD);
// AND the plugin returns a view for the big clock
ClockPlugin plugin = mock(ClockPlugin.class);
TextClock pluginView = new TextClock(getContext());
when(plugin.getBigClockView()).thenReturn(pluginView);
// AND in the keyguard state
mStateListener.onStateChanged(StatusBarState.KEYGUARD);
mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
// WHEN the plugin is connected and then disconnected
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(null);
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
// THEN the big lock container is GONE and the big clock view doesn't have
// a parent.
assertThat(bigClockContainer.getVisibility()).isEqualTo(GONE);
@@ -212,8 +208,8 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
@Test
public void onPluginDisconnected_nullView() {
ClockPlugin plugin = mock(ClockPlugin.class);
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(null);
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
verify(mClockView, never()).setVisibility(GONE);
}
@@ -222,13 +218,12 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
// GIVEN two plugins are connected
ClockPlugin plugin1 = mock(ClockPlugin.class);
when(plugin1.getView()).thenReturn(new TextClock(getContext()));
ClockManager.ClockChangedListener listener = mKeyguardClockSwitch.getClockChangedListener();
listener.onClockChanged(plugin1);
mKeyguardClockSwitch.setClockPlugin(plugin1, StatusBarState.KEYGUARD);
ClockPlugin plugin2 = mock(ClockPlugin.class);
when(plugin2.getView()).thenReturn(new TextClock(getContext()));
listener.onClockChanged(plugin2);
mKeyguardClockSwitch.setClockPlugin(plugin2, StatusBarState.KEYGUARD);
// WHEN the second plugin is disconnected
listener.onClockChanged(null);
mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
// THEN the default clock should be shown.
verify(mClockView).setVisibility(VISIBLE);
assertThat(plugin1.getView().getParent()).isNull();
@@ -240,10 +235,9 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
// GIVEN a plugin is connected
ClockPlugin clockPlugin = mock(ClockPlugin.class);
when(clockPlugin.getView()).thenReturn(new TextClock(getContext()));
ClockManager.ClockChangedListener listener = mKeyguardClockSwitch.getClockChangedListener();
listener.onClockChanged(clockPlugin);
mKeyguardClockSwitch.setClockPlugin(clockPlugin, StatusBarState.KEYGUARD);
// WHEN the plugin is disconnected
listener.onClockChanged(null);
mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
// THEN onDestroyView is called on the plugin
verify(clockPlugin).onDestroyView();
}
@@ -260,7 +254,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
ClockPlugin plugin = mock(ClockPlugin.class);
TextClock pluginView = new TextClock(getContext());
when(plugin.getView()).thenReturn(pluginView);
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
mKeyguardClockSwitch.setTextColor(Color.WHITE);
@@ -284,7 +278,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
TextClock pluginView = new TextClock(getContext());
when(plugin.getView()).thenReturn(pluginView);
Style style = mock(Style.class);
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
mKeyguardClockSwitch.setStyle(style);
@@ -295,9 +289,9 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
public void onStateChanged_GoneInShade() {
// GIVEN that the big clock container is visible
mBigClockContainer.setVisibility(View.VISIBLE);
mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
// WHEN transitioned to SHADE state
mStateListener.onStateChanged(StatusBarState.SHADE);
mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.SHADE);
// THEN the container is gone.
assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.GONE);
}
@@ -306,13 +300,13 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
public void onStateChanged_VisibleInKeyguard() {
// GIVEN that the big clock container is gone
mBigClockContainer.setVisibility(View.GONE);
mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
// AND GIVEN that a plugin is active.
ClockPlugin plugin = mock(ClockPlugin.class);
when(plugin.getBigClockView()).thenReturn(mBigClock);
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
// WHEN transitioned to KEYGUARD state
mStateListener.onStateChanged(StatusBarState.KEYGUARD);
mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
// THEN the container is visible.
assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.VISIBLE);
}
@@ -324,11 +318,11 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
// AND GIVEN that a plugin is active.
ClockPlugin plugin = mock(ClockPlugin.class);
when(plugin.getBigClockView()).thenReturn(mBigClock);
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
// AND in the keyguard state
mStateListener.onStateChanged(StatusBarState.KEYGUARD);
mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
// WHEN the container is associated with the clock switch
mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
// THEN the container remains visible.
assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.VISIBLE);
}
@@ -340,11 +334,11 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
// AND GIVEN that a plugin is active.
ClockPlugin plugin = mock(ClockPlugin.class);
when(plugin.getBigClockView()).thenReturn(mBigClock);
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
// AND in the keyguard state
mStateListener.onStateChanged(StatusBarState.KEYGUARD);
mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
// WHEN the container is associated with the clock switch
mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
// THEN the container is made visible.
assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.VISIBLE);
}
@@ -353,14 +347,14 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
public void setKeyguardHidingBigClock_gone() {
// GIVEN that the container for the big clock has visibility GONE
mBigClockContainer.setVisibility(GONE);
mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
// AND the plugin returns a view for the big clock
ClockPlugin plugin = mock(ClockPlugin.class);
when(plugin.getBigClockView()).thenReturn(mBigClock);
// AND in the keyguard state
mStateListener.onStateChanged(StatusBarState.KEYGUARD);
mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
// WHEN the plugin is connected
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
// WHEN the container set hiding clock as true
mKeyguardClockSwitch.setKeyguardHidingBigClock(true);
// THEN the container is gone.
@@ -371,14 +365,14 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
public void setKeyguardHidingBigClock_visible() {
// GIVEN that the container for the big clock has visibility GONE
mBigClockContainer.setVisibility(GONE);
mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
// AND the plugin returns a view for the big clock
ClockPlugin plugin = mock(ClockPlugin.class);
when(plugin.getBigClockView()).thenReturn(mBigClock);
// AND in the keyguard state
mStateListener.onStateChanged(StatusBarState.KEYGUARD);
mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
// WHEN the plugin is connected
mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
// WHEN the container set hiding clock as false
mKeyguardClockSwitch.setKeyguardHidingBigClock(false);
// THEN the container is made visible.

View File

@@ -51,6 +51,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.internal.util.LatencyTracker;
import com.android.keyguard.KeyguardClockSwitch;
import com.android.keyguard.KeyguardClockSwitchController;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
@@ -183,6 +184,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
private BiometricUnlockController mBiometricUnlockController;
@Mock
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Mock
private KeyguardClockSwitchController mKeyguardClockSwitchController;
private FlingAnimationUtils.Builder mFlingAnimationUtilsBuilder;
private NotificationPanelViewController mNotificationPanelViewController;
@@ -240,7 +243,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mMetricsLogger, mActivityManager, mZenModeController, mConfigurationController,
mFlingAnimationUtilsBuilder, mStatusBarTouchableRegionManager,
mConversationNotificationManager, mMediaHiearchyManager,
mBiometricUnlockController, mStatusBarKeyguardViewManager);
mBiometricUnlockController, mStatusBarKeyguardViewManager,
() -> mKeyguardClockSwitchController);
mNotificationPanelViewController.initDependencies(mStatusBar, mGroupManager,
mNotificationShelf, mNotificationAreaController, mScrimController);
mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);