1 /* 2 * Copyright (C) 2020 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.server.display.color; 18 19 import static com.android.server.display.color.DisplayTransformManager.LEVEL_COLOR_MATRIX_REDUCE_BRIGHT_COLORS; 20 21 import android.content.Context; 22 import android.hardware.display.ColorDisplayManager; 23 import android.opengl.Matrix; 24 import android.util.Slog; 25 26 import com.android.internal.R; 27 28 import java.io.PrintWriter; 29 import java.util.Arrays; 30 31 /** 32 * Control the color transform for bright color reduction. 33 */ 34 public class ReduceBrightColorsTintController extends TintController { 35 36 private final float[] mMatrix = new float[16]; 37 private final float[] mCoefficients = new float[3]; 38 39 private int mStrength; 40 41 @Override setUp(Context context, boolean needsLinear)42 public void setUp(Context context, boolean needsLinear) { 43 final String[] coefficients = context.getResources().getStringArray( 44 needsLinear ? R.array.config_reduceBrightColorsCoefficients 45 : R.array.config_reduceBrightColorsCoefficientsNonlinear); 46 for (int i = 0; i < 3 && i < coefficients.length; i++) { 47 mCoefficients[i] = Float.parseFloat(coefficients[i]); 48 } 49 } 50 51 @Override getMatrix()52 public float[] getMatrix() { 53 return isActivated() ? Arrays.copyOf(mMatrix, mMatrix.length) 54 : ColorDisplayService.MATRIX_IDENTITY; 55 } 56 57 @Override setMatrix(int strengthLevel)58 public void setMatrix(int strengthLevel) { 59 // Clamp to valid range. 60 if (strengthLevel < 0) { 61 strengthLevel = 0; 62 } else if (strengthLevel > 100) { 63 strengthLevel = 100; 64 } 65 Slog.d(ColorDisplayService.TAG, "Setting bright color reduction level: " + strengthLevel); 66 mStrength = strengthLevel; 67 68 Matrix.setIdentityM(mMatrix, 0); 69 70 // All three (r,g,b) components are equal and calculated with the same formula. 71 final float componentValue = computeComponentValue(strengthLevel); 72 mMatrix[0] = componentValue; 73 mMatrix[5] = componentValue; 74 mMatrix[10] = componentValue; 75 } 76 clamp(float value)77 private float clamp(float value) { 78 if (value > 1f) { 79 return 1f; 80 } else if (value < 0f) { 81 return 0f; 82 } 83 return value; 84 } 85 86 @Override dump(PrintWriter pw)87 public void dump(PrintWriter pw) { 88 pw.println(" mStrength = " + mStrength); 89 } 90 91 @Override getLevel()92 public int getLevel() { 93 return LEVEL_COLOR_MATRIX_REDUCE_BRIGHT_COLORS; 94 } 95 96 @Override isAvailable(Context context)97 public boolean isAvailable(Context context) { 98 return ColorDisplayManager.isColorTransformAccelerated(context); 99 } 100 101 @Override setActivated(Boolean isActivated)102 public void setActivated(Boolean isActivated) { 103 super.setActivated(isActivated); 104 Slog.i(ColorDisplayService.TAG, (isActivated != null && isActivated) 105 ? "Turning on reduce bright colors" : "Turning off reduce bright colors"); 106 } 107 getStrength()108 public int getStrength() { 109 return mStrength; 110 } 111 112 /** Returns the offset factor at Ymax. */ getOffsetFactor()113 public float getOffsetFactor() { 114 // Strength terms drop out as strength --> 1, leaving the coefficients. 115 return mCoefficients[0] + mCoefficients[1] + mCoefficients[2]; 116 } 117 118 /** 119 * Returns the effective brightness (in nits), which has been adjusted to account for the effect 120 * of the bright color reduction. 121 */ getAdjustedBrightness(float nits)122 public float getAdjustedBrightness(float nits) { 123 return computeComponentValue(mStrength) * nits; 124 } 125 computeComponentValue(int strengthLevel)126 private float computeComponentValue(int strengthLevel) { 127 final float percentageStrength = strengthLevel / 100f; 128 final float squaredPercentageStrength = percentageStrength * percentageStrength; 129 return clamp( 130 squaredPercentageStrength * mCoefficients[0] + percentageStrength * mCoefficients[1] 131 + mCoefficients[2]); 132 } 133 } 134