1 /* 2 * Copyright (C) 2016 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; 18 19 import android.util.Slog; 20 21 import java.io.PrintWriter; 22 import java.util.Arrays; 23 24 /** 25 * A helper class for handling access to illuminance hysteresis level values. 26 */ 27 public class HysteresisLevels { 28 private static final String TAG = "HysteresisLevels"; 29 30 private static final boolean DEBUG = false; 31 32 private final float[] mBrighteningThresholdsPercentages; 33 private final float[] mDarkeningThresholdsPercentages; 34 private final float[] mBrighteningThresholdLevels; 35 private final float[] mDarkeningThresholdLevels; 36 private final float mMinDarkening; 37 private final float mMinBrightening; 38 39 /** 40 * Creates a {@code HysteresisLevels} object with the given equal-length 41 * float arrays. 42 * @param brighteningThresholdsPercentages 0-100 of thresholds 43 * @param darkeningThresholdsPercentages 0-100 of thresholds 44 * @param brighteningThresholdLevels float array of brightness values in the relevant units 45 * @param darkeningThresholdLevels float array of brightness values in the relevant units 46 * @param minBrighteningThreshold the minimum value for which the brightening value needs to 47 * return. 48 * @param minDarkeningThreshold the minimum value for which the darkening value needs to return. 49 */ HysteresisLevels(float[] brighteningThresholdsPercentages, float[] darkeningThresholdsPercentages, float[] brighteningThresholdLevels, float[] darkeningThresholdLevels, float minDarkeningThreshold, float minBrighteningThreshold)50 HysteresisLevels(float[] brighteningThresholdsPercentages, 51 float[] darkeningThresholdsPercentages, 52 float[] brighteningThresholdLevels, float[] darkeningThresholdLevels, 53 float minDarkeningThreshold, float minBrighteningThreshold) { 54 if (brighteningThresholdsPercentages.length != brighteningThresholdLevels.length 55 || darkeningThresholdsPercentages.length != darkeningThresholdLevels.length) { 56 throw new IllegalArgumentException("Mismatch between hysteresis array lengths."); 57 } 58 mBrighteningThresholdsPercentages = 59 setArrayFormat(brighteningThresholdsPercentages, 100.0f); 60 mDarkeningThresholdsPercentages = 61 setArrayFormat(darkeningThresholdsPercentages, 100.0f); 62 mBrighteningThresholdLevels = setArrayFormat(brighteningThresholdLevels, 1.0f); 63 mDarkeningThresholdLevels = setArrayFormat(darkeningThresholdLevels, 1.0f); 64 mMinDarkening = minDarkeningThreshold; 65 mMinBrightening = minBrighteningThreshold; 66 } 67 68 /** 69 * Return the brightening hysteresis threshold for the given value level. 70 */ getBrighteningThreshold(float value)71 public float getBrighteningThreshold(float value) { 72 final float brightConstant = getReferenceLevel(value, 73 mBrighteningThresholdLevels, mBrighteningThresholdsPercentages); 74 75 float brightThreshold = value * (1.0f + brightConstant); 76 if (DEBUG) { 77 Slog.d(TAG, "bright hysteresis constant=" + brightConstant + ", threshold=" 78 + brightThreshold + ", value=" + value); 79 } 80 81 brightThreshold = Math.max(brightThreshold, value + mMinBrightening); 82 return brightThreshold; 83 } 84 85 /** 86 * Return the darkening hysteresis threshold for the given value level. 87 */ getDarkeningThreshold(float value)88 public float getDarkeningThreshold(float value) { 89 final float darkConstant = getReferenceLevel(value, 90 mDarkeningThresholdLevels, mDarkeningThresholdsPercentages); 91 float darkThreshold = value * (1.0f - darkConstant); 92 if (DEBUG) { 93 Slog.d(TAG, "dark hysteresis constant=: " + darkConstant + ", threshold=" 94 + darkThreshold + ", value=" + value); 95 } 96 darkThreshold = Math.min(darkThreshold, value - mMinDarkening); 97 return Math.max(darkThreshold, 0.0f); 98 } 99 100 /** 101 * Return the hysteresis constant for the closest threshold value from the given array. 102 */ getReferenceLevel(float value, float[] thresholdLevels, float[] thresholdPercentages)103 private float getReferenceLevel(float value, float[] thresholdLevels, 104 float[] thresholdPercentages) { 105 if (thresholdLevels == null || thresholdLevels.length == 0 || value < thresholdLevels[0]) { 106 return 0.0f; 107 } 108 int index = 0; 109 while (index < thresholdLevels.length - 1 && value >= thresholdLevels[index + 1]) { 110 index++; 111 } 112 return thresholdPercentages[index]; 113 } 114 115 /** 116 * Return a float array where each i-th element equals {@code configArray[i]/divideFactor}. 117 */ setArrayFormat(float[] configArray, float divideFactor)118 private float[] setArrayFormat(float[] configArray, float divideFactor) { 119 float[] levelArray = new float[configArray.length]; 120 for (int index = 0; levelArray.length > index; ++index) { 121 levelArray[index] = configArray[index] / divideFactor; 122 } 123 return levelArray; 124 } 125 126 dump(PrintWriter pw)127 void dump(PrintWriter pw) { 128 pw.println("HysteresisLevels"); 129 pw.println(" mBrighteningThresholdLevels=" + Arrays.toString(mBrighteningThresholdLevels)); 130 pw.println(" mBrighteningThresholdsPercentages=" 131 + Arrays.toString(mBrighteningThresholdsPercentages)); 132 pw.println(" mMinBrightening=" + mMinBrightening); 133 pw.println(" mDarkeningThresholdLevels=" + Arrays.toString(mDarkeningThresholdLevels)); 134 pw.println(" mDarkeningThresholdsPercentages=" 135 + Arrays.toString(mDarkeningThresholdsPercentages)); 136 pw.println(" mMinDarkening=" + mMinDarkening); 137 } 138 } 139