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

Commit 74c53a9d authored by James O'Leary's avatar James O'Leary Committed by Automerger Merge Worker
Browse files

Merge changes from topic "colorSchemeChanges" into tm-dev am: e320ce44

parents e79630c4 e320ce44
Loading
Loading
Loading
Loading
+42 −17
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import android.app.WallpaperColors
import android.graphics.Color
import com.android.internal.graphics.ColorUtils
import com.android.internal.graphics.cam.Cam
import com.android.internal.graphics.cam.CamUtils.lstarFromInt
import kotlin.math.absoluteValue
import kotlin.math.max
import kotlin.math.roundToInt
@@ -50,7 +49,7 @@ internal interface Hue {
            val previousHue = hueAndRotations[previousIndex].first
            if (ColorScheme.angleIsBetween(sourceHue, thisHue, previousHue)) {
                return ColorScheme.wrapDegreesDouble(sourceHue.toDouble() +
                        hueAndRotations[previousIndex].first)
                        hueAndRotations[previousIndex].second)
            }
        }

@@ -143,12 +142,24 @@ internal class ChromaMinimum(val chroma: Double) : Chroma {
    }
}

internal class ChromaMultiple(val multiple: Double) : Chroma {
    override fun get(sourceColor: Cam): Double {
        return sourceColor.chroma * multiple
    }
}

internal class ChromaConstant(val chroma: Double) : Chroma {
    override fun get(sourceColor: Cam): Double {
        return chroma
    }
}

internal class ChromaSource : Chroma {
    override fun get(sourceColor: Cam): Double {
        return sourceColor.chroma.toDouble()
    }
}

