[DO NOT MERGE] Initialize TimeZone during DefaultClockProvider init am: c6bfa32a24

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19732908

Change-Id: Ia6ffdd4ab7043b491e2312351e840f47be5a0d09
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Hawkwood Glazier
2022-09-01 20:06:44 +00:00
committed by Automerger Merge Worker
11 changed files with 244 additions and 177 deletions

View File

@@ -61,11 +61,7 @@ interface Clock {
/** Initializes various rendering parameters. If never called, provides reasonable defaults. */
fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) {
events.onColorPaletteChanged(
resources,
ClockDarkness.DEFAULT,
ClockDarkness.DEFAULT
)
events.onColorPaletteChanged(resources, true, true)
animations.doze(dozeFraction)
animations.fold(foldFraction)
events.onTimeTick()
@@ -95,8 +91,8 @@ interface ClockEvents {
/** Call whenever the color palette should update */
fun onColorPaletteChanged(
resources: Resources,
smallClockIsDark: ClockDarkness,
largeClockIsDark: ClockDarkness
smallClockIsDark: Boolean,
largeClockIsDark: Boolean
) { }
}
@@ -120,12 +116,3 @@ data class ClockMetadata(
val clockId: ClockId,
val name: String
)
/**
* Enum for whether clock region is dark or light.
*/
enum class ClockDarkness(val isDark: Boolean) {
DEFAULT(true),
DARK(true),
LIGHT(false)
}

View File

@@ -23,6 +23,7 @@
android:id="@+id/keyguard_clock_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:layout_gravity="center_horizontal|top">
<FrameLayout
android:id="@+id/lockscreen_clock_view"
@@ -30,16 +31,13 @@
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:paddingStart="@dimen/clock_padding_start">
</FrameLayout>
android:paddingStart="@dimen/clock_padding_start" />
<FrameLayout
android:id="@+id/lockscreen_clock_view_large"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/keyguard_slice_view"
android:paddingTop="@dimen/keyguard_large_clock_top_padding"
android:visibility="gone">
</FrameLayout>
android:layout_marginTop="@dimen/keyguard_large_clock_top_margin"
android:visibility="gone" />
<!-- Not quite optimal but needed to translate these items as a group. The
NotificationIconContainer has its own logic for translation. -->

View File

@@ -669,7 +669,7 @@
<!-- When large clock is showing, offset the smartspace by this amount -->
<dimen name="keyguard_smartspace_top_offset">12dp</dimen>
<!-- With the large clock, move up slightly from the center -->
<dimen name="keyguard_large_clock_top_padding">100dp</dimen>
<dimen name="keyguard_large_clock_top_margin">-60dp</dimen>
<dimen name="notification_scrim_corner_radius">32dp</dimen>

View File

@@ -18,7 +18,7 @@
-->
<com.android.systemui.shared.clocks.AnimatableClockView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:gravity="start"

View File

@@ -29,6 +29,7 @@ import android.util.AttributeSet
import android.widget.TextView
import com.android.internal.R.attr.contentDescription
import com.android.internal.R.attr.format
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.animation.GlyphCallback
import com.android.systemui.animation.Interpolators
import com.android.systemui.animation.TextAnimator
@@ -77,7 +78,8 @@ class AnimatableClockView @JvmOverloads constructor(
private var textAnimator: TextAnimator? = null
private var onTextAnimatorInitialized: Runnable? = null
var timeOverrideInMillis: Long? = null
@VisibleForTesting var isAnimationEnabled: Boolean = true
@VisibleForTesting var timeOverrideInMillis: Long? = null
val dozingWeight: Int
get() = if (useBoldedVersion()) dozingWeightInternal + 100 else dozingWeightInternal
@@ -218,7 +220,7 @@ class AnimatableClockView @JvmOverloads constructor(
}
fun animateAppearOnLockscreen() {
if (textAnimator == null) {
if (isAnimationEnabled && textAnimator == null) {
return
}
setTextStyle(
@@ -234,7 +236,7 @@ class AnimatableClockView @JvmOverloads constructor(
weight = lockScreenWeight,
textSize = -1f,
color = lockScreenColor,
animate = true,
animate = isAnimationEnabled,
duration = APPEAR_ANIM_DURATION,
delay = 0,
onAnimationEnd = null
@@ -242,7 +244,7 @@ class AnimatableClockView @JvmOverloads constructor(
}
fun animateFoldAppear(animate: Boolean = true) {
if (textAnimator == null) {
if (isAnimationEnabled && textAnimator == null) {
return
}
setTextStyle(
@@ -258,7 +260,7 @@ class AnimatableClockView @JvmOverloads constructor(
weight = dozingWeightInternal,
textSize = -1f,
color = dozingColor,
animate = animate,
animate = animate && isAnimationEnabled,
interpolator = Interpolators.EMPHASIZED_DECELERATE,
duration = ANIMATION_DURATION_FOLD_TO_AOD.toLong(),
delay = 0,
@@ -276,7 +278,7 @@ class AnimatableClockView @JvmOverloads constructor(
weight = if (isDozing()) dozingWeight else lockScreenWeight,
textSize = -1f,
color = null,
animate = true,
animate = isAnimationEnabled,
duration = CHARGE_ANIM_DURATION_PHASE_1,
delay = 0,
onAnimationEnd = null
@@ -286,7 +288,7 @@ class AnimatableClockView @JvmOverloads constructor(
weight = if (isDozing()) lockScreenWeight else dozingWeight,
textSize = -1f,
color = null,
animate = true,
animate = isAnimationEnabled,
duration = CHARGE_ANIM_DURATION_PHASE_0,
delay = chargeAnimationDelay.toLong(),
onAnimationEnd = startAnimPhase2
@@ -298,7 +300,7 @@ class AnimatableClockView @JvmOverloads constructor(
weight = if (isDozing) dozingWeight else lockScreenWeight,
textSize = -1f,
color = if (isDozing) dozingColor else lockScreenColor,
animate = animate,
animate = animate && isAnimationEnabled,
duration = DOZE_ANIM_DURATION,
delay = 0,
onAnimationEnd = null
@@ -332,7 +334,7 @@ class AnimatableClockView @JvmOverloads constructor(
weight = weight,
textSize = textSize,
color = color,
animate = animate,
animate = animate && isAnimationEnabled,
duration = duration,
interpolator = interpolator,
delay = delay,
@@ -370,7 +372,7 @@ class AnimatableClockView @JvmOverloads constructor(
weight = weight,
textSize = textSize,
color = color,
animate = animate,
animate = animate && isAnimationEnabled,
interpolator = null,
duration = duration,
delay = delay,

View File

@@ -13,16 +13,18 @@
*/
package com.android.systemui.shared.clocks
import android.content.Context
import android.content.res.Resources
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.icu.text.NumberFormat
import android.util.TypedValue
import android.view.LayoutInflater
import android.widget.FrameLayout
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.Clock
import com.android.systemui.plugins.ClockAnimations
import com.android.systemui.plugins.ClockDarkness
import com.android.systemui.plugins.ClockEvents
import com.android.systemui.plugins.ClockId
import com.android.systemui.plugins.ClockMetadata
@@ -39,6 +41,7 @@ const val DEFAULT_CLOCK_ID = "DEFAULT"
/** Provides the default system clock */
class DefaultClockProvider @Inject constructor(
val ctx: Context,
val layoutInflater: LayoutInflater,
@Main val resources: Resources
) : ClockProvider {
@@ -49,7 +52,7 @@ class DefaultClockProvider @Inject constructor(
if (id != DEFAULT_CLOCK_ID) {
throw IllegalArgumentException("$id is unsupported by $TAG")
}
return DefaultClock(layoutInflater, resources)
return DefaultClock(ctx, layoutInflater, resources)
}
override fun getClockThumbnail(id: ClockId): Drawable? {
@@ -69,14 +72,13 @@ class DefaultClockProvider @Inject constructor(
* AnimatableClockView used by the existing lockscreen clock.
*/
class DefaultClock(
ctx: Context,
private val layoutInflater: LayoutInflater,
private val resources: Resources
) : Clock {
override val smallClock =
layoutInflater.inflate(R.layout.clock_default_small, null) as AnimatableClockView
override val largeClock =
layoutInflater.inflate(R.layout.clock_default_large, null) as AnimatableClockView
private val clocks = listOf(smallClock, largeClock)
override val smallClock: AnimatableClockView
override val largeClock: AnimatableClockView
private val clocks get() = listOf(smallClock, largeClock)
private val burmeseNf = NumberFormat.getInstance(Locale.forLanguageTag("my"))
private val burmeseNumerals = burmeseNf.format(FORMAT_NUMBER.toLong())
@@ -84,17 +86,43 @@ class DefaultClock(
resources.getFloat(R.dimen.keyguard_clock_line_spacing_scale_burmese)
private val defaultLineSpacing = resources.getFloat(R.dimen.keyguard_clock_line_spacing_scale)
private fun updateClockColor(clock: AnimatableClockView, darkValue: ClockDarkness) {
val color = if (darkValue.isDark) {
resources.getColor(android.R.color.system_accent2_600)
} else {
resources.getColor(android.R.color.system_accent1_100)
}
clock.setColors(DOZE_COLOR, color)
clock.animateAppearOnLockscreen()
override val events: ClockEvents
override lateinit var animations: ClockAnimations
private set
init {
val parent = FrameLayout(ctx)
smallClock = layoutInflater.inflate(
R.layout.clock_default_small,
parent,
false
) as AnimatableClockView
largeClock = layoutInflater.inflate(
R.layout.clock_default_large,
parent,
false
) as AnimatableClockView
events = DefaultClockEvents()
animations = DefaultClockAnimations(0f, 0f)
events.onLocaleChanged(Locale.getDefault())
// DOZE_COLOR is a placeholder, and will be assigned correctly in initialize
clocks.forEach { it.setColors(DOZE_COLOR, DOZE_COLOR) }
}
override val events = object : ClockEvents {
override fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) {
recomputePadding()
animations = DefaultClockAnimations(dozeFraction, foldFraction)
events.onColorPaletteChanged(resources, true, true)
events.onTimeZoneChanged(TimeZone.getDefault())
events.onTimeTick()
}
inner class DefaultClockEvents() : ClockEvents {
override fun onTimeTick() = clocks.forEach { it.refreshTime() }
override fun onTimeFormatChanged(is24Hr: Boolean) =
@@ -117,8 +145,8 @@ class DefaultClock(
override fun onColorPaletteChanged(
resources: Resources,
smallClockIsDark: ClockDarkness,
largeClockIsDark: ClockDarkness
smallClockIsDark: Boolean,
largeClockIsDark: Boolean
) {
updateClockColor(smallClock, smallClockIsDark)
updateClockColor(largeClock, largeClockIsDark)
@@ -136,9 +164,6 @@ class DefaultClock(
}
}
override var animations = DefaultClockAnimations(0f, 0f)
private set
inner class DefaultClockAnimations(
dozeFraction: Float,
foldFraction: Float
@@ -194,31 +219,26 @@ class DefaultClock(
}
}
init {
events.onLocaleChanged(Locale.getDefault())
clocks.forEach { it.setColors(DOZE_COLOR, DOZE_COLOR) }
}
override fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) {
recomputePadding()
animations = DefaultClockAnimations(dozeFraction, foldFraction)
events.onColorPaletteChanged(
resources,
ClockDarkness.DEFAULT,
ClockDarkness.DEFAULT
)
events.onTimeTick()
private fun updateClockColor(clock: AnimatableClockView, isRegionDark: Boolean) {
val color = if (isRegionDark) {
resources.getColor(android.R.color.system_accent1_100)
} else {
resources.getColor(android.R.color.system_accent2_600)
}
clock.setColors(DOZE_COLOR, color)
clock.animateAppearOnLockscreen()
}
private fun recomputePadding() {
val topPadding = -1 * (largeClock.bottom.toInt() - 180)
largeClock.setPadding(0, topPadding, 0, 0)
val lp = largeClock.getLayoutParams() as FrameLayout.LayoutParams
lp.topMargin = (-0.5f * largeClock.bottom).toInt()
largeClock.setLayoutParams(lp)
}
override fun dump(pw: PrintWriter) = clocks.forEach { it.dump(pw) }
companion object {
private const val DOZE_COLOR = Color.WHITE
@VisibleForTesting const val DOZE_COLOR = Color.WHITE
private const val FORMAT_NUMBER = 1234567890
}
}

View File

@@ -20,17 +20,16 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.res.Resources
import android.graphics.Rect
import android.text.format.DateFormat
import android.util.TypedValue
import android.view.View
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.plugins.Clock
import com.android.systemui.plugins.ClockDarkness
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.shared.navigationbar.RegionSamplingHelper
import com.android.systemui.shared.regionsampling.RegionSamplingInstance
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback
import com.android.systemui.statusbar.policy.ConfigurationController
@@ -44,7 +43,7 @@ import javax.inject.Inject
* Controller for a Clock provided by the registry and used on the keyguard. Instantiated by
* [KeyguardClockSwitchController]. Functionality is forked from [AnimatableClockController].
*/
class ClockEventController @Inject constructor(
open class ClockEventController @Inject constructor(
private val statusBarStateController: StatusBarStateController,
private val broadcastDispatcher: BroadcastDispatcher,
private val batteryController: BatteryController,
@@ -61,6 +60,7 @@ class ClockEventController @Inject constructor(
field = value
if (value != null) {
value.initialize(resources, dozeAmount, 0f)
updateRegionSamplers(value)
}
}
@@ -71,94 +71,71 @@ class ClockEventController @Inject constructor(
private var dozeAmount = 0f
private var isKeyguardShowing = false
private var smallClockIsDark = ClockDarkness.DEFAULT
private var largeClockIsDark = ClockDarkness.DEFAULT
private var smallSamplingBounds = Rect()
private var largeSamplingBounds = Rect()
private val regionSamplingEnabled =
featureFlags.isEnabled(com.android.systemui.flags.Flags.REGION_SAMPLING)
private fun setClockDarkness(isRegionDark: Boolean): ClockDarkness {
return if (isRegionDark) {
ClockDarkness.DARK
} else {
ClockDarkness.LIGHT
private val updateFun = object : RegionSamplingInstance.UpdateColorCallback {
override fun updateColors() {
if (regionSamplingEnabled) {
smallClockIsDark = smallRegionSamplingInstance.currentRegionDarkness().isDark
largeClockIsDark = largeRegionSamplingInstance.currentRegionDarkness().isDark
} else {
val isLightTheme = TypedValue()
context.theme.resolveAttribute(android.R.attr.isLightTheme, isLightTheme, true)
smallClockIsDark = isLightTheme.data == 0
largeClockIsDark = isLightTheme.data == 0
}
clock?.events?.onColorPaletteChanged(resources, smallClockIsDark, largeClockIsDark)
}
}
// TODO: Abstract out the creation of RegionSampler and its fields
var smallRegionSampling: RegionSamplingHelper? =
if (!regionSamplingEnabled || clock == null) {
null
} else {
RegionSamplingHelper(clock?.smallClock,
object : RegionSamplingHelper.SamplingCallback {
override fun onRegionDarknessChanged(isRegionDark: Boolean) {
smallClockIsDark = setClockDarkness(isRegionDark)
clock?.events?.onColorPaletteChanged(
resources,
smallClockIsDark,
largeClockIsDark
)
}
fun updateRegionSamplers(currentClock: Clock?) {
smallRegionSamplingInstance = createRegionSampler(
currentClock?.smallClock,
mainExecutor,
bgExecutor,
regionSamplingEnabled,
updateFun
)
override fun getSampledRegion(sampledView: View): Rect {
smallSamplingBounds = Rect(
sampledView.left,
sampledView.top,
sampledView.right,
sampledView.bottom
)
return smallSamplingBounds
}
largeRegionSamplingInstance = createRegionSampler(
currentClock?.largeClock,
mainExecutor,
bgExecutor,
regionSamplingEnabled,
updateFun
)
override fun isSamplingEnabled(): Boolean {
return regionSamplingEnabled
}
},
mainExecutor, bgExecutor)
}
smallRegionSamplingInstance.startRegionSampler()
largeRegionSamplingInstance.startRegionSampler()
var largeRegionSampling: RegionSamplingHelper? =
if (!regionSamplingEnabled || clock == null) {
null
} else {
RegionSamplingHelper(clock?.largeClock,
object : RegionSamplingHelper.SamplingCallback {
override fun onRegionDarknessChanged(isRegionDark: Boolean) {
largeClockIsDark = setClockDarkness(isRegionDark)
clock?.events?.onColorPaletteChanged(
resources,
smallClockIsDark,
largeClockIsDark
)
}
updateFun.updateColors()
}
override fun getSampledRegion(sampledView: View): Rect {
largeSamplingBounds = Rect(
sampledView.left,
sampledView.top,
sampledView.right,
sampledView.bottom
)
return largeSamplingBounds
}
protected open fun createRegionSampler(
sampledView: View?,
mainExecutor: Executor?,
bgExecutor: Executor?,
regionSamplingEnabled: Boolean,
updateFun: RegionSamplingInstance.UpdateColorCallback
): RegionSamplingInstance {
return RegionSamplingInstance(
sampledView,
mainExecutor,
bgExecutor,
regionSamplingEnabled,
updateFun)
}
override fun isSamplingEnabled(): Boolean {
return regionSamplingEnabled
}
},
mainExecutor, bgExecutor)
}
lateinit var smallRegionSamplingInstance: RegionSamplingInstance
lateinit var largeRegionSamplingInstance: RegionSamplingInstance
private var smallClockIsDark = true
private var largeClockIsDark = true
private val configListener = object : ConfigurationController.ConfigurationListener {
override fun onThemeChanged() {
clock?.events?.onColorPaletteChanged(
resources,
smallClockIsDark,
largeClockIsDark
)
updateFun.updateColors()
}
}
@@ -209,9 +186,6 @@ class ClockEventController @Inject constructor(
init {
isDozing = statusBarStateController.isDozing
smallRegionSampling?.setWindowVisible(true)
largeRegionSampling?.setWindowVisible(true)
clock?.events?.onColorPaletteChanged(resources, smallClockIsDark, largeClockIsDark)
}
fun registerListeners() {
@@ -226,8 +200,8 @@ class ClockEventController @Inject constructor(
batteryController.addCallback(batteryCallback)
keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
statusBarStateController.addCallback(statusBarStateListener)
smallRegionSampling?.start(smallSamplingBounds)
largeRegionSampling?.start(largeSamplingBounds)
smallRegionSamplingInstance.startRegionSampler()
largeRegionSamplingInstance.startRegionSampler()
}
fun unregisterListeners() {
@@ -236,8 +210,8 @@ class ClockEventController @Inject constructor(
batteryController.removeCallback(batteryCallback)
keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
statusBarStateController.removeCallback(statusBarStateListener)
smallRegionSampling?.stop()
largeRegionSampling?.stop()
smallRegionSamplingInstance.stopRegionSampler()
largeRegionSamplingInstance.stopRegionSampler()
}
/**
@@ -246,8 +220,8 @@ class ClockEventController @Inject constructor(
fun dump(pw: PrintWriter) {
pw.println(this)
clock?.dump(pw)
smallRegionSampling?.dump(pw)
largeRegionSampling?.dump(pw)
smallRegionSamplingInstance.dump(pw)
largeRegionSamplingInstance.dump(pw)
}
companion object {

View File

@@ -8,7 +8,6 @@ import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
@@ -106,9 +105,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
}
// Attach small and big clock views to hierarchy.
mSmallClockFrame.addView(clock.getSmallClock(), -1,
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
mSmallClockFrame.addView(clock.getSmallClock());
mLargeClockFrame.addView(clock.getLargeClock());
}
@@ -223,7 +220,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
public void dump(PrintWriter pw, String[] args) {
pw.println("KeyguardClockSwitch:");
pw.println(" mClockFrame: " + mSmallClockFrame);
pw.println(" mSmallClockFrame: " + mSmallClockFrame);
pw.println(" mLargeClockFrame: " + mLargeClockFrame);
pw.println(" mStatusArea: " + mStatusArea);
pw.println(" mDisplayedClockSize: " + mDisplayedClockSize);

View File

@@ -72,7 +72,6 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
private final DumpManager mDumpManager;
private final ClockEventController mClockEventController;
/** Clock frames for both small and large sizes */
private FrameLayout mSmallClockFrame; // top aligned clock
private FrameLayout mLargeClockFrame; // centered clock
@@ -151,7 +150,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
* Attach the controller to the view it relates to.
*/
@Override
public void onInit() {
protected void onInit() {
mKeyguardSliceViewController.init();
mSmallClockFrame = mView.findViewById(R.id.lockscreen_clock_view);
@@ -390,8 +389,6 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
* bounds during the unlock transition.
*/
private void setClipChildrenForUnlock(boolean clip) {
mView.setClipChildren(clip);
if (mStatusArea != null) {
mStatusArea.setClipChildren(clip);
}

View File

@@ -107,13 +107,15 @@ class ClockEventControllerTest : SysuiTestCase() {
@Test
fun themeChanged_verifyClockPaletteUpdated() {
clockEventController.clock = clock
verify(events).onColorPaletteChanged(any(), any(), any())
clockEventController.registerListeners()
val captor = argumentCaptor<ConfigurationController.ConfigurationListener>()
verify(configurationController).addCallback(capture(captor))
captor.value.onThemeChanged()
verify(events).onColorPaletteChanged(any(), any(), any())
verify(events, times(2)).onColorPaletteChanged(any(), any(), any())
}
@Test
@@ -257,6 +259,7 @@ class ClockEventControllerTest : SysuiTestCase() {
@Test
fun unregisterListeners_validate() {
clockEventController.clock = clock
clockEventController.unregisterListeners()
verify(broadcastDispatcher).unregisterReceiver(any())
verify(configurationController).removeCallback(any())

View File

@@ -19,17 +19,31 @@ package com.android.systemui.shared.clocks
import android.content.res.Resources
import android.graphics.drawable.Drawable
import android.testing.AndroidTestingRunner
import android.util.TypedValue
import android.view.LayoutInflater
import android.widget.FrameLayout
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.shared.clocks.DefaultClock.Companion.DOZE_COLOR
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
import java.util.Locale
import java.util.TimeZone
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertNotNull
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyFloat
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.notNull
import org.mockito.Mock
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit
@@ -39,7 +53,8 @@ class DefaultClockProviderTest : SysuiTestCase() {
@JvmField @Rule val mockito = MockitoJUnit.rule()
@Mock private lateinit var mockClockView: AnimatableClockView
@Mock private lateinit var mockSmallClockView: AnimatableClockView
@Mock private lateinit var mockLargeClockView: AnimatableClockView
@Mock private lateinit var layoutInflater: LayoutInflater
@Mock private lateinit var mockClockThumbnail: Drawable
@Mock private lateinit var resources: Resources
@@ -47,14 +62,16 @@ class DefaultClockProviderTest : SysuiTestCase() {
@Before
fun setUp() {
whenever(layoutInflater.inflate(R.layout.clock_default_small, null))
.thenReturn(mockClockView)
whenever(layoutInflater.inflate(R.layout.clock_default_large, null))
.thenReturn(mockClockView)
whenever(layoutInflater.inflate(eq(R.layout.clock_default_small), any(), anyBoolean()))
.thenReturn(mockSmallClockView)
whenever(layoutInflater.inflate(eq(R.layout.clock_default_large), any(), anyBoolean()))
.thenReturn(mockLargeClockView)
whenever(resources.getDrawable(R.drawable.clock_default_thumbnail, null))
.thenReturn(mockClockThumbnail)
whenever(mockSmallClockView.getLayoutParams()).thenReturn(FrameLayout.LayoutParams(10, 10))
whenever(mockLargeClockView.getLayoutParams()).thenReturn(FrameLayout.LayoutParams(10, 10))
provider = DefaultClockProvider(layoutInflater, resources)
provider = DefaultClockProvider(context, layoutInflater, resources)
}
@Test
@@ -71,7 +88,79 @@ class DefaultClockProviderTest : SysuiTestCase() {
// Default clock provider must always provide the default clock
val clock = provider.createClock(DEFAULT_CLOCK_ID)
assertNotNull(clock)
assertEquals(clock.smallClock, mockClockView)
assertEquals(clock.largeClock, mockClockView)
assertEquals(clock.smallClock, mockSmallClockView)
assertEquals(clock.largeClock, mockLargeClockView)
}
@Test
fun defaultClock_initialize() {
val clock = provider.createClock(DEFAULT_CLOCK_ID)
clock.initialize(resources, 0f, 0f)
verify(mockSmallClockView, times(2)).setColors(eq(DOZE_COLOR), anyInt())
verify(mockLargeClockView, times(2)).setColors(eq(DOZE_COLOR), anyInt())
verify(mockSmallClockView).onTimeZoneChanged(notNull())
verify(mockLargeClockView).onTimeZoneChanged(notNull())
verify(mockSmallClockView).refreshTime()
verify(mockLargeClockView).refreshTime()
verify(mockLargeClockView).setLayoutParams(any())
}
@Test
fun defaultClock_events_onTimeTick() {
val clock = provider.createClock(DEFAULT_CLOCK_ID)
clock.events.onTimeTick()
verify(mockSmallClockView).refreshTime()
verify(mockLargeClockView).refreshTime()
}
@Test
fun defaultClock_events_onTimeFormatChanged() {
val clock = provider.createClock(DEFAULT_CLOCK_ID)
clock.events.onTimeFormatChanged(true)
verify(mockSmallClockView).refreshFormat(true)
verify(mockLargeClockView).refreshFormat(true)
}
@Test
fun defaultClock_events_onTimeZoneChanged() {
val timeZone = mock<TimeZone>()
val clock = provider.createClock(DEFAULT_CLOCK_ID)
clock.events.onTimeZoneChanged(timeZone)
verify(mockSmallClockView).onTimeZoneChanged(timeZone)
verify(mockLargeClockView).onTimeZoneChanged(timeZone)
}
@Test
fun defaultClock_events_onFontSettingChanged() {
val clock = provider.createClock(DEFAULT_CLOCK_ID)
clock.events.onFontSettingChanged()
verify(mockSmallClockView).setTextSize(eq(TypedValue.COMPLEX_UNIT_PX), anyFloat())
verify(mockLargeClockView).setTextSize(eq(TypedValue.COMPLEX_UNIT_PX), anyFloat())
verify(mockLargeClockView).setLayoutParams(any())
}
@Test
fun defaultClock_events_onColorPaletteChanged() {
val clock = provider.createClock(DEFAULT_CLOCK_ID)
clock.events.onColorPaletteChanged(resources, true, true)
verify(mockSmallClockView, times(2)).setColors(eq(DOZE_COLOR), anyInt())
verify(mockLargeClockView, times(2)).setColors(eq(DOZE_COLOR), anyInt())
}
@Test
fun defaultClock_events_onLocaleChanged() {
val clock = provider.createClock(DEFAULT_CLOCK_ID)
clock.events.onLocaleChanged(Locale.getDefault())
verify(mockSmallClockView, times(2)).setLineSpacingScale(anyFloat())
verify(mockLargeClockView, times(2)).setLineSpacingScale(anyFloat())
verify(mockSmallClockView, times(2)).refreshFormat()
verify(mockLargeClockView, times(2)).refreshFormat()
}
}