Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6f3eb327 authored by Hawkwood Glazier's avatar Hawkwood Glazier
Browse files

Change clock animations to be per-clock face

Also add a small Start Delay to StatusArea translation

Bug: 276733633
Bug: 276236565
Test: Manually looked at timing of animation
Change-Id: I6d77e53a4f80c8b860596797b3f982e116601167
parent 53c8ac6f
Loading
Loading
Loading
Loading
+26 −13
Original line number Diff line number Diff line
@@ -62,10 +62,7 @@ class DefaultClockController(
    private val defaultLineSpacing = resources.getFloat(R.dimen.keyguard_clock_line_spacing_scale)

    override val events: DefaultClockEvents
    override lateinit var animations: DefaultClockAnimations
        private set

    override val config = ClockConfig(hasCustomPositionUpdatedAnimation = true)
    override val config = ClockConfig()

    init {
        val parent = FrameLayout(ctx)
@@ -84,13 +81,13 @@ class DefaultClockController(
        clocks = listOf(smallClock.view, largeClock.view)

        events = DefaultClockEvents()
        animations = DefaultClockAnimations(0f, 0f)
        events.onLocaleChanged(Locale.getDefault())
    }

    override fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) {
        largeClock.recomputePadding(null)
        animations = DefaultClockAnimations(dozeFraction, foldFraction)
        largeClock.animations = LargeClockAnimations(largeClock.view, dozeFraction, foldFraction)
        smallClock.animations = DefaultClockAnimations(smallClock.view, dozeFraction, foldFraction)
        events.onColorPaletteChanged(resources)
        events.onTimeZoneChanged(TimeZone.getDefault())
        smallClock.events.onTimeTick()
@@ -115,6 +112,9 @@ class DefaultClockController(
                view.logBuffer = value
            }

        override var animations: DefaultClockAnimations = DefaultClockAnimations(view, 0f, 0f)
            internal set

        init {
            if (seedColor != null) {
                currentColor = seedColor!!
@@ -170,6 +170,12 @@ class DefaultClockController(
        view: AnimatableClockView,
        seedColor: Int?,
    ) : DefaultClockFaceController(view, seedColor) {
        override val config = ClockFaceConfig(hasCustomPositionUpdatedAnimation = true)

        init {
            animations = LargeClockAnimations(view, 0f, 0f)
        }

        override fun recomputePadding(targetRegion: Rect?) {
            // We center the view within the targetRegion instead of within the parent
            // view by computing the difference and adding that to the padding.
@@ -220,7 +226,8 @@ class DefaultClockController(
        }
    }

    inner class DefaultClockAnimations(
    open inner class DefaultClockAnimations(
        val view: AnimatableClockView,
        dozeFraction: Float,
        foldFraction: Float,
    ) : ClockAnimations {
@@ -229,34 +236,40 @@ class DefaultClockController(

        init {
            if (foldState.isActive) {
                clocks.forEach { it.animateFoldAppear(false) }
                view.animateFoldAppear(false)
            } else {
                clocks.forEach { it.animateDoze(dozeState.isActive, false) }
                view.animateDoze(dozeState.isActive, false)
            }
        }

        override fun enter() {
            if (!dozeState.isActive) {
                clocks.forEach { it.animateAppearOnLockscreen() }
                view.animateAppearOnLockscreen()
            }
        }

        override fun charge() = clocks.forEach { it.animateCharge { dozeState.isActive } }
        override fun charge() = view.animateCharge { dozeState.isActive }

        override fun fold(fraction: Float) {
            val (hasChanged, hasJumped) = foldState.update(fraction)
            if (hasChanged) {
                clocks.forEach { it.animateFoldAppear(!hasJumped) }
                view.animateFoldAppear(!hasJumped)
            }
        }

        override fun doze(fraction: Float) {
            val (hasChanged, hasJumped) = dozeState.update(fraction)
            if (hasChanged) {
                clocks.forEach { it.animateDoze(dozeState.isActive, !hasJumped) }
                view.animateDoze(dozeState.isActive, !hasJumped)
            }
        }
    }

    inner class LargeClockAnimations(
        view: AnimatableClockView,
        dozeFraction: Float,
        foldFraction: Float,
    ) : DefaultClockAnimations(view, dozeFraction, foldFraction) {
        override fun onPositionUpdated(fromRect: Rect, toRect: Rect, fraction: Float) {
            largeClock.moveForSplitShade(fromRect, toRect, fraction)
        }
+14 −12
Original line number Diff line number Diff line
@@ -69,9 +69,6 @@ interface ClockController {
    /** Events that clocks may need to respond to */
    val events: ClockEvents

    /** Triggers for various animations */
    val animations: ClockAnimations

    /** Initializes various rendering parameters. If never called, provides reasonable defaults. */
    fun initialize(
        resources: Resources,
@@ -79,8 +76,10 @@ interface ClockController {
        foldFraction: Float,
    ) {
        events.onColorPaletteChanged(resources)
        animations.doze(dozeFraction)
        animations.fold(foldFraction)
        smallClock.animations.doze(dozeFraction)
        largeClock.animations.doze(dozeFraction)
        smallClock.animations.fold(foldFraction)
        largeClock.animations.fold(foldFraction)
        smallClock.events.onTimeTick()
        largeClock.events.onTimeTick()
    }
@@ -100,6 +99,9 @@ interface ClockFaceController {
    /** Events specific to this clock face */
    val events: ClockFaceEvents

    /** Triggers for various animations */
    val animations: ClockAnimations

    /** Some clocks may log debug information */
    var logBuffer: LogBuffer?
}
@@ -192,13 +194,6 @@ data class ClockMetadata(

/** Render configuration for the full clock. Modifies the way systemUI behaves with this clock. */
data class ClockConfig(
    /**
     * Whether this clock has a custom position update animation. If true, the keyguard will call
     * `onPositionUpdated` to notify the clock of a position update animation. If false, a default
     * animation will be used (e.g. a simple translation).
     */
    val hasCustomPositionUpdatedAnimation: Boolean = false,

    /** Transition to AOD should move smartspace like large clock instead of small clock */
    val useAlternateSmartspaceAODTransition: Boolean = false,

@@ -213,6 +208,13 @@ data class ClockFaceConfig(

    /** Call to check whether the clock consumes weather data */
    val hasCustomWeatherDataDisplay: Boolean = false,

    /**
     * Whether this clock has a custom position update animation. If true, the keyguard will call
     * `onPositionUpdated` to notify the clock of a position update animation. If false, a default
     * animation will be used (e.g. a simple translation).
     */
    val hasCustomPositionUpdatedAnimation: Boolean = false,
)

/** Structure for keeping clock-specific settings */
+48 −37
Original line number Diff line number Diff line
@@ -99,8 +99,10 @@ constructor(
                value.initialize(resources, dozeAmount, 0f)

                if (regionSamplingEnabled) {
                    clock?.smallClock?.view?.addOnLayoutChangeListener(mLayoutChangedListener)
                    clock?.largeClock?.view?.addOnLayoutChangeListener(mLayoutChangedListener)
                    clock?.run {
                        smallClock.view.addOnLayoutChangeListener(mLayoutChangedListener)
                        largeClock.view.addOnLayoutChangeListener(mLayoutChangedListener)
                    }
                } else {
                    updateColors()
                }
@@ -175,15 +177,17 @@ constructor(
    private fun updateColors() {
        val wallpaperManager = WallpaperManager.getInstance(context)
        if (regionSamplingEnabled && !wallpaperManager.lockScreenWallpaperExists()) {
            if (regionSampler != null) {
                if (regionSampler?.sampledView == clock?.smallClock?.view) {
                    smallClockIsDark = regionSampler!!.currentRegionDarkness().isDark
                    clock?.smallClock?.events?.onRegionDarknessChanged(smallClockIsDark)
                    return
                } else if (regionSampler?.sampledView == clock?.largeClock?.view) {
                    largeClockIsDark = regionSampler!!.currentRegionDarkness().isDark
                    clock?.largeClock?.events?.onRegionDarknessChanged(largeClockIsDark)
                    return
            regionSampler?.let { regionSampler ->
                clock?.let { clock ->
                    if (regionSampler.sampledView == clock.smallClock.view) {
                        smallClockIsDark = regionSampler.currentRegionDarkness().isDark
                        clock.smallClock.events.onRegionDarknessChanged(smallClockIsDark)
                        return@updateColors
                    } else if (regionSampler.sampledView == clock.largeClock.view) {
                        largeClockIsDark = regionSampler.currentRegionDarkness().isDark
                        clock.largeClock.events.onRegionDarknessChanged(largeClockIsDark)
                        return@updateColors
                    }
                }
            }
        }
@@ -193,8 +197,10 @@ constructor(
        smallClockIsDark = isLightTheme.data == 0
        largeClockIsDark = isLightTheme.data == 0

        clock?.smallClock?.events?.onRegionDarknessChanged(smallClockIsDark)
        clock?.largeClock?.events?.onRegionDarknessChanged(largeClockIsDark)
        clock?.run {
            smallClock.events.onRegionDarknessChanged(smallClockIsDark)
            largeClock.events.onRegionDarknessChanged(largeClockIsDark)
        }
    }

    private fun updateRegionSampler(sampledRegion: View) {
@@ -240,7 +246,7 @@ constructor(
    private val configListener =
        object : ConfigurationController.ConfigurationListener {
            override fun onThemeChanged() {
                clock?.events?.onColorPaletteChanged(resources)
                clock?.run { events.onColorPaletteChanged(resources) }
                updateColors()
            }

@@ -253,7 +259,10 @@ constructor(
        object : BatteryStateChangeCallback {
            override fun onBatteryLevelChanged(level: Int, pluggedIn: Boolean, charging: Boolean) {
                if (isKeyguardVisible && !isCharging && charging) {
                    clock?.animations?.charge()
                    clock?.run {
                        smallClock.animations.charge()
                        largeClock.animations.charge()
                    }
                }
                isCharging = charging
            }
@@ -262,7 +271,7 @@ constructor(
    private val localeBroadcastReceiver =
        object : BroadcastReceiver() {
            override fun onReceive(context: Context, intent: Intent) {
                clock?.events?.onLocaleChanged(Locale.getDefault())
                clock?.run { events.onLocaleChanged(Locale.getDefault()) }
            }
        }

@@ -272,7 +281,10 @@ constructor(
                isKeyguardVisible = visible
                if (!featureFlags.isEnabled(DOZING_MIGRATION_1)) {
                    if (!isKeyguardVisible) {
                        clock?.animations?.doze(if (isDozing) 1f else 0f)
                        clock?.run {
                            smallClock.animations.doze(if (isDozing) 1f else 0f)
                            largeClock.animations.doze(if (isDozing) 1f else 0f)
                        }
                    }
                }

@@ -281,19 +293,19 @@ constructor(
            }

            override fun onTimeFormatChanged(timeFormat: String?) {
                clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context))
                clock?.run { events.onTimeFormatChanged(DateFormat.is24HourFormat(context)) }
            }

            override fun onTimeZoneChanged(timeZone: TimeZone) {
                clock?.events?.onTimeZoneChanged(timeZone)
                clock?.run { events.onTimeZoneChanged(timeZone) }
            }

            override fun onUserSwitchComplete(userId: Int) {
                clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context))
                clock?.run { events.onTimeFormatChanged(DateFormat.is24HourFormat(context)) }
            }

            override fun onWeatherDataChanged(data: WeatherData) {
                clock?.events?.onWeatherDataChanged(data)
                clock?.run { events.onWeatherDataChanged(data) }
            }
        }

@@ -349,34 +361,33 @@ constructor(
        smallTimeListener = null
        largeTimeListener = null

        clock?.smallClock?.let {
            smallTimeListener = TimeListener(it, mainExecutor)
            smallTimeListener?.update(shouldTimeListenerRun)
        clock?.let {
            smallTimeListener = TimeListener(it.smallClock, mainExecutor).apply {
                update(shouldTimeListenerRun)
            }
            largeTimeListener = TimeListener(it.largeClock, mainExecutor).apply {
                update(shouldTimeListenerRun)
            }
        clock?.largeClock?.let {
            largeTimeListener = TimeListener(it, mainExecutor)
            largeTimeListener?.update(shouldTimeListenerRun)
        }
    }

    private fun updateFontSizes() {
        clock
            ?.smallClock
            ?.events
            ?.onFontSettingChanged(
        clock?.run {
            smallClock.events.onFontSettingChanged(
                resources.getDimensionPixelSize(R.dimen.small_clock_text_size).toFloat()
            )
        clock
            ?.largeClock
            ?.events
            ?.onFontSettingChanged(
            largeClock.events.onFontSettingChanged(
                resources.getDimensionPixelSize(R.dimen.large_clock_text_size).toFloat()
            )
        }
    }

    private fun handleDoze(doze: Float) {
        dozeAmount = doze
        clock?.animations?.doze(dozeAmount)
        clock?.run {
            smallClock.animations.doze(dozeAmount)
            largeClock.animations.doze(dozeAmount)
        }
        smallTimeListener?.update(doze < DOZE_TICKRATE_THRESHOLD)
        largeTimeListener?.update(doze < DOZE_TICKRATE_THRESHOLD)
    }
+5 −4
Original line number Diff line number Diff line
@@ -26,8 +26,6 @@ import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import kotlin.Unit;

/**
 * Switch to show plugin clock when plugin is connected, otherwise it will show default clock.
 */
@@ -38,6 +36,8 @@ public class KeyguardClockSwitch extends RelativeLayout {

    private static final long CLOCK_OUT_MILLIS = 150;
    private static final long CLOCK_IN_MILLIS = 200;
    public static final long CLOCK_IN_START_DELAY_MILLIS = CLOCK_OUT_MILLIS / 2;
    private static final long STATUS_AREA_START_DELAY_MILLIS = 50;
    private static final long STATUS_AREA_MOVE_MILLIS = 350;

    @IntDef({LARGE, SMALL})
@@ -173,7 +173,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
                msg.setBool1(useLargeClock);
                msg.setBool2(animate);
                msg.setBool3(mChildrenAreLaidOut);
                return Unit.INSTANCE;
                return kotlin.Unit.INSTANCE;
            }, (msg) -> "updateClockViews"
                    + "; useLargeClock=" + msg.getBool1()
                    + "; animate=" + msg.getBool2()
@@ -235,7 +235,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
        mClockInAnim.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
        mClockInAnim.playTogether(ObjectAnimator.ofFloat(in, View.ALPHA, 1f),
                ObjectAnimator.ofFloat(in, View.TRANSLATION_Y, direction * mClockSwitchYAmount, 0));
        mClockInAnim.setStartDelay(CLOCK_OUT_MILLIS / 2);
        mClockInAnim.setStartDelay(CLOCK_IN_START_DELAY_MILLIS);
        mClockInAnim.addListener(new AnimatorListenerAdapter() {
            public void onAnimationEnd(Animator animation) {
                mClockInAnim = null;
@@ -247,6 +247,7 @@ public class KeyguardClockSwitch extends RelativeLayout {

        mStatusAreaAnim = ObjectAnimator.ofFloat(mStatusArea, View.TRANSLATION_Y,
                statusAreaYTranslation);
        mStatusAreaAnim.setStartDelay(useLargeClock ? STATUS_AREA_START_DELAY_MILLIS : 0L);
        mStatusAreaAnim.setDuration(STATUS_AREA_MOVE_MILLIS);
        mStatusAreaAnim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
        mStatusAreaAnim.addListener(new AnimatorListenerAdapter() {
+7 −5
Original line number Diff line number Diff line
@@ -53,11 +53,11 @@ import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
import com.android.systemui.util.ViewController;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.settings.SecureSettings;

import java.io.PrintWriter;
import java.util.Locale;
import java.util.concurrent.Executor;

import javax.inject.Inject;

@@ -98,7 +98,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
    private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;

    private boolean mOnlyClock = false;
    private final Executor mUiExecutor;
    private final DelayableExecutor mUiExecutor;
    private boolean mCanShowDoubleLineClock = true;
    private final ContentObserver mDoubleLineClockObserver = new ContentObserver(null) {
        @Override
@@ -133,7 +133,7 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
            LockscreenSmartspaceController smartspaceController,
            KeyguardUnlockAnimationController keyguardUnlockAnimationController,
            SecureSettings secureSettings,
            @Main Executor uiExecutor,
            @Main DelayableExecutor uiExecutor,
            DumpManager dumpManager,
            ClockEventController clockEventController,
            @KeyguardClockLog LogBuffer logBuffer) {
@@ -344,7 +344,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
        ClockController clock = getClock();
        boolean appeared = mView.switchToClock(clockSize, animate);
        if (clock != null && animate && appeared && clockSize == LARGE) {
            clock.getAnimations().enter();
            mUiExecutor.executeDelayed(() -> clock.getLargeClock().getAnimations().enter(),
                    KeyguardClockSwitch.CLOCK_IN_START_DELAY_MILLIS);
        }
    }

@@ -354,7 +355,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
    public void animateFoldToAod(float foldFraction) {
        ClockController clock = getClock();
        if (clock != null) {
            clock.getAnimations().fold(foldFraction);
            clock.getSmallClock().getAnimations().fold(foldFraction);
            clock.getLargeClock().getAnimations().fold(foldFraction);
        }
    }

Loading