1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.providers.media.photopicker; 18 19 import android.app.Application; 20 import android.content.res.Configuration; 21 import android.graphics.Color; 22 import android.provider.MediaStore; 23 import android.util.Log; 24 25 /** 26 * This class holds the parameters and the utility methods for setting a custom picker accent 27 * color. 28 * Only valid input color codes with luminance greater than 0.6 will be set on the major picker 29 * components. All other colors are set based on Material3 baseline theme for both the dark and 30 * light theme. 31 */ 32 public class PickerAccentColorParameters { 33 public static final String TAG = "PhotoPicker"; 34 private int mPickerAccentColor = -1; 35 private boolean mIsNightModeEnabled = false; 36 private float mAccentColorLuminance = 0; 37 PickerAccentColorParameters()38 public PickerAccentColorParameters() {} 39 PickerAccentColorParameters(int color, Application application)40 public PickerAccentColorParameters(int color, Application application) { 41 mPickerAccentColor = color; 42 // Needs to be set here since the PickerAccentColorParameters object gets initialised again 43 // after color validity check therefore the value if set then will be lost. 44 mAccentColorLuminance = Color.luminance(color); 45 setNightModeFlag(application); 46 } 47 setNightModeFlag(Application application)48 private void setNightModeFlag(Application application) { 49 if (application == null) { 50 return; 51 } 52 int nightModeFlag = 53 application.getApplicationContext().getResources().getConfiguration().uiMode 54 & Configuration.UI_MODE_NIGHT_MASK; 55 mIsNightModeEnabled = nightModeFlag == Configuration.UI_MODE_NIGHT_YES; 56 } 57 58 /** 59 * Return dark or light color variant based on whether night mode is enabled or not. 60 */ getThemeBasedColor(String lightThemeVariant, String darkThemeVariant)61 public int getThemeBasedColor(String lightThemeVariant, String darkThemeVariant) { 62 return mIsNightModeEnabled 63 ? Color.parseColor(darkThemeVariant) : Color.parseColor(lightThemeVariant); 64 } 65 66 /** 67 * Returns whether the accent color is set or not 68 */ isCustomPickerColorSet()69 public boolean isCustomPickerColorSet() { 70 return mPickerAccentColor != -1; 71 } 72 73 /** 74 * Checks whether the input color to be used as the picker accent color is valid or not and 75 * returns the int color value if it is valid after dropping the alpha component 76 * or -1 otherwise. 77 */ checkColorValidityAndGetColor(long color)78 public static int checkColorValidityAndGetColor(long color) { 79 // Gives us the formatted color string where the mask gives us the color in the RRGGBB 80 // format and the %06X gives zero-padded hex (6 characters long) 81 String hexColor = String.format("#%06X", (0xFFFFFF & color)); 82 int inputColor = Color.parseColor(hexColor); 83 if (!isColorFeasibleForBothBackgrounds(inputColor)) { 84 // Fall back to the android theme 85 Log.w(TAG, "Value set for " + MediaStore.EXTRA_PICK_IMAGES_ACCENT_COLOR 86 + " is not within the permitted brightness range. Please refer to the " 87 + "docs for more details. Setting android theme on the picker."); 88 return -1; 89 } 90 return inputColor; 91 } 92 isColorFeasibleForBothBackgrounds(int color)93 private static boolean isColorFeasibleForBothBackgrounds(int color) { 94 // Returns the luminance(can also be thought of brightness) 95 // Returned value ranges from 0(black) to 1(white) 96 // Colors within this range will work both on light and dark background. Range set by 97 // testing with different colors. 98 float luminance = Color.luminance(color); 99 return luminance >= 0.05 && luminance < 0.9; 100 } 101 102 /** 103 * Returns whether the accent color is bright or not based on the luminance of the color. 104 * Lower luminance bound set by testing with different colors. 105 */ isAccentColorBright()106 public boolean isAccentColorBright() { 107 return mAccentColorLuminance >= 0.6; 108 } 109 110 /** 111 * Returns the accent color to be set. We can ignore the alpha component when using the color 112 * to be set on various picker components. Also, all of these components require integer color 113 * value to set their respective colors. 114 */ getPickerAccentColor()115 public int getPickerAccentColor() { 116 return mPickerAccentColor; 117 } 118 } 119