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

Commit a9dc99bf authored by Catherine Liang's avatar Catherine Liang
Browse files

Pre-revamped UI color manager & provider cleanup

As part of the revamped UI flag removal process, clean up
ColorCustomizationManager, ColorProvider, and color options that are no
longer in use--ColorBundle and ColorSeedOption. Also updated and fixed
previously failing and ignored tests.

Bug: 262780002
Bug: 222433744
Bug: 260925899
Test: fixed and updated previously ignored ColorCustomizationManagerTest
& ColorOptionTest, tests now pass

Change-Id: Ia1892b4e1e0f48a1297c45fb1430f4e6562c6aad
parent fd6c1edb
Loading
Loading
Loading
Loading

res/layout/color_option.xml

deleted100644 → 0
+0 −103
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?><!--
     Copyright (C) 2022 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.
-->
<!-- Enclosing layout must be match_parent so that we can center content within -->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:clipChildren="false"
    android:gravity="center"
    android:padding="@dimen/option_tile_grid_tile_padding_min">

    <!--
        This displays the background. It is dynamically sized, constrained remain square and
        have a maximum size, and be centered within its parent.
     -->
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_gravity="center"
        android:background="@drawable/option_border_color"
        android:gravity="center"
        android:padding="@dimen/option_tile_grid_icon_padding_min"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="1:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_max="@dimen/option_tile_width">

        <!-- This is the color wheel itself, constrained to a maximum size and centered -->
        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/option_tile"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_gravity="center"
            android:gravity="center"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHeight_max="@dimen/component_color_chip_small_diameter_default"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintWidth_max="@dimen/component_color_chip_small_diameter_default">

            <ImageView
                android:id="@+id/color_preview_0"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:adjustViewBounds="true"
                android:src="@drawable/color_chip_seed_filled0"
                app:layout_constraintHeight_percent=".50"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintWidth_percent=".50" />

            <ImageView
                android:id="@+id/color_preview_1"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:adjustViewBounds="true"
                android:src="@drawable/color_chip_seed_filled2"
                app:layout_constraintHeight_percent=".50"
                app:layout_constraintLeft_toRightOf="@id/color_preview_0"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintWidth_percent=".50" />

            <ImageView
                android:id="@+id/color_preview_2"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:adjustViewBounds="true"
                android:src="@drawable/color_chip_seed_filled1"
                app:layout_constraintHeight_percent=".50"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@id/color_preview_0"
                app:layout_constraintWidth_percent=".50" />

            <ImageView
                android:id="@+id/color_preview_3"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:adjustViewBounds="true"
                android:src="@drawable/color_chip_seed_filled3"
                app:layout_constraintHeight_percent=".50"
                app:layout_constraintLeft_toRightOf="@id/color_preview_2"
                app:layout_constraintTop_toBottomOf="@id/color_preview_1"
                app:layout_constraintWidth_percent=".50" />
        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

res/layout/color_options_view.xml

deleted100644 → 0
+0 −27
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
     Copyright (C) 2022 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.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/color_option_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:orientation="horizontal" />
</FrameLayout>

res/layout/color_pages_view.xml

deleted100644 → 0
+0 −33
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
     Copyright (C) 2022 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/color_page_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <com.android.wallpaper.widget.PageIndicator
        android:id="@+id/color_page_indicator"
        android:layout_marginTop="@dimen/color_page_indicator_margin_top"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"
        android:layout_gravity="center"/>
</LinearLayout>
+0 −306
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.customization.model.color;

import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.view.View;
import android.widget.ImageView;

import androidx.annotation.ColorInt;
import androidx.annotation.Dimension;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;

import com.android.customization.model.ResourceConstants;
import com.android.systemui.monet.Style;
import com.android.wallpaper.R;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * Represents a preset color available for the user to chose as their theming option.
 */
public class ColorBundle extends ColorOption {

    private final PreviewInfo mPreviewInfo;

    @VisibleForTesting ColorBundle(String title,
            Map<String, String> overlayPackages, boolean isDefault, Style style, int index,
            PreviewInfo previewInfo) {
        super(title, overlayPackages, isDefault, style, index);
        mPreviewInfo = previewInfo;
    }

    @Override
    public void bindThumbnailTile(View view) {
        Resources res = view.getContext().getResources();
        int primaryColor = mPreviewInfo.resolvePrimaryColor(res);
        int secondaryColor = mPreviewInfo.resolveSecondaryColor(res);

        for (int i = 0; i < mPreviewColorIds.length; i++) {
            ImageView colorPreviewImageView = view.findViewById(mPreviewColorIds[i]);
            int color = i % 2 == 0 ? primaryColor : secondaryColor;
            colorPreviewImageView.getDrawable().setColorFilter(color, PorterDuff.Mode.SRC);
        }
        view.setContentDescription(getContentDescription(view.getContext()));
    }

    @Override
    public PreviewInfo getPreviewInfo() {
        return mPreviewInfo;
    }

    @Override
    public int getLayoutResId() {
        return R.layout.color_option;
    }

