Add clock plugin function
Use clock plugin interface to replace current TextClock in keyguard Bug: 111971817 Test: atest SystemUITests Change-Id: Ib6920844700445d9cd3ffa4159cd7f630eaa853b
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
**
|
||||
** Copyright 2018, 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<!-- This is a view that shows clock information in Keyguard. -->
|
||||
<com.android.keyguard.KeyguardClockSwitch
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_alignParentTop="true">
|
||||
<TextClock
|
||||
android:id="@+id/default_clock_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:letterSpacing="0.03"
|
||||
android:textColor="?attr/wallpaperTextColor"
|
||||
android:singleLine="true"
|
||||
style="@style/widget_big_thin"
|
||||
android:format12Hour="@string/keyguard_widget_12_hours_format"
|
||||
android:format24Hour="@string/keyguard_widget_24_hours_format" />
|
||||
</com.android.keyguard.KeyguardClockSwitch>
|
||||
@@ -38,19 +38,10 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal|top">
|
||||
<TextClock
|
||||
android:id="@+id/clock_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:letterSpacing="0.03"
|
||||
android:textColor="?attr/wallpaperTextColor"
|
||||
android:singleLine="true"
|
||||
style="@style/widget_big_thin"
|
||||
android:format12Hour="@string/keyguard_widget_12_hours_format"
|
||||
android:format24Hour="@string/keyguard_widget_24_hours_format" />
|
||||
<include layout="@layout/keyguard_clock_switch"
|
||||
android:id="@+id/clock_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
<View
|
||||
android:id="@+id/clock_separator"
|
||||
android:layout_width="@dimen/widget_separator_width"
|
||||
|
||||
@@ -55,19 +55,10 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal|top">
|
||||
<TextClock
|
||||
android:id="@+id/clock_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:letterSpacing="0.03"
|
||||
android:textColor="?attr/wallpaperTextColor"
|
||||
android:singleLine="true"
|
||||
style="@style/widget_big_thin"
|
||||
android:format12Hour="@string/keyguard_widget_12_hours_format"
|
||||
android:format24Hour="@string/keyguard_widget_24_hours_format" />
|
||||
<include layout="@layout/keyguard_clock_switch"
|
||||
android:id="@+id/clock_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
<View
|
||||
android:id="@+id/clock_separator"
|
||||
android:layout_width="@dimen/widget_separator_width"
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
package com.android.keyguard;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextClock;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.plugins.ClockPlugin;
|
||||
import com.android.systemui.plugins.PluginListener;
|
||||
import com.android.systemui.plugins.PluginManager;
|
||||
|
||||
/**
|
||||
* Switch to show plugin clock when plugin is connected, otherwise it will show default clock.
|
||||
*/
|
||||
public class KeyguardClockSwitch extends FrameLayout {
|
||||
/**
|
||||
* Optional/alternative clock injected via plugin.
|
||||
*/
|
||||
private ClockPlugin mClockPlugin;
|
||||
/**
|
||||
* Default clock.
|
||||
*/
|
||||
private TextClock mClockView;
|
||||
|
||||
private final PluginListener<ClockPlugin> mClockPluginListener =
|
||||
new PluginListener<ClockPlugin>() {
|
||||
@Override
|
||||
public void onPluginConnected(ClockPlugin plugin, Context pluginContext) {
|
||||
View view = plugin.getView();
|
||||
if (view != null) {
|
||||
mClockPlugin = plugin;
|
||||
addView(view, -1,
|
||||
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
initPluginParams();
|
||||
mClockView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPluginDisconnected(ClockPlugin plugin) {
|
||||
View view = plugin.getView();
|
||||
if (view != null) {
|
||||
mClockPlugin = null;
|
||||
removeView(view);
|
||||
mClockView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public KeyguardClockSwitch(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public KeyguardClockSwitch(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mClockView = findViewById(R.id.default_clock_view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
Dependency.get(PluginManager.class).addPluginListener(mClockPluginListener,
|
||||
ClockPlugin.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
Dependency.get(PluginManager.class).removePluginListener(mClockPluginListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* It will also update plugin setStyle if plugin is connected.
|
||||
*/
|
||||
public void setStyle(Style style) {
|
||||
mClockView.getPaint().setStyle(style);
|
||||
if (mClockPlugin != null) {
|
||||
mClockPlugin.setStyle(style);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It will also update plugin setTextColor if plugin is connected.
|
||||
*/
|
||||
public void setTextColor(int color) {
|
||||
mClockView.setTextColor(color);
|
||||
if (mClockPlugin != null) {
|
||||
mClockPlugin.setTextColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
public void setShowCurrentUserTime(boolean showCurrentUserTime) {
|
||||
mClockView.setShowCurrentUserTime(showCurrentUserTime);
|
||||
}
|
||||
|
||||
public void setElegantTextHeight(boolean elegant) {
|
||||
mClockView.setElegantTextHeight(elegant);
|
||||
}
|
||||
|
||||
public void setTextSize(int unit, float size) {
|
||||
mClockView.setTextSize(unit, size);
|
||||
}
|
||||
|
||||
public void setFormat12Hour(CharSequence format) {
|
||||
mClockView.setFormat12Hour(format);
|
||||
}
|
||||
|
||||
public void setFormat24Hour(CharSequence format) {
|
||||
mClockView.setFormat24Hour(format);
|
||||
}
|
||||
|
||||
public Paint getPaint() {
|
||||
return mClockView.getPaint();
|
||||
}
|
||||
|
||||
public int getCurrentTextColor() {
|
||||
return mClockView.getCurrentTextColor();
|
||||
}
|
||||
|
||||
public float getTextSize() {
|
||||
return mClockView.getTextSize();
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
mClockView.refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* When plugin changes, set all kept parameters into newer plugin.
|
||||
*/
|
||||
private void initPluginParams() {
|
||||
if (mClockPlugin != null) {
|
||||
mClockPlugin.setStyle(getPaint().getStyle());
|
||||
mClockPlugin.setTextColor(getCurrentTextColor());
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting (otherwise = VisibleForTesting.NONE)
|
||||
PluginListener getClockPluginListener() {
|
||||
return mClockPluginListener;
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,6 @@ import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.widget.GridLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextClock;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
@@ -64,7 +63,7 @@ public class KeyguardStatusView extends GridLayout implements
|
||||
private final float mSmallClockScale;
|
||||
|
||||
private TextView mLogoutView;
|
||||
private TextClock mClockView;
|
||||
private KeyguardClockSwitch mClockView;
|
||||
private View mClockSeparator;
|
||||
private TextView mOwnerInfo;
|
||||
private KeyguardSliceView mKeyguardSlice;
|
||||
@@ -248,7 +247,7 @@ public class KeyguardStatusView extends GridLayout implements
|
||||
.scaleX(clockScale)
|
||||
.scaleY(clockScale)
|
||||
.withEndAction(() -> {
|
||||
mClockView.getPaint().setStyle(style);
|
||||
mClockView.setStyle(style);
|
||||
mClockView.invalidate();
|
||||
})
|
||||
.start();
|
||||
@@ -256,7 +255,7 @@ public class KeyguardStatusView extends GridLayout implements
|
||||
mClockView.setY(top);
|
||||
mClockView.setScaleX(clockScale);
|
||||
mClockView.setScaleY(clockScale);
|
||||
mClockView.getPaint().setStyle(style);
|
||||
mClockView.setStyle(style);
|
||||
mClockView.invalidate();
|
||||
}
|
||||
} else if (view == mClockSeparator) {
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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 android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper.RunWithLooper;
|
||||
import android.text.TextPaint;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextClock;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.plugins.ClockPlugin;
|
||||
import com.android.systemui.plugins.PluginListener;
|
||||
import com.android.systemui.plugins.PluginManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@SmallTest
|
||||
@RunWithLooper(setAsMainLooper = true)
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class KeyguardClockSwitchTest extends SysuiTestCase {
|
||||
private PluginManager mPluginManager;
|
||||
|
||||
@Mock
|
||||
TextClock mClockView;
|
||||
@InjectMocks
|
||||
KeyguardClockSwitch mKeyguardClockSwitch;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mPluginManager = mDependency.injectMockDependency(PluginManager.class);
|
||||
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
|
||||
mKeyguardClockSwitch =
|
||||
(KeyguardClockSwitch) layoutInflater.inflate(R.layout.keyguard_clock_switch, null);
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onAttachToWindow_addPluginListener() {
|
||||
mKeyguardClockSwitch.onAttachedToWindow();
|
||||
|
||||
ArgumentCaptor<PluginListener> listener = ArgumentCaptor.forClass(PluginListener.class);
|
||||
verify(mPluginManager).addPluginListener(listener.capture(), eq(ClockPlugin.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDetachToWindow_removePluginListener() {
|
||||
mKeyguardClockSwitch.onDetachedFromWindow();
|
||||
|
||||
ArgumentCaptor<PluginListener> listener = ArgumentCaptor.forClass(PluginListener.class);
|
||||
verify(mPluginManager).removePluginListener(listener.capture());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPluginConnected_showPluginClock() {
|
||||
ClockPlugin plugin = mock(ClockPlugin.class);
|
||||
TextClock pluginView = new TextClock(getContext());
|
||||
when(plugin.getView()).thenReturn(pluginView);
|
||||
TextPaint paint = mock(TextPaint.class);
|
||||
doReturn(paint).when(mClockView).getPaint();
|
||||
PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
|
||||
|
||||
listener.onPluginConnected(plugin, null);
|
||||
|
||||
verify(mClockView).setVisibility(GONE);
|
||||
assertThat(plugin.getView().getParent()).isEqualTo(mKeyguardClockSwitch);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPluginDisconnected_showDefaultClock() {
|
||||
ClockPlugin plugin = mock(ClockPlugin.class);
|
||||
TextClock pluginView = new TextClock(getContext());
|
||||
when(plugin.getView()).thenReturn(pluginView);
|
||||
mClockView.setVisibility(GONE);
|
||||
mKeyguardClockSwitch.addView(plugin.getView(), -1,
|
||||
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
|
||||
|
||||
listener.onPluginDisconnected(plugin);
|
||||
|
||||
verify(mClockView).setVisibility(VISIBLE);
|
||||
assertThat(plugin.getView().getParent()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setTextColor_defaultClockSetTextColor() {
|
||||
mKeyguardClockSwitch.setTextColor(Color.YELLOW);
|
||||
|
||||
verify(mClockView).setTextColor(Color.YELLOW);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setTextColor_pluginClockSetTextColor() {
|
||||
ClockPlugin plugin = mock(ClockPlugin.class);
|
||||
TextClock pluginView = new TextClock(getContext());
|
||||
when(plugin.getView()).thenReturn(pluginView);
|
||||
TextPaint paint = mock(TextPaint.class);
|
||||
doReturn(paint).when(mClockView).getPaint();
|
||||
PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
|
||||
listener.onPluginConnected(plugin, null);
|
||||
|
||||
mKeyguardClockSwitch.setTextColor(Color.WHITE);
|
||||
|
||||
verify(plugin).setTextColor(Color.WHITE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setStyle_defaultClockSetStyle() {
|
||||
TextPaint paint = mock(TextPaint.class);
|
||||
Style style = mock(Style.class);
|
||||
doReturn(paint).when(mClockView).getPaint();
|
||||
|
||||
mKeyguardClockSwitch.setStyle(style);
|
||||
|
||||
verify(paint).setStyle(style);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setStyle_pluginClockSetStyle() {
|
||||
ClockPlugin plugin = mock(ClockPlugin.class);
|
||||
TextClock pluginView = new TextClock(getContext());
|
||||
when(plugin.getView()).thenReturn(pluginView);
|
||||
TextPaint paint = mock(TextPaint.class);
|
||||
doReturn(paint).when(mClockView).getPaint();
|
||||
Style style = mock(Style.class);
|
||||
PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
|
||||
listener.onPluginConnected(plugin, null);
|
||||
|
||||
mKeyguardClockSwitch.setStyle(style);
|
||||
|
||||
verify(plugin).setStyle(style);
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper.RunWithLooper;
|
||||
import android.view.LayoutInflater;
|
||||
import android.widget.TextClock;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
|
||||
@@ -40,7 +39,7 @@ public class KeyguardStatusViewTest extends SysuiTestCase {
|
||||
@Mock
|
||||
KeyguardSliceView mKeyguardSlice;
|
||||
@Mock
|
||||
TextClock mClockView;
|
||||
KeyguardClockSwitch mClockView;
|
||||
@InjectMocks
|
||||
KeyguardStatusView mKeyguardStatusView;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user