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 com.android.internal.annotations.VisibleForTesting; 22 23 import java.io.PrintWriter; 24 import java.util.Arrays; 25 26 /** 27 * A helper class for handling access to illuminance hysteresis level values. 28 */ 29 @VisibleForTesting 30 public class HysteresisLevels { 31 private static final String TAG = "HysteresisLevels"; 32 33 private static final boolean DEBUG = false; 34 35 private final float[] mBrighteningThresholds; 36 private final float[] mDarkeningThresholds; 37 private final float[] mThresholdLevels; 38 private final float mMinDarkening; 39 private final float mMinBrightening; 40 41 /** 42 * Creates a {@code HysteresisLevels} object with the given equal-length 43 * integer arrays. 44 * @param brighteningThresholds an array of brightening hysteresis constraint constants. 45 * @param darkeningThresholds an array of darkening hysteresis constraint constants. 46 * @param thresholdLevels a monotonically increasing array of threshold levels. 47 * @param minBrighteningThreshold the minimum value for which the brightening value needs to 48 * return. 49 * @param minDarkeningThreshold the minimum value for which the darkening value needs to return. 50 */ HysteresisLevels(int[] brighteningThresholds, int[] darkeningThresholds, int[] thresholdLevels, float minDarkeningThreshold, float minBrighteningThreshold)51 HysteresisLevels(int[] brighteningThresholds, int[] darkeningThresholds, 52 int[] thresholdLevels, float minDarkeningThreshold, float minBrighteningThreshold) { 53 if (brighteningThresholds.length != darkeningThresholds.length 54 || darkeningThresholds.length != thresholdLevels.length + 1) { 55 throw new IllegalArgumentException("Mismatch between hysteresis array lengths."); 56 } 57 mBrighteningThresholds = setArrayFormat(brighteningThresholds, 1000.0f); 58 mDarkeningThresholds = setArrayFormat(darkeningThresholds, 1000.0f); 59 mThresholdLevels = setArrayFormat(thresholdLevels, 1.0f); 60 mMinDarkening = minDarkeningThreshold; 61 mMinBrightening = minBrighteningThreshold; 62 } 63 64 /** 65 * Return the brightening hysteresis threshold for the given value level. 66 */ getBrighteningThreshold(float value)67 public float getBrighteningThreshold(float value) { 68 final float brightConstant = getReferenceLevel(value, mBrighteningThresholds); 69 float brightThreshold = value * (1.0f + brightConstant); 70 if (DEBUG) { 71 Slog.d(TAG, "bright hysteresis constant=" + brightConstant + ", threshold=" 72 + brightThreshold + ", value=" + value); 73 } 74 75 brightThreshold = Math.max(brightThreshold, value + mMinBrightening); 76 return brightThreshold; 77 } 78 79 /** 80 * Return the darkening hysteresis threshold for the given value level. 81 */ getDarkeningThreshold(float value)82 public float getDarkeningThreshold(float value) { 83 final float darkConstant = getReferenceLevel(value, mDarkeningThresholds); 84 float darkThreshold = value * (1.0f - darkConstant); 85 if (DEBUG) { 86 Slog.d(TAG, "dark hysteresis constant=: " + darkConstant + ", threshold=" 87 + darkThreshold + ", value=" + value); 88 } 89 darkThreshold = Math.min(darkThreshold, value - mMinDarkening); 90 return Math.max(darkThreshold, 0.0f); 91 } 92 93 /** 94 * Return the hysteresis constant for the closest threshold value from the given array. 95 */ getReferenceLevel(float value, float[] referenceLevels)96 private float getReferenceLevel(float value, float[] referenceLevels) { 97 int index = 0; 98 while (mThresholdLevels.length > index && value >= mThresholdLevels[index]) { 99 ++index; 100 } 101 return referenceLevels[index]; 102 } 103 104 /** 105 * Return a float array where each i-th element equals {@code configArray[i]/divideFactor}. 106 */ setArrayFormat(int[] configArray, float divideFactor)107 private float[] setArrayFormat(int[] configArray, float divideFactor) { 108 float[] levelArray = new float[configArray.length]; 109 for (int index = 0; levelArray.length > index; ++index) { 110 levelArray[index] = (float)configArray[index] / divideFactor; 111 } 112 return levelArray; 113 } 114 dump(PrintWriter pw)115 void dump(PrintWriter pw) { 116 pw.println("HysteresisLevels"); 117 pw.println(" mBrighteningThresholds=" + Arrays.toString(mBrighteningThresholds)); 118 pw.println(" mDarkeningThresholds=" + Arrays.toString(mDarkeningThresholds)); 119 pw.println(" mThresholdLevels=" + Arrays.toString(mThresholdLevels)); 120 } 121 } 122