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

Commit 35330480 authored by Ibrahim Yilmaz's avatar Ibrahim Yilmaz Committed by Android (Google) Code Review
Browse files

Merge "Add timeout to loadImage to prevent shade freeze" into main

parents b44477da 56a930e7
Loading
Loading
Loading
Loading
+35 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.brightness.ui.viewmodel

import android.graphics.drawable.Icon
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.settingslib.display.BrightnessUtils
@@ -27,6 +28,7 @@ import com.android.systemui.brightness.shared.model.GammaBrightness
import com.android.systemui.brightness.shared.model.LinearBrightness
import com.android.systemui.classifier.domain.interactor.falsingInteractor
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.graphics.ImageLoader
import com.android.systemui.graphics.imageLoader
import com.android.systemui.haptics.slider.sliderHapticsViewModelFactory
import com.android.systemui.kosmos.Kosmos
@@ -37,11 +39,15 @@ import com.android.systemui.settings.brightness.domain.interactor.brightnessMirr
import com.android.systemui.settings.brightness.ui.brightnessWarningToast
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.delay
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.doSuspendableAnswer
import org.mockito.kotlin.mock

@SmallTest
@RunWith(AndroidJUnit4::class)
@@ -225,7 +231,35 @@ class BrightnessSliderViewModelTest : SysuiTestCase() {
        }
    }

    private fun Kosmos.create(supportsMirror: Boolean = true): BrightnessSliderViewModel {
    @Test
    fun loadImage_timesOutAndReturnsNull_whenLoaderHangs() =
        with(kosmos) {
            testScope.runTest {
                // GIVEN: a mock ImageLoader that simulates a long-running operation
                val hangingImageLoader: ImageLoader = mock {
                    onBlocking {
                        loadDrawable(any<Icon>(), any(), any(), any(), any())
                    } doSuspendableAnswer
                        {
                            delay(10_000)
                            mock<android.graphics.drawable.Drawable>()
                        }
                }

                val underTest = create(imageLoader = hangingImageLoader)

                // WHEN: we load the image
                val loadedIcon = underTest.loadImage(R.drawable.ic_brightness_full, context)

                // THEN: return null due to timeout
                assertThat(loadedIcon).isNull()
            }
        }

    private fun Kosmos.create(
        supportsMirror: Boolean = true,
        imageLoader: ImageLoader = this.imageLoader,
    ): BrightnessSliderViewModel {
        return BrightnessSliderViewModel(
            screenBrightnessInteractor,
            brightnessPolicyEnforcementInteractor,
+8 −7
Original line number Diff line number Diff line
@@ -83,7 +83,6 @@ import com.android.compose.modifiers.padding
import com.android.compose.modifiers.thenIf
import com.android.compose.theme.LocalAndroidColorScheme
import com.android.compose.ui.graphics.drawInOverlay
import com.android.systemui.Flags
import com.android.systemui.biometrics.Utils.toBitmap
import com.android.systemui.brightness.shared.model.GammaBrightness
import com.android.systemui.brightness.ui.compose.AnimationSpecs.IconAppearSpec
@@ -115,7 +114,7 @@ fun BrightnessSlider(
    gammaValue: Int,
    valueRange: IntRange,
    iconResProvider: (Float) -> Int,
    imageLoader: suspend (Int, Context) -> Icon.Loaded,
    imageLoader: suspend (Int, Context) -> Icon.Loaded?,
    restriction: PolicyRestriction,
    onRestrictedClick: (PolicyRestriction.Restricted) -> Unit,
    onDrag: (Int) -> Unit,
@@ -165,12 +164,14 @@ fun BrightnessSlider(
            key1 = iconRes,
            key2 = context,
        ) {
            val icon = imageLoader(iconRes, context)
            // toBitmap is Drawable?.() -> Bitmap? and handles null internally.
            val bitmap = icon.drawable.toBitmap()!!.asImageBitmap()
            val icon: Icon.Loaded? = imageLoader(iconRes, context)
            if (icon != null) {
                val bitmap = icon.drawable.toBitmap()?.asImageBitmap()
                if (bitmap != null) {
                    this@produceState.value = BitmapPainter(bitmap)
                }

            }
        }
    val activeIconColor = colors.activeTickColor
    val inactiveIconColor = colors.inactiveTickColor
    // Offset from the right
+11 −8
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.withTimeoutOrNull

/**
 * View Model for a brightness slider.
@@ -102,14 +103,16 @@ constructor(
        falsingInteractor.isFalseTouch(Classifier.BRIGHTNESS_SLIDER)
    }

    suspend fun loadImage(@DrawableRes resId: Int, context: Context): Icon.Loaded {
        return imageLoader
    suspend fun loadImage(@DrawableRes resId: Int, context: Context): Icon.Loaded? {
        return withTimeoutOrNull(500L) {
            imageLoader
                .loadDrawable(
                    android.graphics.drawable.Icon.createWithResource(context, resId),
                    maxHeight = 200,
                    maxWidth = 200,
            )!!
            .asIcon(null, resId)
                )
                ?.asIcon(null, resId)
        }
    }

    /**