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

Commit 3c61f986 authored by Hawkwood Glazier's avatar Hawkwood Glazier
Browse files

Modify null clock handling in picker

The plugin crash protection layer is predicated on ClockRegistry
returning null when a plugin has a crashing problem. As a result,
ThemePicker requiring a non-null response appears to hide the
underlying error. This fixes that by handling the null value at
all the relevant callsites by doing nothing.

The clock parts of ThemePicker will still undoubtedly be broken in
some way since a clock is failing to load or function, but this is
preferrable to ThemePicker crashing as a result of changes to the
library, especially since picker presubmits are not currently
running there.

Bug: 398070481
Test: Manual + Presubmits
Flag: NONE Bugfix
Change-Id: Id8e6f9888bc3b84c084587b2b4adade3934de286
parent 2f6c3c04
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -467,7 +467,7 @@ class ClockCarouselView(context: Context, attrs: AttributeSet) : FrameLayout(con
                it.pivotY = it.height / 2F
            }

            val controller = clockViewFactory.getController(clockId)
            clockViewFactory.getController(clockId)?.let { controller ->
                if (isMiddleView) {
                    clockScaleView.scaleX = 1f
                    clockScaleView.scaleY = 1f
@@ -478,6 +478,7 @@ class ClockCarouselView(context: Context, attrs: AttributeSet) : FrameLayout(con
                    controller.largeClock.animations.onPickerCarouselSwiping(0F)
                }
            }
        }

        private fun initializeSmallClockView(
            clockId: String,
+35 −36
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ import javax.inject.Inject
class ThemePickerClockViewFactory
@Inject
constructor(
    activity: Activity,
    private val activity: Activity,
    private val wallpaperManager: WallpaperManager,
    private val registry: ClockRegistry,
) : ClockViewFactory {
@@ -55,9 +55,9 @@ constructor(
    private val clockControllers: ConcurrentHashMap<String, ClockController> = ConcurrentHashMap()
    private val smallClockFrames: HashMap<String, FrameLayout> = HashMap()

    override fun getController(clockId: String): ClockController {
    override fun getController(clockId: String): ClockController? {
        return clockControllers[clockId]
            ?: initClockController(clockId).also { clockControllers[clockId] = it }
            ?: initClockController(clockId)?.also { clockControllers[clockId] = it }
    }

    /**
@@ -66,10 +66,10 @@ constructor(
     */
    override fun getLargeView(clockId: String): View {
        assert(!Flags.newCustomizationPickerUi())
        return getController(clockId).largeClock.let {
        return getController(clockId)?.largeClock?.let {
            it.animations.onPickerCarouselSwiping(1F)
            it.view
        }
        } ?: FrameLayout(activity)
    }

    /**
@@ -83,9 +83,9 @@ constructor(
                (layoutParams as FrameLayout.LayoutParams).topMargin = getSmallClockTopMargin()
                (layoutParams as FrameLayout.LayoutParams).marginStart = getSmallClockStartPadding()
            }
                ?: createSmallClockFrame().also {
                    it.addView(getController(clockId).smallClock.view)
                    smallClockFrames[clockId] = it
                ?: createSmallClockFrame().also { frame ->
                    getController(clockId)?.let { frame.addView(it.smallClock.view) }
                    smallClockFrames[clockId] = frame
                }
        smallClockFrame.translationX = 0F
        smallClockFrame.translationY = 0F
@@ -130,14 +130,14 @@ constructor(
    }

    override fun updateColor(clockId: String, @ColorInt seedColor: Int?) {
        getController(clockId).let {
        getController(clockId)?.let {
            it.largeClock.run { events.onThemeChanged(theme.copy(seedColor = seedColor)) }
            it.smallClock.run { events.onThemeChanged(theme.copy(seedColor = seedColor)) }
        }
    }

    override fun updateFontAxes(clockId: String, settings: List<ClockFontAxisSetting>) {
        getController(clockId).let { it.events.onFontAxesChanged(settings) }
        getController(clockId)?.let { it.events.onFontAxesChanged(settings) }
    }

    override fun updateRegionDarkness() {
@@ -155,8 +155,8 @@ constructor(

    override fun updateTimeFormat(clockId: String) {
        getController(clockId)
            .events
            .onTimeFormatChanged(android.text.format.DateFormat.is24HourFormat(appContext))
            ?.events
            ?.onTimeFormatChanged(android.text.format.DateFormat.is24HourFormat(appContext))
    }

    override fun registerTimeTicker(owner: LifecycleOwner) {
@@ -190,11 +190,10 @@ constructor(
        }
    }

    private fun initClockController(clockId: String): ClockController {
    private fun initClockController(clockId: String): ClockController? {
        val isWallpaperDark = isLockscreenWallpaperDark()
        val controller =
            registry.createExampleClock(clockId).also { it?.initialize(isWallpaperDark, 0f, 0f) }
        checkNotNull(controller)
        return registry.createExampleClock(clockId)?.also { controller ->
            controller.initialize(isWallpaperDark, 0f, 0f)

            // Initialize large clock
            controller.largeClock.events.onFontSettingChanged(
@@ -216,7 +215,7 @@ constructor(
            )
            controller.smallClock.events.onTargetRegionChanged(getSmallClockRegion())
            controller.events.onWeatherDataChanged(WeatherData.getPlaceholderWeatherData())
        return controller
        }
    }

    /**
+18 −8
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
@@ -57,15 +58,23 @@ class ClockCarouselViewModel(
            .mapLatest { allClocks ->
                // Delay to avoid the case that the full list of clocks is not initiated.
                delay(CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
                allClocks.map {
                allClocks
                    .map { model ->
                        clockViewFactory.getController(model.clockId)?.let { clock ->
                            val contentDescription =
                                resources.getString(
                                    R.string.select_clock_action_description,
                            clockViewFactory.getController(it.clockId).config.description
                                    clock.config.description,
                                )
                            ClockCarouselItemViewModel(
                                model.clockId,
                                model.isSelected,
                                contentDescription,
                            )
                    ClockCarouselItemViewModel(it.clockId, it.isSelected, contentDescription)
                        }
                    }
                    .filterNotNull()
            }
            // makes sure that the operations above this statement are executed on I/O dispatcher
            // while parallelism limits the number of threads this can run on which makes sure that
            // the flows run sequentially
@@ -126,6 +135,7 @@ class ClockCarouselViewModel(
            .mapNotNull { it }

    private var setSelectedClockJob: Job? = null

    fun setSelectedClock(clockId: String) {
        setSelectedClockJob?.cancel()
        setSelectedClockJob =
+1 −1
Original line number Diff line number Diff line
@@ -418,7 +418,7 @@ constructor(private val defaultCustomizationOptionsBinder: DefaultCustomizationO
                            clockHostView.removeAllViews()
                            // For new customization picker, we should get views from clocklayout
                            if (Flags.newCustomizationPickerUi()) {
                                clockViewFactory.getController(clock.clockId).let { clockController
                                clockViewFactory.getController(clock.clockId)?.let { clockController
                                    ->
                                    val udfpsTop =
                                        clockPickerViewModel.getUdfpsLocation()?.let {
+2 −2
Original line number Diff line number Diff line
@@ -146,14 +146,14 @@ constructor(
                            )
                            .collect { (previewingClock, previewingClockSize) ->
                                val hideSmartspace =
                                    clockViewFactory.getController(previewingClock.clockId).let {
                                    clockViewFactory.getController(previewingClock.clockId)?.let {
                                        when (previewingClockSize) {
                                            ClockSize.DYNAMIC ->
                                                it.largeClock.config.hasCustomWeatherDataDisplay
                                            ClockSize.SMALL ->
                                                it.smallClock.config.hasCustomWeatherDataDisplay
                                        }
                                    }
                                    } ?: false
                                workspaceCallback.sendMessage(
                                    MESSAGE_ID_HIDE_SMART_SPACE,
                                    Bundle().apply {
Loading