diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt index 3ec3b5c3f758c..6ca7f12e842bf 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt @@ -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) } diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt index 05630e7954767..8ef2d80330002 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt @@ -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 */ diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt index 7262a736c4333..8b87e2a538ca2 100644 --- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt +++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt @@ -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?.largeClock?.let { - largeTimeListener = TimeListener(it, mainExecutor) - largeTimeListener?.update(shouldTimeListenerRun) + clock?.let { + smallTimeListener = TimeListener(it.smallClock, mainExecutor).apply { + update(shouldTimeListenerRun) + } + largeTimeListener = TimeListener(it.largeClock, mainExecutor).apply { + 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) } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java index 5ba0ad62e9fbf..a6c782d88e18a 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java @@ -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() { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java index ad333b7bfbb65..a34c9fa5aced6 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java @@ -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 clock.getLargeClock().getAnimations().enter(), + KeyguardClockSwitch.CLOCK_IN_START_DELAY_MILLIS); } } @@ -354,7 +355,8 @@ public class KeyguardClockSwitchController extends ViewController