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

Commit 76bc2cef authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 11585034 from a0286ce3 to 24Q3-release

Change-Id: I5f9ae73cc401c0e448af75a97bd2cf5c36895921
parents 00730b89 a0286ce3
Loading
Loading
Loading
Loading
+168 −15
Original line number Diff line number Diff line
@@ -17,7 +17,13 @@
package com.android.app.tracing.coroutines

import com.android.app.tracing.TraceState.openSectionsOnCurrentThread
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.newSingleThreadContext
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertArrayEquals
import org.junit.Assert.assertEquals
@@ -25,27 +31,174 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.BlockJUnit4ClassRunner

/**
 * Helper util for asserting that the open trace sections on the current thread equal the passed
 * list of strings.
 */
private fun assertTraceEquals(vararg openTraceSections: String) {
    assertArrayEquals(openTraceSections, openSectionsOnCurrentThread())
}

/** Helper util for asserting that there are no open trace sections on the current thread. */
private fun assertTraceIsEmpty() = assertEquals(0, openSectionsOnCurrentThread().size)

/**
 * Helper util for calling [runTest] with a [TraceContextElement]. This is useful for formatting
 * purposes. Passing an arg to `runTest {}` directly, as in `fun testStuff() =
 * runTest(TraceContextElement()) {}` would require more indentations according to our style guide.
 */
private fun runTestWithTraceContext(testBody: suspend TestScope.() -> Unit) =
    runTest(context = TraceContextElement(), testBody = testBody)

@RunWith(BlockJUnit4ClassRunner::class)
class CoroutineTracingTest {