    @Override
    public String getSource() {
        return ColorOptionsProvider.COLOR_SOURCE_PRESET;
    }

    /**
     * The preview information of {@link ColorBundle}
     */
    public static class PreviewInfo implements ColorOption.PreviewInfo {
        @ColorInt
        public final int secondaryColorLight;
        @ColorInt public final int secondaryColorDark;
        // Monet system palette and accent colors
        @ColorInt public final int primaryColorLight;
        @ColorInt public final int primaryColorDark;
        @Dimension
        public final int bottomSheetCornerRadius;

        @ColorInt private int mOverrideSecondaryColorLight = Color.TRANSPARENT;
        @ColorInt private int mOverrideSecondaryColorDark = Color.TRANSPARENT;
        @ColorInt private int mOverridePrimaryColorLight = Color.TRANSPARENT;
        @ColorInt private int mOverridePrimaryColorDark = Color.TRANSPARENT;

        private PreviewInfo(
                int secondaryColorLight, int secondaryColorDark, int colorSystemPaletteLight,
                int primaryColorDark, @Dimension int cornerRadius) {
            this.secondaryColorLight = secondaryColorLight;
            this.secondaryColorDark = secondaryColorDark;
            this.primaryColorLight = colorSystemPaletteLight;
            this.primaryColorDark = primaryColorDark;
            this.bottomSheetCornerRadius = cornerRadius;
        }

        /**
         * Returns the accent color to be applied corresponding with the current configuration's
         * UI mode.
         * @return one of {@link #secondaryColorDark} or {@link #secondaryColorLight}
         */
        @ColorInt
        public int resolveSecondaryColor(Resources res) {
            boolean night = (res.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK)
                    == Configuration.UI_MODE_NIGHT_YES;
            if (mOverrideSecondaryColorDark != Color.TRANSPARENT
                    || mOverrideSecondaryColorLight != Color.TRANSPARENT) {
                return night ? mOverrideSecondaryColorDark : mOverrideSecondaryColorLight;
            }
            return night ? secondaryColorDark : secondaryColorLight;
        }

        /**
         * Returns the palette (main) color to be applied corresponding with the current
         * configuration's UI mode.
         * @return one of {@link #secondaryColorDark} or {@link #secondaryColorLight}
         */
        @ColorInt
        public int resolvePrimaryColor(Resources res) {
            boolean night = (res.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK)
                    == Configuration.UI_MODE_NIGHT_YES;
            if (mOverridePrimaryColorDark != Color.TRANSPARENT
                    || mOverridePrimaryColorLight != Color.TRANSPARENT) {
                return night ? mOverridePrimaryColorDark : mOverridePrimaryColorLight;
            }
            return night ? primaryColorDark
                    : primaryColorLight;
        }

        /**
         * Sets accent colors to override the ones in this bundle
         */
        public void setOverrideAccentColors(int overrideColorAccentLight,
                int overrideColorAccentDark) {
            mOverrideSecondaryColorLight = overrideColorAccentLight;
            mOverrideSecondaryColorDark = overrideColorAccentDark;
        }

        /**
         * Sets palette colors to override the ones in this bundle
         */
        public void setOverridePaletteColors(int overrideColorPaletteLight,
                int overrideColorPaletteDark) {
            mOverridePrimaryColorLight = overrideColorPaletteLight;
            mOverridePrimaryColorDark = overrideColorPaletteDark;
        }
    }

    /**
     * The builder of ColorBundle
     */
    public static class Builder {
        protected String mTitle;
        @ColorInt private int mSecondaryColorLight = Color.TRANSPARENT;
        @ColorInt private int mSecondaryColorDark = Color.TRANSPARENT;
        // System and Monet colors
        @ColorInt private int mPrimaryColorLight = Color.TRANSPARENT;
        @ColorInt private int mPrimaryColorDark = Color.TRANSPARENT;
        private boolean mIsDefault;
        private Style mStyle = Style.TONAL_SPOT;
        private int mIndex;
        protected Map<String, String> mPackages = new HashMap<>();

        /**
         * Builds the ColorBundle
         * @param context {@link Context}
         * @return new {@link ColorBundle} object
         */
        public ColorBundle build(Context context) {
            if (mTitle == null) {
                mTitle = context.getString(R.string.adaptive_color_title);
            }
            return new ColorBundle(mTitle, mPackages, mIsDefault, mStyle, mIndex,
                    createPreviewInfo(context));
        }

        /**
         * Creates preview information
         * @param context the {@link Context}
         * @return the {@link PreviewInfo} object
         */
        public PreviewInfo createPreviewInfo(@NonNull Context context) {
            Resources system = context.getResources().getSystem();
            return new PreviewInfo(mSecondaryColorLight,
                    mSecondaryColorDark, mPrimaryColorLight, mPrimaryColorDark,
                    system.getDimensionPixelOffset(
                            system.getIdentifier(ResourceConstants.CONFIG_CORNERRADIUS, "dimen",
                                    ResourceConstants.ANDROID_PACKAGE)));
        }

