From e5383425e16718bf7fa6c31206f515e6d32f6d7f Mon Sep 17 00:00:00 2001 From: Hawkwood Glazier Date: Fri, 16 Sep 2022 18:26:40 +0000 Subject: [PATCH] Ensure state is set correctly after animateAppearOnLockscreen is called Before the textAnimator is initialized, animateAppearOnLockscreen can be called to set the color to be correctly set on the AnimatableClockView. As a result, we should not suppress the calls to setTextStyle so that the correct setTextStyle call is cached in onTextAnimatorInitialized. Fixes: 246831875 Test: Manually checked broken usecase and several working usecases Change-Id: I9ffbb34bc314affe64180ab1bbea411bebe37d2d --- .../shared/clocks/AnimatableClockView.kt | 8 +- .../shared/clocks/AnimatableClockViewTest.kt | 74 +++++++++++++++++++ 2 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt index 34e2e83d76439..c2e74456c032f 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt @@ -23,6 +23,7 @@ import android.annotation.SuppressLint import android.app.compat.ChangeIdStateCache.invalidate import android.content.Context import android.graphics.Canvas +import android.text.Layout import android.text.TextUtils import android.text.format.DateFormat import android.util.AttributeSet @@ -78,6 +79,8 @@ class AnimatableClockView @JvmOverloads constructor( private var textAnimator: TextAnimator? = null private var onTextAnimatorInitialized: Runnable? = null + @VisibleForTesting var textAnimatorFactory: (Layout, () -> Unit) -> TextAnimator = + { layout, invalidateCb -> TextAnimator(layout, invalidateCb) } @VisibleForTesting var isAnimationEnabled: Boolean = true @VisibleForTesting var timeOverrideInMillis: Long? = null @@ -174,7 +177,7 @@ class AnimatableClockView @JvmOverloads constructor( super.onMeasure(widthMeasureSpec, heightMeasureSpec) val animator = textAnimator if (animator == null) { - textAnimator = TextAnimator(layout) { invalidate() } + textAnimator = textAnimatorFactory(layout, ::invalidate) onTextAnimatorInitialized?.run() onTextAnimatorInitialized = null } else { @@ -219,9 +222,6 @@ class AnimatableClockView @JvmOverloads constructor( } fun animateAppearOnLockscreen() { - if (isAnimationEnabled && textAnimator == null) { - return - } setTextStyle( weight = dozingWeight, textSize = -1f, diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt new file mode 100644 index 0000000000000..eb34561d15a0f --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2022 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.systemui.shared.clocks + +import android.testing.AndroidTestingRunner +import android.view.LayoutInflater +import androidx.test.filters.SmallTest +import com.android.systemui.R +import com.android.systemui.SysuiTestCase +import com.android.systemui.animation.TextAnimator +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.times +import org.mockito.Mockito.verify +import org.mockito.Mockito.verifyNoMoreInteractions +import org.mockito.junit.MockitoJUnit + +@RunWith(AndroidTestingRunner::class) +@SmallTest +class AnimatableClockViewTest : SysuiTestCase() { + + @JvmField @Rule val mockito = MockitoJUnit.rule() + + @Mock private lateinit var mockTextAnimator: TextAnimator + private lateinit var clockView: AnimatableClockView + + @Before + fun setUp() { + val layoutInflater = LayoutInflater.from(context) + clockView = + layoutInflater.inflate(R.layout.clock_default_small, null) as AnimatableClockView + clockView.textAnimatorFactory = { _, _ -> mockTextAnimator } + } + + @Test + fun validateColorAnimationRunsBeforeMeasure() { + clockView.setColors(100, 200) + clockView.animateAppearOnLockscreen() + clockView.measure(50, 50) + + verify(mockTextAnimator).glyphFilter = null + verify(mockTextAnimator).setTextStyle(300, -1.0f, 200, false, 350L, null, 0L, null) + verifyNoMoreInteractions(mockTextAnimator) + } + + @Test + fun validateColorAnimationRunsAfterMeasure() { + clockView.setColors(100, 200) + clockView.measure(50, 50) + clockView.animateAppearOnLockscreen() + + verify(mockTextAnimator, times(2)).glyphFilter = null + verify(mockTextAnimator).setTextStyle(100, -1.0f, 200, false, 0L, null, 0L, null) + verify(mockTextAnimator).setTextStyle(300, -1.0f, 200, true, 350L, null, 0L, null) + verifyNoMoreInteractions(mockTextAnimator) + } +}