    @Test
    fun nestedTraceSectionsOnSingleThread() {
        runTest(TraceContextElement()) {
    fun nestedTraceSectionsOnSingleThread() = runTestWithTraceContext {
        val fetchData: suspend () -> String = {
            delay(1L)
            traceCoroutine("span-for-fetchData") {
                    assertArrayEquals(
                        arrayOf("span-for-launch", "span-for-fetchData"),
                        openSectionsOnCurrentThread()
                    )
                assertTraceEquals("span-for-launch", "span-for-fetchData")
            }
            "stuff"
        }
        launch("span-for-launch") {
            assertEquals("stuff", fetchData())
                assertArrayEquals(arrayOf("span-for-launch"), openSectionsOnCurrentThread())
            assertTraceEquals("span-for-launch")
        }
        assertTraceIsEmpty()
    }

    private fun CoroutineScope.testTraceSectionsMultiThreaded(
        thread1Context: CoroutineContext,
        thread2Context: CoroutineContext
    ) {
        val fetchData1: suspend () -> String = {
            assertTraceEquals("span-for-launch-1")
            delay(1L)
            traceCoroutine("span-for-fetchData-1") {
                assertTraceEquals("span-for-launch-1", "span-for-fetchData-1")
            }
            assertTraceEquals("span-for-launch-1")
            "stuff-1"
        }

        val fetchData2: suspend () -> String = {
            assertTraceEquals(
                "span-for-launch-1",
                "span-for-launch-2",
            )
            delay(1L)
            traceCoroutine("span-for-fetchData-2") {
                assertTraceEquals("span-for-launch-1", "span-for-launch-2", "span-for-fetchData-2")
            }
            assertTraceEquals(
                "span-for-launch-1",
                "span-for-launch-2",
            )
            "stuff-2"
        }

        val thread1 = newSingleThreadContext("thread-#1") + thread1Context
        val thread2 = newSingleThreadContext("thread-#2") + thread2Context

        launch("span-for-launch-1", thread1) {
            assertEquals("stuff-1", fetchData1())
            assertTraceEquals("span-for-launch-1")
            launch("span-for-launch-2", thread2) {
                assertEquals("stuff-2", fetchData2())
                assertTraceEquals("span-for-launch-1", "span-for-launch-2")
            }
            assertTraceEquals("span-for-launch-1")
        }
        assertTraceIsEmpty()

        // Launching without the trace extension won't result in traces
        launch(thread1) { assertTraceIsEmpty() }
        launch(thread2) { assertTraceIsEmpty() }
    }
            assertEquals(0, openSectionsOnCurrentThread().size)

    @Test
    fun nestedTraceSectionsMultiThreaded1() = runTestWithTraceContext {
        // Thread-#1 and Thread-#2 inherit TraceContextElement from the test's CoroutineContext.
        testTraceSectionsMultiThreaded(
            thread1Context = EmptyCoroutineContext,
            thread2Context = EmptyCoroutineContext
        )
    }

    @Test
    fun nestedTraceSectionsMultiThreaded2() = runTest {
        // Thread-#2 inherits the TraceContextElement from Thread-#1. The test's CoroutineContext
        // does not need a TraceContextElement because it does not do any tracing.
        testTraceSectionsMultiThreaded(
            thread1Context = TraceContextElement(),
            thread2Context = EmptyCoroutineContext
        )
    }

    @Test
    fun nestedTraceSectionsMultiThreaded3() = runTest {
        // Thread-#2 overrides the TraceContextElement from Thread-#1, but the merging context
        // should be fine; it is essentially a no-op. The test's CoroutineContext does not need the
        // trace context because it does not do any tracing.
        testTraceSectionsMultiThreaded(
            thread1Context = TraceContextElement(),
            thread2Context = TraceContextElement()
        )
    }

    @Test
    fun nestedTraceSectionsMultiThreaded4() = runTestWithTraceContext {
        // TraceContextElement is merged on each context switch, which should have no effect on the
        // trace results.
        testTraceSectionsMultiThreaded(
            thread1Context = TraceContextElement(),
            thread2Context = TraceContextElement()
        )
    }

    @Test
    fun missingTraceContextObjects() = runTest {
        // Thread-#1 is missing a TraceContextElement, so some of the trace sections get dropped.
        // The resulting trace sections will be different than the 4 tests above.
        val fetchData1: suspend () -> String = {
            assertTraceIsEmpty()
            delay(1L)
            traceCoroutine("span-for-fetchData-1") { assertTraceIsEmpty() }
            assertTraceIsEmpty()
            "stuff-1"
        }

        val fetchData2: suspend () -> String = {
            assertTraceEquals(
                "span-for-launch-2",
            )
            delay(1L)
            traceCoroutine("span-for-fetchData-2") {
                assertTraceEquals("span-for-launch-2", "span-for-fetchData-2")
            }
            assertTraceEquals(
                "span-for-launch-2",
            )
            "stuff-2"
        }

        val thread1 = newSingleThreadContext("thread-#1")
        val thread2 = newSingleThreadContext("thread-#2") + TraceContextElement()

        launch("span-for-launch-1", thread1) {
            assertEquals("stuff-1", fetchData1())
            assertTraceIsEmpty()
            launch("span-for-launch-2", thread2) {
                assertEquals("stuff-2", fetchData2())
                assertTraceEquals("span-for-launch-2")
            }
            assertTraceIsEmpty()
        }
        assertTraceIsEmpty()

        // Launching without the trace extension won't result in traces
        launch(thread1) { assertTraceIsEmpty() }
        launch(thread2) { assertTraceIsEmpty() }
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -22,14 +22,14 @@ uniform half snowThickness;
#include "shaders/utils.agsl"

float random(vec2 uv) {
    return fract(sin(dot(uv.xy, vec2(14.53898, 56.233))) * 45312.644263742);
    return fract(sin(dot(uv, vec2(14.53898, 56.233))) * 45312.644263742);
}

vec4 main(float2 fragCoord) {
    // fragCoord should be already the adjusted UVs to have the expected rect of the image.
    vec2 uv = fragCoord / imageWidth;
    float variation = 0.3 + simplex2d(11. * uv);
    float distance = 20. * variation * snowThickness;
    float distance = variation * snowThickness;

    float aN = foreground.eval(fragCoord + vec2(0., distance)).a;
    float aS = foreground.eval(fragCoord + vec2(0., -distance)).a;
+0 −1
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
uniform shader foreground;
uniform shader background;
uniform shader accumulatedSnow;
uniform shader blurredBackground;
uniform float2 uvOffsetFgd;
uniform float2 uvScaleFgd;
uniform float2 uvOffsetBgd;
+14 −12
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import com.google.android.wallpaper.weathereffects.graphics.FrameBuffer
import com.google.android.wallpaper.weathereffects.graphics.WeatherEffect
import com.google.android.wallpaper.weathereffects.graphics.utils.GraphicsUtils
import com.google.android.wallpaper.weathereffects.graphics.utils.ImageCrop
import com.google.android.wallpaper.weathereffects.graphics.utils.MathUtils
import java.util.concurrent.Executor
import kotlin.random.Random

@@ -39,6 +40,7 @@ class SnowEffect(
    private val mainExecutor: Executor
) : WeatherEffect {

    private var snowSpeed: Float = 0.8f
    private val snowPaint = Paint().also { it.shader = snowConfig.colorGradingShader }
    private var elapsedTime: Float = 0f

@@ -59,7 +61,8 @@ class SnowEffect(
    override fun resize(newSurfaceSize: SizeF) = adjustCropping(newSurfaceSize)

    override fun update(deltaMillis: Long, frameTimeNanos: Long) {
        elapsedTime += deltaMillis * MILLIS_TO_SECONDS
        elapsedTime += snowSpeed * deltaMillis * MILLIS_TO_SECONDS

        snowConfig.shader.setFloatUniform("time", elapsedTime)
        snowConfig.colorGradingShader.setInputShader("texture", snowConfig.shader)
    }
@@ -79,13 +82,21 @@ class SnowEffect(
    }

    override fun setIntensity(intensity: Float) {
        /**
         * Increase effect speed as weather intensity decreases. This compensates for the floaty
         * appearance when there are fewer particles at the original speed.
         */
        snowSpeed = MathUtils.map(intensity, 0f, 1f, 2.5f, 1.7f)

        snowConfig.shader.setFloatUniform("intensity", intensity)
        snowConfig.colorGradingShader.setFloatUniform(
            "intensity",
            snowConfig.colorGradingIntensity * intensity
        )
        snowConfig.accumulatedSnowShader.setFloatUniform("snowThickness", intensity)

        snowConfig.accumulatedSnowShader.setFloatUniform(
            "snowThickness",
            snowConfig.maxAccumulatedSnowThickness * intensity
        )
        // Regenerate accumulated snow since the uniform changed.
        generateAccumulatedSnow()
    }
@@ -142,15 +153,6 @@ class SnowEffect(
            "background",
            BitmapShader(snowConfig.background, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR)
        )

        snowConfig.shader.setInputBuffer(
            "blurredBackground",
            BitmapShader(
                snowConfig.blurredBackground,
                Shader.TileMode.MIRROR,
                Shader.TileMode.MIRROR
            )
        )
    }

    private fun prepareColorGrading() {
+5 −1
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ data class SnowEffectConfig(
    @FloatRange(from = 0.0, to = 1.0) val intensity: Float,
    /** The intensity of the color grading. 0: no color grading, 1: color grading in full effect. */
    @FloatRange(from = 0.0, to = 1.0) val colorGradingIntensity: Float,
    /** Max thickness for the accumulated snow. */
    val maxAccumulatedSnowThickness: Float,
) {
    /**
     * Constructor for [SnowEffectConfig].
@@ -67,7 +69,8 @@ data class SnowEffectConfig(
        background,
        blurredBackground = GraphicsUtils.blurImage(context, background, BLUR_RADIUS),
        intensity,
        COLOR_GRADING_INTENSITY
        COLOR_GRADING_INTENSITY,
        MAX_SNOW_THICKNESS
    )

    private companion object {
@@ -78,5 +81,6 @@ data class SnowEffectConfig(
        private const val BLUR_RADIUS = 20f
        private const val DEFAULT_INTENSITY = 1f
        private const val COLOR_GRADING_INTENSITY = 0.7f
        private const val MAX_SNOW_THICKNESS = 10f
    }
}
Loading