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

Commit 77c206e3 authored by Florence Yang's avatar Florence Yang Committed by Android (Google) Code Review
Browse files

Merge "LS Wallpaper Sampling for LS Smartspace" into udc-dev

parents f91a331f aad58839
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