1 /*
2  * Copyright (C) 2023 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.config;
18 
19 import android.annotation.Nullable;
20 import android.util.Slog;
21 import android.util.Spline;
22 
23 import com.android.internal.annotations.VisibleForTesting;
24 
25 import java.util.Arrays;
26 import java.util.List;
27 
28 /**
29  * Brightness config for even dimmer
30  */
31 public class EvenDimmerBrightnessData {
32     private static final String TAG = "EvenDimmerBrightnessData";
33 
34     /**
35      * Brightness value at which even dimmer methods are used.
36      */
37     public final float mTransitionPoint;
38 
39     /**
40      * Nits array, maps to mBacklight
41      */
42     public final float[] mNits;
43 
44     /**
45      * Backlight array, maps to mBrightness and mNits
46      */
47     public final float[] mBacklight;
48 
49     /**
50      * Brightness array, maps to mBacklight
51      */
52     public final float[] mBrightness;
53     /**
54      * Spline, mapping between backlight and nits
55      */
56     public final Spline mBacklightToNits;
57     /**
58      * Spline, mapping between nits and backlight
59      */
60     public final Spline mNitsToBacklight;
61     /**
62      * Spline, mapping between brightness and backlight
63      */
64     public final Spline mBrightnessToBacklight;
65     /**
66      * Spline, mapping between backlight and brightness
67      */
68     public final Spline mBacklightToBrightness;
69 
70     /**
71      * Spline, mapping the minimum nits for each lux condition.
72      */
73     public final Spline mMinLuxToNits;
74 
75     @VisibleForTesting
EvenDimmerBrightnessData(float transitionPoint, float[] nits, float[] backlight, float[] brightness, Spline backlightToNits, Spline nitsToBacklight, Spline brightnessToBacklight, Spline backlightToBrightness, Spline minLuxToNits)76     public EvenDimmerBrightnessData(float transitionPoint, float[] nits,
77             float[] backlight, float[] brightness, Spline backlightToNits,
78             Spline nitsToBacklight, Spline brightnessToBacklight, Spline backlightToBrightness,
79             Spline minLuxToNits) {
80         mTransitionPoint = transitionPoint;
81         mNits = nits;
82         mBacklight = backlight;
83         mBrightness = brightness;
84         mBacklightToNits = backlightToNits;
85         mNitsToBacklight = nitsToBacklight;
86         mBrightnessToBacklight = brightnessToBacklight;
87         mBacklightToBrightness = backlightToBrightness;
88         mMinLuxToNits = minLuxToNits;
89     }
90 
91     @Override
toString()92     public String toString() {
93         return "EvenDimmerBrightnessData {"
94                 + "mTransitionPoint: " + mTransitionPoint
95                 + ", mNits: " + Arrays.toString(mNits)
96                 + ", mBacklight: " + Arrays.toString(mBacklight)
97                 + ", mBrightness: " + Arrays.toString(mBrightness)
98                 + ", mBacklightToNits: " + mBacklightToNits
99                 + ", mNitsToBacklight: " + mNitsToBacklight
100                 + ", mBrightnessToBacklight: " + mBrightnessToBacklight
101                 + ", mBacklightToBrightness: " + mBacklightToBrightness
102                 + ", mMinLuxToNits: " + mMinLuxToNits
103                 + "} ";
104     }
105 
106     /**
107      * Loads EvenDimmerBrightnessData from DisplayConfiguration
108      */
109     @Nullable
loadConfig(DisplayConfiguration config)110     public static EvenDimmerBrightnessData loadConfig(DisplayConfiguration config) {
111         final EvenDimmerMode lbm = config.getEvenDimmer();
112         if (lbm == null) {
113             return null;
114         }
115 
116         boolean lbmIsEnabled = lbm.getEnabled();
117         if (!lbmIsEnabled) {
118             return null;
119         }
120 
121         ComprehensiveBrightnessMap map = lbm.getBrightnessMapping();
122         if (map == null) {
123             return null;
124         }
125         String interpolation = map.getInterpolation();
126 
127         List<BrightnessPoint> brightnessPoints = map.getBrightnessPoint();
128         if (brightnessPoints.isEmpty()) {
129             return null;
130         }
131 
132         float[] nits = new float[brightnessPoints.size()];
133         float[] backlight = new float[brightnessPoints.size()];
134         float[] brightness = new float[brightnessPoints.size()];
135 
136         for (int i = 0; i < brightnessPoints.size(); i++) {
137             BrightnessPoint val = brightnessPoints.get(i);
138             nits[i] = val.getNits().floatValue();
139             backlight[i] = val.getBacklight().floatValue();
140             brightness[i] = val.getBrightness().floatValue();
141         }
142 
143         float transitionPoint = lbm.getTransitionPoint().floatValue();
144         final NitsMap minimumNitsMap = lbm.getLuxToMinimumNitsMap();
145         if (minimumNitsMap == null) {
146             Slog.e(TAG, "Invalid min lux to nits mapping");
147             return null;
148         }
149         final List<Point> points = minimumNitsMap.getPoint();
150         final int size = points.size();
151 
152         float[] minLux = new float[size];
153         float[] minNits = new float[size];
154 
155         int i = 0;
156         for (Point point : points) {
157             minLux[i] = point.getValue().floatValue();
158             minNits[i] = point.getNits().floatValue();
159             if (i > 0) {
160                 if (minLux[i] < minLux[i - 1]) {
161                     Slog.e(TAG, "minLuxToNitsSpline must be non-decreasing, ignoring rest "
162                             + " of configuration. Value: " + minLux[i] + " < " + minLux[i - 1]);
163                 }
164                 if (minNits[i] < minNits[i - 1]) {
165                     Slog.e(TAG, "minLuxToNitsSpline must be non-decreasing, ignoring rest "
166                             + " of configuration. Nits: " + minNits[i] + " < " + minNits[i - 1]);
167                 }
168             }
169             ++i;
170         }
171 
172         // Explicitly choose linear interpolation.
173         if ("linear".equals(interpolation)) {
174             return new EvenDimmerBrightnessData(transitionPoint, nits, backlight, brightness,
175                     new Spline.LinearSpline(backlight, nits),
176                     new Spline.LinearSpline(nits, backlight),
177                     new Spline.LinearSpline(brightness, backlight),
178                     new Spline.LinearSpline(backlight, brightness),
179                     new Spline.LinearSpline(minLux, minNits)
180             );
181         }
182 
183         return new EvenDimmerBrightnessData(transitionPoint, nits, backlight, brightness,
184                 Spline.createSpline(backlight, nits),
185                 Spline.createSpline(nits, backlight),
186                 Spline.createSpline(brightness, backlight),
187                 Spline.createSpline(backlight, brightness),
188                 Spline.createSpline(minLux, minNits)
189         );
190     }
191 }
192