        public Map<String, String> getPackages() {
            return Collections.unmodifiableMap(mPackages);
        }

        /**
         * Gets title of this {@link ColorBundle} object
         * @return title string
         */
        public String getTitle() {
            return mTitle;
        }

        /**
         * Sets title of bundle
         * @param title specified title
         * @return this of {@link Builder}
         */
        public Builder setTitle(String title) {
            mTitle = title;
            return this;
        }

        /**
         * Sets color accent (light)
         * @param colorSecondaryLight color accent light in {@link ColorInt}
         * @return this of {@link Builder}
         */
        public Builder setColorSecondaryLight(@ColorInt int colorSecondaryLight) {
            mSecondaryColorLight = colorSecondaryLight;
            return this;
        }

        /**
         * Sets color accent (dark)
         * @param colorSecondaryDark color accent dark in {@link ColorInt}
         * @return this of {@link Builder}
         */
        public Builder setColorSecondaryDark(@ColorInt int colorSecondaryDark) {
            mSecondaryColorDark = colorSecondaryDark;
            return this;
        }

        /**
         * Sets color system palette (light)
         * @param colorPrimaryLight color system palette in {@link ColorInt}
         * @return this of {@link Builder}
         */
        public Builder setColorPrimaryLight(@ColorInt int colorPrimaryLight) {
            mPrimaryColorLight = colorPrimaryLight;
            return this;
        }

        /**
         * Sets color system palette (dark)
         * @param colorPrimaryDark color system palette in {@link ColorInt}
         * @return this of {@link Builder}
         */
        public Builder setColorPrimaryDark(@ColorInt int colorPrimaryDark) {
            mPrimaryColorDark = colorPrimaryDark;
            return this;
        }

        /**
         * Sets overlay package for bundle
         * @param category the category of bundle
         * @param packageName tha name of package in the category
         * @return this of {@link Builder}
         */
        public Builder addOverlayPackage(String category, String packageName) {
            mPackages.put(category, packageName);
            return this;
        }

        /**
         * Sets the style of this color seed
         * @param style color style of {@link Style}
         * @return this of {@link Builder}
         */
        public Builder setStyle(Style style) {
            mStyle = style;
            return this;
        }

        /**
         * Sets color option index of bundle
         * @param index color option index
         * @return this of {@link Builder}
         */
        public Builder setIndex(int index) {
            mIndex = index;
            return this;
        }

        /**
         * Sets as default bundle
         * @return this of {@link Builder}
         */
        public Builder asDefault() {
            mIsDefault = true;
            return this;
        }
    }
}
+0 −77
Original line number Diff line number Diff line
/**
 * Copyright (C) 2022 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.customization.model.color;

import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_COLOR;
import static com.android.customization.model.ResourceConstants.OVERLAY_CATEGORY_SYSTEM_PALETTE;
import static com.android.customization.model.color.ColorUtils.toColorString;

import android.content.Context;
import android.content.pm.PackageManager;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.ColorInt;

import com.android.systemui.monet.ColorScheme;
import com.android.systemui.monet.Style;

/**
 * Utility class to read all the details of a color bundle for previewing it
 * (eg, actual color values)
 */
class ColorBundlePreviewExtractor {

    private static final String TAG = "ColorBundlePreviewExtractor";

    private final PackageManager mPackageManager;

    ColorBundlePreviewExtractor(Context context) {
        mPackageManager = context.getPackageManager();
    }

    void addSecondaryColor(ColorBundle.Builder builder, @ColorInt int color) {
        ColorScheme darkColorScheme = new ColorScheme(color, true);
        ColorScheme lightColorScheme = new ColorScheme(color, false);
        int lightSecondary = lightColorScheme.getAccentColor();
        int darkSecondary = darkColorScheme.getAccentColor();
        builder.addOverlayPackage(OVERLAY_CATEGORY_COLOR, toColorString(color))
                .setColorSecondaryLight(lightSecondary)
                .setColorSecondaryDark(darkSecondary);
    }

    void addPrimaryColor(ColorBundle.Builder builder, @ColorInt int color) {
        ColorScheme darkColorScheme = new ColorScheme(color, true);
        ColorScheme lightColorScheme = new ColorScheme(color, false);
        int lightPrimary = lightColorScheme.getAccentColor();
        int darkPrimary = darkColorScheme.getAccentColor();
        builder.addOverlayPackage(OVERLAY_CATEGORY_SYSTEM_PALETTE, toColorString(color))
                .setColorPrimaryLight(lightPrimary)
                .setColorPrimaryDark(darkPrimary);
    }

    void addColorStyle(ColorBundle.Builder builder, String styleName) {
        Style s = Style.TONAL_SPOT;
        if (!TextUtils.isEmpty(styleName)) {
            try {
                s = Style.valueOf(styleName);
            } catch (IllegalArgumentException e) {
                Log.i(TAG, "Unknown style : " + styleName + ". Will default to TONAL_SPOT.");
            }
        }
        builder.setStyle(s);
    }
}
Loading