summaryrefslogtreecommitdiff
path: root/src/com/android/customization/model/color/ColorOption.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/customization/model/color/ColorOption.java')
-rw-r--r--src/com/android/customization/model/color/ColorOption.java223
1 files changed, 223 insertions, 0 deletions
diff --git a/src/com/android/customization/model/color/ColorOption.java b/src/com/android/customization/model/color/ColorOption.java
new file mode 100644
index 00000000..c8b28c29
--- /dev/null
+++ b/src/com/android/customization/model/color/ColorOption.java
@@ -0,0 +1,223 @@
+/*
+ * 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 android.content.Context;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.customization.model.CustomizationManager;
+import com.android.customization.model.CustomizationOption;
+import com.android.customization.model.color.ColorOptionsProvider.ColorSource;
+import com.android.systemui.monet.Style;
+import com.android.wallpaper.R;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Represents a color choice for the user.
+ * This could be a preset color or those obtained from a wallpaper.
+ */
+public abstract class ColorOption implements CustomizationOption<ColorOption> {
+
+ private static final String TAG = "ColorOption";
+ private static final String EMPTY_JSON = "{}";
+ @VisibleForTesting
+ static final String TIMESTAMP_FIELD = "_applied_timestamp";
+
+ protected final Map<String, String> mPackagesByCategory;
+ protected final int[] mPreviewColorIds = {R.id.color_preview_0, R.id.color_preview_1,
+ R.id.color_preview_2, R.id.color_preview_3};
+ private final String mTitle;
+ private final boolean mIsDefault;
+ private final Style mStyle;
+ private final int mIndex;
+ private CharSequence mContentDescription;
+
+ protected ColorOption(String title, Map<String, String> overlayPackages, boolean isDefault,
+ Style style, int index) {
+ mTitle = title;
+ mIsDefault = isDefault;
+ mStyle = style;
+ mIndex = index;
+ mPackagesByCategory = Collections.unmodifiableMap(removeNullValues(overlayPackages));
+ }
+
+ @Override
+ public String getTitle() {
+ return mTitle;
+ }
+
+ @Override
+ public boolean isActive(CustomizationManager<ColorOption> manager) {
+ ColorCustomizationManager colorManager = (ColorCustomizationManager) manager;
+
+ String currentStyle = colorManager.getCurrentStyle();
+ if (TextUtils.isEmpty(currentStyle)) {
+ currentStyle = Style.TONAL_SPOT.toString();
+ }
+ boolean isCurrentStyle = TextUtils.equals(getStyle().toString(), currentStyle);
+
+ if (mIsDefault) {
+ String serializedOverlays = colorManager.getStoredOverlays();
+ return (TextUtils.isEmpty(serializedOverlays) || EMPTY_JSON.equals(serializedOverlays)
+ || colorManager.getCurrentOverlays().isEmpty() || !(serializedOverlays.contains(
+ OVERLAY_CATEGORY_SYSTEM_PALETTE) || serializedOverlays.contains(
+ OVERLAY_CATEGORY_COLOR))) && isCurrentStyle;
+ } else {
+ Map<String, String> currentOverlays = colorManager.getCurrentOverlays();
+ String currentSource = colorManager.getCurrentColorSource();
+ boolean isCurrentSource = TextUtils.isEmpty(currentSource) || getSource().equals(
+ currentSource);
+ return isCurrentSource && isCurrentStyle && mPackagesByCategory.equals(currentOverlays);
+ }
+ }
+
+ /**
+ * This is similar to #equals() but it only compares this theme's packages with the other, that
+ * is, it will return true if applying this theme has the same effect of applying the given one.
+ */
+ public boolean isEquivalent(ColorOption other) {
+ if (other == null) {
+ return false;
+ }
+ if (mIsDefault) {
+ return other.isDefault() || TextUtils.isEmpty(other.getSerializedPackages())
+ || EMPTY_JSON.equals(other.getSerializedPackages());
+ }
+ // Map#equals ensures keys and values are compared.
+ return mPackagesByCategory.equals(other.mPackagesByCategory);
+ }
+
+ /**
+ * Returns the {@link PreviewInfo} object for this ColorOption
+ */
+ public abstract PreviewInfo getPreviewInfo();
+
+ boolean isDefault() {
+ return mIsDefault;
+ }
+
+ public Map<String, String> getPackagesByCategory() {
+ return mPackagesByCategory;
+ }
+
+ public String getSerializedPackages() {
+ return getJsonPackages(false).toString();
+ }
+
+ public String getSerializedPackagesWithTimestamp() {
+ return getJsonPackages(true).toString();
+ }
+
+ /**
+ * Get a JSONObject representation of this color option, with the current values for each
+ * field, and optionally a {@link TIMESTAMP_FIELD} field.
+ * @param insertTimestamp whether to add a field with the current timestamp
+ * @return the JSONObject for this color option
+ */
+ public JSONObject getJsonPackages(boolean insertTimestamp) {
+ JSONObject json;
+ if (isDefault()) {
+ json = new JSONObject();
+ } else {
+ json = new JSONObject(mPackagesByCategory);
+ // Remove items with null values to avoid deserialization issues.
+ removeNullValues(json);
+ }
+ if (insertTimestamp) {
+ try {
+ json.put(TIMESTAMP_FIELD, System.currentTimeMillis());
+ } catch (JSONException e) {
+ Log.e(TAG, "Couldn't add timestamp to serialized themebundle");
+ }
+ }
+ return json;
+ }
+
+ private void removeNullValues(JSONObject json) {
+ Iterator<String> keys = json.keys();
+ Set<String> keysToRemove = new HashSet<>();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ if (json.isNull(key)) {
+ keysToRemove.add(key);
+ }
+ }
+ for (String key : keysToRemove) {
+ json.remove(key);
+ }
+ }
+
+ private Map<String, String> removeNullValues(Map<String, String> map) {
+ return map.entrySet()
+ .stream()
+ .filter(entry -> entry.getValue() != null)
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+ }
+
+ protected CharSequence getContentDescription(Context context) {
+ if (mContentDescription == null) {
+ CharSequence defaultName = context.getString(R.string.default_theme_title);
+ if (isDefault()) {
+ mContentDescription = defaultName;
+ } else {
+ mContentDescription = mTitle;
+ }
+ }
+ return mContentDescription;
+ }
+
+ /**
+ * @return the source of this color option
+ */
+ @ColorSource
+ public abstract String getSource();
+
+ /**
+ * @return the style of this color option
+ */
+ public Style getStyle() {
+ return mStyle;
+ }
+
+ /**
+ * @return the index of this color option
+ */
+ public int getIndex() {
+ return mIndex;
+ }
+
+ /**
+ * The preview information of {@link ColorOption}
+ */
+ public interface PreviewInfo {
+ }
+
+}