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

Commit 471dc8d1 authored by Florence Yang's avatar Florence Yang Committed by Automerger Merge Worker
Browse files

Merge "LS Wallpaper Sampling for LS Smartspace" into udc-dev am: 77c206e3

parents 8149db13 77c206e3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -588,7 +588,7 @@ public final class WallpaperColors implements Parcelable {

        int hints = 0;
        double meanLuminance = totalLuminance / pixels.length;
        if (meanLuminance > BRIGHT_IMAGE_MEAN_LUMINANCE && darkPixels < maxDarkPixels) {
        if (meanLuminance > BRIGHT_IMAGE_MEAN_LUMINANCE && darkPixels <= maxDarkPixels) {
            hints |= HINT_SUPPORTS_DARK_TEXT;
        }
        if (meanLuminance < DARK_THEME_MEAN_LUMINANCE) {
+2 −2
Original line number Diff line number Diff line
@@ -1680,14 +1680,14 @@ public class WallpaperManager {
     * @hide
     */
    public void addOnColorsChangedListener(@NonNull LocalWallpaperColorConsumer callback,
            List<RectF> regions) throws IllegalArgumentException {
            List<RectF> regions, int which) throws IllegalArgumentException {
        for (RectF region : regions) {
            if (!LOCAL_COLOR_BOUNDS.contains(region)) {
                throw new IllegalArgumentException("Regions must be within bounds "
                        + LOCAL_COLOR_BOUNDS);
            }
        }
        sGlobals.addOnColorsChangedListener(callback, regions, FLAG_SYSTEM,
        sGlobals.addOnColorsChangedListener(callback, regions, which,
                                                 mContext.getUserId(), mContext.getDisplayId());
    }

+86 −30
Original line number Diff line number Diff line
@@ -21,9 +21,9 @@ import android.graphics.Color
import android.graphics.Point
import android.graphics.Rect
import android.graphics.RectF
import android.util.Log
import android.view.View
import androidx.annotation.VisibleForTesting
import com.android.systemui.shared.navigationbar.RegionSamplingHelper
import java.io.PrintWriter
import java.util.concurrent.Executor

@@ -31,20 +31,21 @@ import java.util.concurrent.Executor
open class RegionSampler
@JvmOverloads
constructor(
    val sampledView: View?,
    val sampledView: View,
    mainExecutor: Executor?,
    val bgExecutor: Executor?,
    val regionSamplingEnabled: Boolean,
    val isLockscreen: Boolean = false,
    val wallpaperManager: WallpaperManager? = WallpaperManager.getInstance(sampledView.context),
    val updateForegroundColor: UpdateColorCallback,
    val wallpaperManager: WallpaperManager? = WallpaperManager.getInstance(sampledView?.context)
) : WallpaperManager.LocalWallpaperColorConsumer {
    private var regionDarkness = RegionDarkness.DEFAULT
    private var samplingBounds = Rect()
    private val tmpScreenLocation = IntArray(2)
    @VisibleForTesting var regionSampler: RegionSamplingHelper? = null
    private var lightForegroundColor = Color.WHITE
    private var darkForegroundColor = Color.BLACK
    private val displaySize = Point()
    @VisibleForTesting val displaySize = Point()
    private var initialSampling: WallpaperColors? = null

    /**
     * Sets the colors to be used for Dark and Light Foreground.
@@ -57,6 +58,36 @@ constructor(
        darkForegroundColor = darkColor
    }

    private val layoutChangedListener =
        object : View.OnLayoutChangeListener {

            override fun onLayoutChange(
                view: View?,
                left: Int,
                top: Int,
                right: Int,
                bottom: Int,
                oldLeft: Int,
                oldTop: Int,
                oldRight: Int,
                oldBottom: Int
            ) {

                // don't pass in negative bounds when region is in transition state
                if (sampledView.locationOnScreen[0] < 0 || sampledView.locationOnScreen[1] < 0) {
                    return
                }

                val currentViewRect = Rect(left, top, right, bottom)
                val oldViewRect = Rect(oldLeft, oldTop, oldRight, oldBottom)

                if (currentViewRect != oldViewRect) {
                    stopRegionSampler()
                    startRegionSampler()
                }
            }
        }

    /**
     * Determines which foreground color to use based on region darkness.
     *
@@ -84,40 +115,57 @@ constructor(

    /** Start region sampler */
    fun startRegionSampler() {
        if (!regionSamplingEnabled || sampledView == null) {

        if (!regionSamplingEnabled) {
            if (DEBUG) Log.d(TAG, "startRegionSampler() | RegionSampling flag not enabled")
            return
        }

        val sampledRegion = calculateSampledRegion(sampledView)
        val regions = ArrayList<RectF>()
        val sampledRegionWithOffset = convertBounds(sampledRegion)
        sampledView.addOnLayoutChangeListener(layoutChangedListener)

        val screenLocationBounds = calculateScreenLocation(sampledView)
        if (screenLocationBounds == null) {
            if (DEBUG) Log.d(TAG, "startRegionSampler() | passed in null region")
            return
        }
        if (screenLocationBounds.isEmpty) {
            if (DEBUG) Log.d(TAG, "startRegionSampler() | passed in empty region")
            return
        }

        val sampledRegionWithOffset = convertBounds(screenLocationBounds)
        if (
            sampledRegionWithOffset.left < 0.0 ||
                sampledRegionWithOffset.right > 1.0 ||
                sampledRegionWithOffset.top < 0.0 ||
                sampledRegionWithOffset.bottom > 1.0
        ) {
            android.util.Log.e(
                "RegionSampler",
                "view out of bounds: $sampledRegion | " +
            if (DEBUG)
                Log.d(
                    TAG,
                    "startRegionSampler() | view out of bounds: $screenLocationBounds | " +
                        "screen width: ${displaySize.x}, screen height: ${displaySize.y}",
                    Exception()
                )
            return
        }

        val regions = ArrayList<RectF>()
        regions.add(sampledRegionWithOffset)

        wallpaperManager?.removeOnColorsChangedListener(this)
        wallpaperManager?.addOnColorsChangedListener(this, regions)
        wallpaperManager?.addOnColorsChangedListener(
            this,
            regions,
            if (isLockscreen) WallpaperManager.FLAG_LOCK else WallpaperManager.FLAG_SYSTEM
        )

        // TODO(b/265969235): conditionally set FLAG_LOCK or FLAG_SYSTEM once HS smartspace
        // implemented
        bgExecutor?.execute(
            Runnable {
                val initialSampling =
                    wallpaperManager?.getWallpaperColors(WallpaperManager.FLAG_LOCK)
                initialSampling =
                    wallpaperManager?.getWallpaperColors(
                        if (isLockscreen) WallpaperManager.FLAG_LOCK
                        else WallpaperManager.FLAG_SYSTEM
                    )
                onColorsChanged(sampledRegionWithOffset, initialSampling)
            }
        )
@@ -126,6 +174,7 @@ constructor(
    /** Stop region sampler */
    fun stopRegionSampler() {
        wallpaperManager?.removeOnColorsChangedListener(this)
        sampledView.removeOnLayoutChangeListener(layoutChangedListener)
    }

    /** Dump region sampler */
@@ -138,22 +187,23 @@ constructor(
        pw.println("passed-in sampledView: $sampledView")
        pw.println("calculated samplingBounds: $samplingBounds")
        pw.println(
            "sampledView width: ${sampledView?.width}, sampledView height: ${sampledView?.height}"
            "sampledView width: ${sampledView.width}, sampledView height: ${sampledView.height}"
        )
        pw.println("screen width: ${displaySize.x}, screen height: ${displaySize.y}")
        pw.println(
            "sampledRegionWithOffset: ${convertBounds(calculateSampledRegion(sampledView!!))}"
            "sampledRegionWithOffset: ${convertBounds(
                    calculateScreenLocation(sampledView) ?: RectF())}"
        )
        // TODO(b/265969235): mock initialSampling based on if component is on HS or LS wallpaper
        // HS Smartspace - wallpaperManager?.getWallpaperColors(WallpaperManager.FLAG_SYSTEM)
        // LS Smartspace, clock - wallpaperManager?.getWallpaperColors(WallpaperManager.FLAG_LOCK)
        pw.println(
            "initialSampling for lockscreen: " +
                "${wallpaperManager?.getWallpaperColors(WallpaperManager.FLAG_LOCK)}"
            "initialSampling for ${if (isLockscreen) "lockscreen" else "homescreen" }" +
                ": $initialSampling"
        )
    }

    fun calculateSampledRegion(sampledView: View): RectF {
    fun calculateScreenLocation(sampledView: View): RectF? {

        if (!sampledView.isLaidOut) return null

        val screenLocation = tmpScreenLocation
        /**
         * The method getLocationOnScreen is used to obtain the view coordinates relative to its
@@ -181,7 +231,8 @@ constructor(
     */
    fun convertBounds(originalBounds: RectF): RectF {

        // TODO(b/265969235): GRAB # PAGES + CURRENT WALLPAPER PAGE # FROM LAUNCHER
        // TODO(b/265969235): GRAB # PAGES + CURRENT WALLPAPER PAGE # FROM LAUNCHER (--> HS
        // Smartspace always on 1st page)
        // TODO(b/265968912): remove hard-coded value once LS wallpaper supported
        val wallpaperPageNum = 0
        val numScreens = 1
@@ -214,6 +265,11 @@ constructor(
            )
        updateForegroundColor()
    }

    companion object {
        private const val TAG = "RegionSampler"
        private const val DEBUG = false
    }
}

typealias UpdateColorCallback = () -> Unit
+11 −50
Original line number Diff line number Diff line
@@ -21,13 +21,11 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.res.Resources
import android.graphics.Rect
import android.text.format.DateFormat
import android.util.TypedValue
import android.view.View
import android.view.View.OnAttachStateChangeListener
import android.view.ViewTreeObserver
import android.widget.FrameLayout
import androidx.annotation.VisibleForTesting
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
@@ -55,16 +53,16 @@ import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.concurrency.DelayableExecutor
import java.util.Locale
import java.util.TimeZone
import java.util.concurrent.Executor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DisposableHandle
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
import java.util.Locale
import java.util.TimeZone
import java.util.concurrent.Executor
import javax.inject.Inject

/**
 * Controller for a Clock provided by the registry and used on the keyguard. Instantiated by
@@ -98,12 +96,7 @@ constructor(

                value.initialize(resources, dozeAmount, 0f)

                if (regionSamplingEnabled) {
                    clock?.run {
                        smallClock.view.addOnLayoutChangeListener(mLayoutChangedListener)
                        largeClock.view.addOnLayoutChangeListener(mLayoutChangedListener)
                    }
                } else {
                if (!regionSamplingEnabled) {
                    updateColors()
                }
                updateFontSizes()
@@ -140,44 +133,10 @@ constructor(
    private var disposableHandle: DisposableHandle? = null
    private val regionSamplingEnabled = featureFlags.isEnabled(REGION_SAMPLING)

    private val mLayoutChangedListener =
        object : View.OnLayoutChangeListener {

            override fun onLayoutChange(
                view: View?,
                left: Int,
                top: Int,
                right: Int,
                bottom: Int,
                oldLeft: Int,
                oldTop: Int,
                oldRight: Int,
                oldBottom: Int
            ) {
                view?.removeOnLayoutChangeListener(this)

                val parent = (view?.parent) as FrameLayout

                // don't pass in negative bounds when clocks are in transition state
                if (view.locationOnScreen[0] < 0 || view.locationOnScreen[1] < 0) {
                    return
                }

                val currentViewRect = Rect(left, top, right, bottom)
                val oldViewRect = Rect(oldLeft, oldTop, oldRight, oldBottom)

                if (
                    currentViewRect.width() != oldViewRect.width() ||
                        currentViewRect.height() != oldViewRect.height()
                ) {
                    updateRegionSampler(view)
                }
            }
        }

    private fun updateColors() {
        val wallpaperManager = WallpaperManager.getInstance(context)
        if (regionSamplingEnabled && !wallpaperManager.lockScreenWallpaperExists()) {
        if (regionSamplingEnabled) {
            regionSampler?.let { regionSampler ->
                clock?.let { clock ->
                    if (regionSampler.sampledView == clock.smallClock.view) {
@@ -212,6 +171,7 @@ constructor(
                    mainExecutor,
                    bgExecutor,
                    regionSamplingEnabled,
                    isLockscreen = true,
                    ::updateColors
                )
                ?.apply { startRegionSampler() }
@@ -220,10 +180,11 @@ constructor(
    }

    protected open fun createRegionSampler(
        sampledView: View?,
        sampledView: View,
        mainExecutor: Executor?,
        bgExecutor: Executor?,
        regionSamplingEnabled: Boolean,
        isLockscreen: Boolean,
        updateColors: () -> Unit
    ): RegionSampler? {
        return RegionSampler(
@@ -231,8 +192,8 @@ constructor(
            mainExecutor,
            bgExecutor,
            regionSamplingEnabled,
            updateColors
        )
            isLockscreen,
        ) { updateColors() }
    }

    var regionSampler: RegionSampler? = null
+12 −15
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.lockscreen

import android.app.PendingIntent
import android.app.WallpaperManager
import android.app.smartspace.SmartspaceConfig
import android.app.smartspace.SmartspaceManager
import android.app.smartspace.SmartspaceSession
@@ -56,7 +55,6 @@ import com.android.systemui.plugins.WeatherData
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.settings.UserTracker
import com.android.systemui.shared.regionsampling.RegionSampler
import com.android.systemui.shared.regionsampling.UpdateColorCallback
import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.DATE_SMARTSPACE_DATA_PLUGIN
import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.WEATHER_SMARTSPACE_DATA_PLUGIN
import com.android.systemui.statusbar.phone.KeyguardBypassController
@@ -120,7 +118,7 @@ constructor(

    private val regionSamplingEnabled =
            featureFlags.isEnabled(Flags.REGION_SAMPLING)
    private var isContentUpdatedOnce = false
    private var isRegionSamplersCreated = false
    private var showNotifications = false
    private var showSensitiveContentForCurrentUser = false
    private var showSensitiveContentForManagedUser = false
@@ -128,7 +126,6 @@ constructor(

    // TODO(b/202758428): refactor so that we can test color updates via region samping, similar to
    //  how we test color updates when theme changes (See testThemeChangeUpdatesTextColor).
    private val updateFun: UpdateColorCallback = { updateTextColorFromRegionSampler() }

    // TODO: Move logic into SmartspaceView
    var stateChangeListener = object : View.OnAttachStateChangeListener {
@@ -144,6 +141,9 @@ constructor(
        override fun onViewDetachedFromWindow(v: View) {
            smartspaceViews.remove(v as SmartspaceView)

            regionSamplers[v]?.stopRegionSampler()
            regionSamplers.remove(v as SmartspaceView)

            if (smartspaceViews.isEmpty()) {
                disconnect()
            }
@@ -170,7 +170,7 @@ constructor(

        val filteredTargets = targets.filter(::filterSmartspaceTarget)
        plugin?.onTargetsAvailable(filteredTargets)
        if (!isContentUpdatedOnce) {
        if (!isRegionSamplersCreated) {
            for (v in smartspaceViews) {
                if (regionSamplingEnabled) {
                    var regionSampler = RegionSampler(
@@ -178,15 +178,14 @@ constructor(
                        uiExecutor,
                        bgExecutor,
                        regionSamplingEnabled,
                        updateFun
                    )
                        isLockscreen = true,
                    ) { updateTextColorFromRegionSampler() }
                    initializeTextColors(regionSampler)
                    regionSamplers[v] = regionSampler
                    regionSampler.startRegionSampler()
                }
                updateTextColorFromWallpaper()
            }
            isContentUpdatedOnce = true
            isRegionSamplersCreated = true
        }
    }

@@ -504,18 +503,16 @@ constructor(
    }

    private fun updateTextColorFromRegionSampler() {
        smartspaceViews.forEach {
            val textColor = regionSamplers.get(it)?.currentForegroundColor()
        regionSamplers.forEach { (view, region) ->
            val textColor = region.currentForegroundColor()
            if (textColor != null) {
                it.setPrimaryTextColor(textColor)
                view.setPrimaryTextColor(textColor)
            }
        }
    }

    private fun updateTextColorFromWallpaper() {
        val wallpaperManager = WallpaperManager.getInstance(context)
        if (!regionSamplingEnabled || wallpaperManager.lockScreenWallpaperExists() ||
            regionSamplers.isEmpty()) {
        if (!regionSamplingEnabled || regionSamplers.isEmpty()) {
            val wallpaperTextColor =
                    Utils.getColorAttrDefaultColor(context, R.attr.wallpaperTextColor)
            smartspaceViews.forEach { it.setPrimaryTextColor(wallpaperTextColor) }
Loading