internal class TonalSpec(val hue: Hue = HueSource(), val chroma: Chroma) {
    fun shades(sourceColor: Cam): List<Int> {
        val hue = hue.get(sourceColor)
@@ -184,8 +195,8 @@ enum class Style(internal val coreSpec: CoreSpec) {
            a1 = TonalSpec(HueSource(), ChromaMinimum(48.0)),
            a2 = TonalSpec(HueVibrantSecondary(), ChromaConstant(24.0)),
            a3 = TonalSpec(HueVibrantTertiary(), ChromaConstant(32.0)),
            n1 = TonalSpec(HueSource(), ChromaConstant(10.0)),
            n2 = TonalSpec(HueSource(), ChromaConstant(12.0))
            n1 = TonalSpec(HueSource(), ChromaConstant(12.0)),
            n2 = TonalSpec(HueSource(), ChromaConstant(14.0))
    )),
    EXPRESSIVE(CoreSpec(
            a1 = TonalSpec(HueAdd(240.0), ChromaConstant(40.0)),
@@ -208,6 +219,13 @@ enum class Style(internal val coreSpec: CoreSpec) {
            n1 = TonalSpec(HueSource(), ChromaConstant(10.0)),
            n2 = TonalSpec(HueSource(), ChromaConstant(16.0))
    )),
    CONTENT(CoreSpec(
            a1 = TonalSpec(HueSource(), ChromaSource()),
            a2 = TonalSpec(HueSource(), ChromaMultiple(0.33)),
            a3 = TonalSpec(HueSource(), ChromaMultiple(0.66)),
            n1 = TonalSpec(HueSource(), ChromaMultiple(0.0833)),
            n2 = TonalSpec(HueSource(), ChromaMultiple(0.1666))
    )),
}

class ColorScheme(
@@ -231,7 +249,7 @@ class ColorScheme(
        darkTheme: Boolean,
        style: Style = Style.TONAL_SPOT
    ):
            this(getSeedColor(wallpaperColors), darkTheme, style)
            this(getSeedColor(wallpaperColors, style != Style.CONTENT), darkTheme, style)

    val allAccentColors: List<Int>
        get() {
@@ -260,7 +278,7 @@ class ColorScheme(
        val proposedSeedCam = Cam.fromInt(seed)
        val seedArgb = if (seed == Color.TRANSPARENT) {
            GOOGLE_BLUE
        } else if (proposedSeedCam.chroma < 5) {
        } else if (style != Style.CONTENT && proposedSeedCam.chroma < 5) {
            GOOGLE_BLUE
        } else {
            seed
@@ -289,22 +307,26 @@ class ColorScheme(
         * Identifies a color to create a color scheme from.
         *
         * @param wallpaperColors Colors extracted from an image via quantization.
         * @param filter If false, allow colors that have low chroma, creating grayscale themes.
         * @return ARGB int representing the color
         */
        @JvmStatic
        @JvmOverloads
        @ColorInt
        fun getSeedColor(wallpaperColors: WallpaperColors): Int {
            return getSeedColors(wallpaperColors).first()
        fun getSeedColor(wallpaperColors: WallpaperColors, filter: Boolean = true): Int {
            return getSeedColors(wallpaperColors, filter).first()
        }

        /**
         * Filters and ranks colors from WallpaperColors.
         *
         * @param wallpaperColors Colors extracted from an image via quantization.
         * @param filter If false, allow colors that have low chroma, creating grayscale themes.
         * @return List of ARGB ints, ordered from highest scoring to lowest.
         */
        @JvmStatic
        fun getSeedColors(wallpaperColors: WallpaperColors): List<Int> {
        @JvmOverloads
        fun getSeedColors(wallpaperColors: WallpaperColors, filter: Boolean = true): List<Int> {
            val totalPopulation = wallpaperColors.allColors.values.reduce { a, b -> a + b }
                    .toDouble()
            val totalPopulationMeaningless = (totalPopulation == 0.0)
@@ -317,9 +339,12 @@ class ColorScheme(
                val distinctColors = wallpaperColors.mainColors.map {
                    it.toArgb()
                }.distinct().filter {
                    if (!filter) {
                        true
                    } else {
                        Cam.fromInt(it).chroma >= MIN_CHROMA
                    }
                }.toList()

                if (distinctColors.isEmpty()) {
                    return listOf(GOOGLE_BLUE)
                }
@@ -332,7 +357,7 @@ class ColorScheme(
            val intToCam = wallpaperColors.allColors.mapValues { Cam.fromInt(it.key) }

            // Get an array with 360 slots. A slot contains the percentage of colors with that hue.
            val hueProportions = huePopulations(intToCam, intToProportion)
            val hueProportions = huePopulations(intToCam, intToProportion, filter)
            // Map each color to the percentage of the image with its hue.
            val intToHueProportion = wallpaperColors.allColors.mapValues {
                val cam = intToCam[it.key]!!
@@ -346,13 +371,12 @@ class ColorScheme(
            // Remove any inappropriate seed colors. For example, low chroma colors look grayscale
            // raising their chroma will turn them to a much louder color that may not have been
            // in the image.
            val filteredIntToCam = intToCam.filter {
            val filteredIntToCam = if (!filter) intToCam else (intToCam.filter {
                val cam = it.value
                val lstar = lstarFromInt(it.key)
                val proportion = intToHueProportion[it.key]!!
                cam.chroma >= MIN_CHROMA &&
                        (totalPopulationMeaningless || proportion > 0.01)
            }
            })
            // Sort the colors by score, from high to low.
            val intToScoreIntermediate = filteredIntToCam.mapValues {
                score(it.value, intToHueProportion[it.key]!!)
@@ -444,7 +468,8 @@ class ColorScheme(

        private fun huePopulations(
            camByColor: Map<Int, Cam>,
            populationByColor: Map<Int, Double>
            populationByColor: Map<Int, Double>,
            filter: Boolean = true
        ): List<Double> {
            val huePopulation = List(size = 360, init = { 0.0 }).toMutableList()

@@ -452,7 +477,7 @@ class ColorScheme(
                val population = populationByColor[entry.key]!!
                val cam = camByColor[entry.key]!!
                val hue = cam.hue.roundToInt() % 360
                if (cam.chroma <= MIN_CHROMA) {
                if (filter && cam.chroma <= MIN_CHROMA) {
                    continue
                }
                huePopulation[hue] = huePopulation[hue] + population
+4 −2
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.media.dialog.MediaOutputDialogFactory;
import com.android.systemui.monet.ColorScheme;
import com.android.systemui.monet.Style;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.shared.system.SysUiStatsLog;
@@ -627,7 +628,7 @@ public class MediaControlPanel {
            if (artworkIcon != null) {
                WallpaperColors wallpaperColors = WallpaperColors
                        .fromBitmap(artworkIcon.getBitmap());
                mutableColorScheme = new ColorScheme(wallpaperColors, true);
                mutableColorScheme = new ColorScheme(wallpaperColors, true, Style.CONTENT);
                artwork = getScaledBackground(artworkIcon, width, height);
                isArtworkBound = true;
            } else {
@@ -637,7 +638,8 @@ public class MediaControlPanel {
                try {
                    Drawable icon = mContext.getPackageManager()
                            .getApplicationIcon(data.getPackageName());
                    mutableColorScheme = new ColorScheme(WallpaperColors.fromDrawable(icon), true);
                    mutableColorScheme = new ColorScheme(WallpaperColors.fromDrawable(icon), true,
                            Style.CONTENT);
                } catch (PackageManager.NameNotFoundException e) {
                    Log.w(TAG, "Cannot find icon for package " + data.getPackageName(), e);
                }
+9 −0
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ import org.json.JSONException;
import org.json.JSONObject;

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
@@ -639,6 +640,11 @@ public class ThemeOverlayController extends CoreStartable implements Dumpable {
    }

    private Style fetchThemeStyleFromSetting() {
        // Allow-list of Style objects that can be created from a setting string, i.e. can be
        // used as a system-wide theme.
        // - Content intentionally excluded, intended for media player, not system-wide
        List<Style> validStyles = Arrays.asList(Style.EXPRESSIVE, Style.SPRITZ, Style.TONAL_SPOT,
                Style.FRUIT_SALAD, Style.RAINBOW, Style.VIBRANT);
        Style style = mThemeStyle;
        final String overlayPackageJson = mSecureSettings.getStringForUser(
                Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
@@ -648,6 +654,9 @@ public class ThemeOverlayController extends CoreStartable implements Dumpable {
                JSONObject object = new JSONObject(overlayPackageJson);
                style = Style.valueOf(
                        object.getString(ThemeOverlayApplier.OVERLAY_CATEGORY_THEME_STYLE));
                if (!validStyles.contains(style)) {
                    style = Style.TONAL_SPOT;
                }
            } catch (JSONException | IllegalArgumentException e) {
                Log.i(TAG, "Failed to parse THEME_CUSTOMIZATION_OVERLAY_PACKAGES.", e);
                style = Style.TONAL_SPOT;
+1 −1
Original line number Diff line number Diff line
@@ -133,7 +133,7 @@ public class ColorSchemeTest extends SysuiTestCase {
                Style.VIBRANT /* style */);
        int neutralMid = colorScheme.getNeutral1().get(colorScheme.getNeutral1().size() / 2);
        Cam cam = Cam.fromInt(neutralMid);
        Assert.assertTrue("chroma was " + cam.getChroma(), Math.floor(cam.getChroma()) <= 10.0);
        Assert.assertTrue("chroma was " + cam.getChroma(), Math.floor(cam.getChroma()) <= 12.0);
    }

    @Test
+5 −1
Original line number Diff line number Diff line
@@ -74,6 +74,8 @@ import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;

@@ -345,7 +347,9 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
    @Test
    public void onSettingChanged_honorThemeStyle() {
        when(mDeviceProvisionedController.isUserSetup(anyInt())).thenReturn(true);
        for (Style style : Style.values()) {
        List<Style> validStyles = Arrays.asList(Style.EXPRESSIVE, Style.SPRITZ, Style.TONAL_SPOT,
                Style.FRUIT_SALAD, Style.RAINBOW, Style.VIBRANT);
        for (Style style : validStyles) {
            reset(mSecureSettings);

            String jsonString = "{\"android.theme.customization.system_palette\":\"A16B00\","