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

Commit e408b8b0 authored by Steven Ng's avatar Steven Ng
Browse files

Add GradientColorWallpaper in SystemUi

GradientColorWallpaper is a very sample wallpaper that draws a full screen rectangle.

Test: GradientColorWallpaperTest
Flag: android.app.enable_connected_displays_wallpaper
Bug: 384519696
Change-Id: Ie098a47451a3e8a6c05ef9626337212214cbca91
parent ce27eff9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -423,6 +423,7 @@ android_library {
    ],
    manifest: "AndroidManifest-res.xml",
    flags_packages: [
        "android.app.flags-aconfig",
        "com_android_systemui_flags",
    ],
}
+6 −0
Original line number Diff line number Diff line
@@ -547,6 +547,12 @@
                android:permission="android.permission.BIND_WALLPAPER"
                android:exported="true" />

        <service android:name=".wallpapers.GradientColorWallpaper"
            android:featureFlag="android.app.enable_connected_displays_wallpaper"
            android:singleUser="true"
            android:permission="android.permission.BIND_WALLPAPER"
            android:exported="true" />

        <activity android:name=".tuner.TunerActivity"
                  android:enabled="false"
                  android:icon="@drawable/tuner"
+85 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.wallpapers

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.RectF
import android.service.wallpaper.WallpaperService.Engine
import android.testing.TestableLooper.RunWithLooper
import android.view.Surface
import android.view.SurfaceHolder
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito.spy
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.any
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever

@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWithLooper
class GradientColorWallpaperTest : SysuiTestCase() {

    @Mock private lateinit var surfaceHolder: SurfaceHolder

    @Mock private lateinit var surface: Surface

    @Mock private lateinit var canvas: Canvas

    @Mock private lateinit var mockContext: Context

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)

        whenever(surfaceHolder.surface).thenReturn(surface)
        whenever(surfaceHolder.surfaceFrame).thenReturn(surfaceFrame)
        whenever(surface.lockHardwareCanvas()).thenReturn(canvas)
        whenever(mockContext.getColor(anyInt())).thenReturn(1)
    }

    private fun createGradientColorWallpaperEngine(): Engine {
        val gradientColorWallpaper = GradientColorWallpaper()
        val engine = spy(gradientColorWallpaper.onCreateEngine())
        whenever(engine.displayContext).thenReturn(mockContext)
        return engine
    }

    @Test
    fun onSurfaceRedrawNeeded_shouldDrawInCanvas() {
        val engine = createGradientColorWallpaperEngine()
        engine.onCreate(surfaceHolder)

        engine.onSurfaceRedrawNeeded(surfaceHolder)

        verify(canvas).drawRect(any<RectF>(), any<Paint>())
    }

    private companion object {
        val surfaceFrame = Rect(0, 0, 100, 100)
    }
}
+62 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.wallpapers

import android.graphics.Canvas
import android.graphics.Paint
import android.service.wallpaper.WallpaperService
import android.util.Log
import android.view.SurfaceHolder
import androidx.core.graphics.toRectF

/** A wallpaper that shows a static gradient color image wallpaper. */
class GradientColorWallpaper : WallpaperService() {

    override fun onCreateEngine(): Engine = GradientColorWallpaperEngine()

    inner class GradientColorWallpaperEngine : Engine() {
        init {
            setShowForAllUsers(true)
        }

        override fun onSurfaceRedrawNeeded(surfaceHolder: SurfaceHolder) {
            drawFrameInternal(surfaceHolder)
        }

        private fun drawFrameInternal(surfaceHolder: SurfaceHolder) {
            val context = displayContext ?: return
            val surface = surfaceHolder.surface
            var canvas: Canvas? = null
            try {
                canvas = surface.lockHardwareCanvas()
                val destRectF = surfaceHolder.surfaceFrame.toRectF()
                val toColor = context.getColor(com.android.internal.R.color.materialColorPrimary)

                // TODO(b/384519696): Draw the actual gradient color wallpaper instead.
                canvas.drawRect(destRectF, Paint().apply { color = toColor })
            } catch (exception: IllegalStateException) {
                Log.d(TAG, "Fail to draw in the canvas", exception)
            } finally {
                canvas?.let { surface.unlockCanvasAndPost(it) }
            }
        }
    }

    private companion object {
        const val TAG = "GradientColorWallpaper"
    }
}