blob: 5b63dcfa7ad6fcdc695c1d5ff322ac0913d1d622 [file] [log] [blame]
Michael Wrighteef0e132017-11-21 17:57:52 +00001/*
2 * Copyright (C) 2017 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
17package android.hardware.display;
18
Kenny Guy0a9e3412019-02-25 16:23:48 +000019import android.annotation.NonNull;
Kenny Guy05ce8092018-01-17 13:44:20 +000020import android.annotation.Nullable;
Kenny Guy0ff44892018-01-10 14:06:42 +000021import android.annotation.SystemApi;
22import android.annotation.TestApi;
Dan Gittika5a2d632019-01-09 14:25:29 +000023import android.content.pm.ApplicationInfo;
Michael Wrighteef0e132017-11-21 17:57:52 +000024import android.os.Parcel;
25import android.os.Parcelable;
26import android.util.Pair;
27
28import com.android.internal.util.Preconditions;
Dan Gittika5a2d632019-01-09 14:25:29 +000029import com.android.internal.util.XmlUtils;
Michael Wrighteef0e132017-11-21 17:57:52 +000030
Dan Gittika5a2d632019-01-09 14:25:29 +000031import org.xmlpull.v1.XmlPullParser;
32import org.xmlpull.v1.XmlPullParserException;
33import org.xmlpull.v1.XmlSerializer;
34
35import java.io.IOException;
36import java.util.ArrayList;
Michael Wrighteef0e132017-11-21 17:57:52 +000037import java.util.Arrays;
Dan Gittika5a2d632019-01-09 14:25:29 +000038import java.util.HashMap;
39import java.util.List;
40import java.util.Map;
41import java.util.Map.Entry;
Kenny Guy05ce8092018-01-17 13:44:20 +000042import java.util.Objects;
Michael Wrighteef0e132017-11-21 17:57:52 +000043
44/** @hide */
Kenny Guy0ff44892018-01-10 14:06:42 +000045@SystemApi
46@TestApi
Michael Wrighteef0e132017-11-21 17:57:52 +000047public final class BrightnessConfiguration implements Parcelable {
Dan Gittika5a2d632019-01-09 14:25:29 +000048 private static final String TAG_BRIGHTNESS_CURVE = "brightness-curve";
49 private static final String TAG_BRIGHTNESS_POINT = "brightness-point";
50 private static final String TAG_BRIGHTNESS_CORRECTIONS = "brightness-corrections";
51 private static final String TAG_BRIGHTNESS_CORRECTION = "brightness-correction";
52 private static final String ATTR_LUX = "lux";
53 private static final String ATTR_NITS = "nits";
54 private static final String ATTR_DESCRIPTION = "description";
55 private static final String ATTR_PACKAGE_NAME = "package-name";
56 private static final String ATTR_CATEGORY = "category";
57
Michael Wrighteef0e132017-11-21 17:57:52 +000058 private final float[] mLux;
59 private final float[] mNits;
Dan Gittika5a2d632019-01-09 14:25:29 +000060 private final Map<String, BrightnessCorrection> mCorrectionsByPackageName;
61 private final Map<Integer, BrightnessCorrection> mCorrectionsByCategory;
Kenny Guy05ce8092018-01-17 13:44:20 +000062 private final String mDescription;
Michael Wrighteef0e132017-11-21 17:57:52 +000063
Dan Gittika5a2d632019-01-09 14:25:29 +000064 private BrightnessConfiguration(float[] lux, float[] nits,
65 Map<String, BrightnessCorrection> correctionsByPackageName,
66 Map<Integer, BrightnessCorrection> correctionsByCategory, String description) {
Michael Wrighteef0e132017-11-21 17:57:52 +000067 mLux = lux;
68 mNits = nits;
Dan Gittika5a2d632019-01-09 14:25:29 +000069 mCorrectionsByPackageName = correctionsByPackageName;
70 mCorrectionsByCategory = correctionsByCategory;
Kenny Guy05ce8092018-01-17 13:44:20 +000071 mDescription = description;
Michael Wrighteef0e132017-11-21 17:57:52 +000072 }
73
74 /**
75 * Gets the base brightness as curve.
76 *
77 * The curve is returned as a pair of float arrays, the first representing all of the lux
78 * points of the brightness curve and the second representing all of the nits values of the
79 * brightness curve.
80 *
81 * @return the control points for the brightness curve.
82 */
83 public Pair<float[], float[]> getCurve() {
84 return Pair.create(Arrays.copyOf(mLux, mLux.length), Arrays.copyOf(mNits, mNits.length));
85 }
86
Kenny Guy05ce8092018-01-17 13:44:20 +000087 /**
Dan Gittika5a2d632019-01-09 14:25:29 +000088 * Returns a brightness correction by app, or null.
89 *
90 * @param packageName
91 * The app's package name.
92 *
93 * @return The matching brightness correction, or null.
94 *
Dan Gittika5a2d632019-01-09 14:25:29 +000095 */
Dan Gittika5a2d632019-01-09 14:25:29 +000096 @Nullable
Kenny Guy0a9e3412019-02-25 16:23:48 +000097 public BrightnessCorrection getCorrectionByPackageName(@NonNull String packageName) {
Dan Gittika5a2d632019-01-09 14:25:29 +000098 return mCorrectionsByPackageName.get(packageName);
99 }
100
101 /**
102 * Returns a brightness correction by app category, or null.
103 *
104 * @param category
105 * The app category.
106 *
107 * @return The matching brightness correction, or null.
Dan Gittika5a2d632019-01-09 14:25:29 +0000108 */
Dan Gittika5a2d632019-01-09 14:25:29 +0000109 @Nullable
Kenny Guy0a9e3412019-02-25 16:23:48 +0000110 public BrightnessCorrection getCorrectionByCategory(@ApplicationInfo.Category int category) {
Dan Gittika5a2d632019-01-09 14:25:29 +0000111 return mCorrectionsByCategory.get(category);
112 }
113
114 /**
Kenny Guy05ce8092018-01-17 13:44:20 +0000115 * Returns description string.
116 * @hide
117 */
118 public String getDescription() {
119 return mDescription;
120 }
121
Michael Wrighteef0e132017-11-21 17:57:52 +0000122 @Override
123 public void writeToParcel(Parcel dest, int flags) {
124 dest.writeFloatArray(mLux);
125 dest.writeFloatArray(mNits);
Dan Gittika5a2d632019-01-09 14:25:29 +0000126 dest.writeInt(mCorrectionsByPackageName.size());
127 for (Entry<String, BrightnessCorrection> entry : mCorrectionsByPackageName.entrySet()) {
128 final String packageName = entry.getKey();
129 final BrightnessCorrection correction = entry.getValue();
130 dest.writeString(packageName);
131 correction.writeToParcel(dest, flags);
132 }
133 dest.writeInt(mCorrectionsByCategory.size());
134 for (Entry<Integer, BrightnessCorrection> entry : mCorrectionsByCategory.entrySet()) {
135 final int category = entry.getKey();
136 final BrightnessCorrection correction = entry.getValue();
137 dest.writeInt(category);
138 correction.writeToParcel(dest, flags);
139 }
Kenny Guy05ce8092018-01-17 13:44:20 +0000140 dest.writeString(mDescription);
Michael Wrighteef0e132017-11-21 17:57:52 +0000141 }
142
143 @Override
144 public int describeContents() {
145 return 0;
146 }
147
148 @Override
149 public String toString() {
150 StringBuilder sb = new StringBuilder("BrightnessConfiguration{[");
151 final int size = mLux.length;
152 for (int i = 0; i < size; i++) {
153 if (i != 0) {
154 sb.append(", ");
155 }
156 sb.append("(").append(mLux[i]).append(", ").append(mNits[i]).append(")");
157 }
Dan Gittika5a2d632019-01-09 14:25:29 +0000158 sb.append("], {");
159 for (Entry<String, BrightnessCorrection> entry : mCorrectionsByPackageName.entrySet()) {
160 sb.append("'" + entry.getKey() + "': " + entry.getValue() + ", ");
161 }
162 for (Entry<Integer, BrightnessCorrection> entry : mCorrectionsByCategory.entrySet()) {
163 sb.append(entry.getKey() + ": " + entry.getValue() + ", ");
164 }
165 sb.append("}, '");
Dan Gittik122df862018-03-28 16:59:22 +0100166 if (mDescription != null) {
167 sb.append(mDescription);
168 }
Kenny Guy05ce8092018-01-17 13:44:20 +0000169 sb.append("'}");
Michael Wrighteef0e132017-11-21 17:57:52 +0000170 return sb.toString();
171 }
172
173 @Override
174 public int hashCode() {
175 int result = 1;
176 result = result * 31 + Arrays.hashCode(mLux);
177 result = result * 31 + Arrays.hashCode(mNits);
Dan Gittika5a2d632019-01-09 14:25:29 +0000178 result = result * 31 + mCorrectionsByPackageName.hashCode();
179 result = result * 31 + mCorrectionsByCategory.hashCode();
Dan Gittik122df862018-03-28 16:59:22 +0100180 if (mDescription != null) {
181 result = result * 31 + mDescription.hashCode();
182 }
Michael Wrighteef0e132017-11-21 17:57:52 +0000183 return result;
184 }
185
186 @Override
187 public boolean equals(Object o) {
188 if (o == this) {
189 return true;
190 }
191 if (!(o instanceof BrightnessConfiguration)) {
192 return false;
193 }
194 final BrightnessConfiguration other = (BrightnessConfiguration) o;
Kenny Guy05ce8092018-01-17 13:44:20 +0000195 return Arrays.equals(mLux, other.mLux) && Arrays.equals(mNits, other.mNits)
Dan Gittika5a2d632019-01-09 14:25:29 +0000196 && mCorrectionsByPackageName.equals(other.mCorrectionsByPackageName)
197 && mCorrectionsByCategory.equals(other.mCorrectionsByCategory)
Kenny Guy05ce8092018-01-17 13:44:20 +0000198 && Objects.equals(mDescription, other.mDescription);
Michael Wrighteef0e132017-11-21 17:57:52 +0000199 }
200
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700201 public static final @android.annotation.NonNull Creator<BrightnessConfiguration> CREATOR =
Michael Wrighteef0e132017-11-21 17:57:52 +0000202 new Creator<BrightnessConfiguration>() {
203 public BrightnessConfiguration createFromParcel(Parcel in) {
Michael Wrighteef0e132017-11-21 17:57:52 +0000204 float[] lux = in.createFloatArray();
205 float[] nits = in.createFloatArray();
Kenny Guy05ce8092018-01-17 13:44:20 +0000206 Builder builder = new Builder(lux, nits);
Dan Gittika5a2d632019-01-09 14:25:29 +0000207
208 int n = in.readInt();
209 for (int i = 0; i < n; i++) {
210 final String packageName = in.readString();
211 final BrightnessCorrection correction =
212 BrightnessCorrection.CREATOR.createFromParcel(in);
213 builder.addCorrectionByPackageName(packageName, correction);
214 }
215
216 n = in.readInt();
217 for (int i = 0; i < n; i++) {
218 final int category = in.readInt();
219 final BrightnessCorrection correction =
220 BrightnessCorrection.CREATOR.createFromParcel(in);
221 builder.addCorrectionByCategory(category, correction);
222 }
223
224 final String description = in.readString();
225 builder.setDescription(description);
Michael Wrighteef0e132017-11-21 17:57:52 +0000226 return builder.build();
227 }
228
229 public BrightnessConfiguration[] newArray(int size) {
230 return new BrightnessConfiguration[size];
231 }
232 };
233
234 /**
Dan Gittika5a2d632019-01-09 14:25:29 +0000235 * Writes the configuration to an XML serializer.
236 *
237 * @param serializer
238 * The XML serializer.
239 *
240 * @hide
241 */
Kenny Guy0a9e3412019-02-25 16:23:48 +0000242 public void saveToXml(@NonNull XmlSerializer serializer) throws IOException {
Dan Gittika5a2d632019-01-09 14:25:29 +0000243 serializer.startTag(null, TAG_BRIGHTNESS_CURVE);
244 if (mDescription != null) {
245 serializer.attribute(null, ATTR_DESCRIPTION, mDescription);
246 }
247 for (int i = 0; i < mLux.length; i++) {
248 serializer.startTag(null, TAG_BRIGHTNESS_POINT);
249 serializer.attribute(null, ATTR_LUX, Float.toString(mLux[i]));
250 serializer.attribute(null, ATTR_NITS, Float.toString(mNits[i]));
251 serializer.endTag(null, TAG_BRIGHTNESS_POINT);
252 }
253 serializer.endTag(null, TAG_BRIGHTNESS_CURVE);
254 serializer.startTag(null, TAG_BRIGHTNESS_CORRECTIONS);
255 for (Map.Entry<String, BrightnessCorrection> entry :
256 mCorrectionsByPackageName.entrySet()) {
257 final String packageName = entry.getKey();
258 final BrightnessCorrection correction = entry.getValue();
259 serializer.startTag(null, TAG_BRIGHTNESS_CORRECTION);
260 serializer.attribute(null, ATTR_PACKAGE_NAME, packageName);
261 correction.saveToXml(serializer);
262 serializer.endTag(null, TAG_BRIGHTNESS_CORRECTION);
263 }
264 for (Map.Entry<Integer, BrightnessCorrection> entry : mCorrectionsByCategory.entrySet()) {
265 final int category = entry.getKey();
266 final BrightnessCorrection correction = entry.getValue();
267 serializer.startTag(null, TAG_BRIGHTNESS_CORRECTION);
268 serializer.attribute(null, ATTR_CATEGORY, Integer.toString(category));
269 correction.saveToXml(serializer);
270 serializer.endTag(null, TAG_BRIGHTNESS_CORRECTION);
271 }
272 serializer.endTag(null, TAG_BRIGHTNESS_CORRECTIONS);
273 }
274
275 /**
276 * Read a configuration from an XML parser.
277 *
278 * @param parser
279 * The XML parser.
280 *
281 * @throws IOException
282 * The parser failed to read the XML file.
283 * @throws XmlPullParserException
284 * The parser failed to parse the XML file.
285 *
286 * @hide
287 */
Kenny Guy0a9e3412019-02-25 16:23:48 +0000288 public static BrightnessConfiguration loadFromXml(@NonNull XmlPullParser parser)
Dan Gittika5a2d632019-01-09 14:25:29 +0000289 throws IOException, XmlPullParserException {
290 String description = null;
291 List<Float> luxList = new ArrayList<>();
292 List<Float> nitsList = new ArrayList<>();
293 Map<String, BrightnessCorrection> correctionsByPackageName = new HashMap<>();
294 Map<Integer, BrightnessCorrection> correctionsByCategory = new HashMap<>();
295 final int configDepth = parser.getDepth();
296 while (XmlUtils.nextElementWithin(parser, configDepth)) {
297 if (TAG_BRIGHTNESS_CURVE.equals(parser.getName())) {
298 description = parser.getAttributeValue(null, ATTR_DESCRIPTION);
299 final int curveDepth = parser.getDepth();
300 while (XmlUtils.nextElementWithin(parser, curveDepth)) {
301 if (!TAG_BRIGHTNESS_POINT.equals(parser.getName())) {
302 continue;
303 }
304 final float lux = loadFloatFromXml(parser, ATTR_LUX);
305 final float nits = loadFloatFromXml(parser, ATTR_NITS);
306 luxList.add(lux);
307 nitsList.add(nits);
308 }
309 }
310 if (TAG_BRIGHTNESS_CORRECTIONS.equals(parser.getName())) {
311 final int correctionsDepth = parser.getDepth();
312 while (XmlUtils.nextElementWithin(parser, correctionsDepth)) {
313 if (!TAG_BRIGHTNESS_CORRECTION.equals(parser.getName())) {
314 continue;
315 }
316 final String packageName = parser.getAttributeValue(null, ATTR_PACKAGE_NAME);
317 final String categoryText = parser.getAttributeValue(null, ATTR_CATEGORY);
318 BrightnessCorrection correction = BrightnessCorrection.loadFromXml(parser);
319 if (packageName != null) {
320 correctionsByPackageName.put(packageName, correction);
321 } else if (categoryText != null) {
322 try {
323 final int category = Integer.parseInt(categoryText);
324 correctionsByCategory.put(category, correction);
325 } catch (NullPointerException | NumberFormatException e) {
326 continue;
327 }
328 }
329 }
330 }
331 }
332 final int n = luxList.size();
333 float[] lux = new float[n];
334 float[] nits = new float[n];
335 for (int i = 0; i < n; i++) {
336 lux[i] = luxList.get(i);
337 nits[i] = nitsList.get(i);
338 }
339 final BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(lux,
340 nits);
341 builder.setDescription(description);
342 for (Map.Entry<String, BrightnessCorrection> entry : correctionsByPackageName.entrySet()) {
343 final String packageName = entry.getKey();
344 final BrightnessCorrection correction = entry.getValue();
345 builder.addCorrectionByPackageName(packageName, correction);
346 }
347 for (Map.Entry<Integer, BrightnessCorrection> entry : correctionsByCategory.entrySet()) {
348 final int category = entry.getKey();
349 final BrightnessCorrection correction = entry.getValue();
350 builder.addCorrectionByCategory(category, correction);
351 }
352 return builder.build();
353 }
354
355 private static float loadFloatFromXml(XmlPullParser parser, String attribute) {
356 final String string = parser.getAttributeValue(null, attribute);
357 try {
358 return Float.parseFloat(string);
359 } catch (NullPointerException | NumberFormatException e) {
360 return Float.NaN;
361 }
362 }
363
364 /**
Michael Wrighteef0e132017-11-21 17:57:52 +0000365 * A builder class for {@link BrightnessConfiguration}s.
366 */
367 public static class Builder {
Dan Gittika5a2d632019-01-09 14:25:29 +0000368 private static final int MAX_CORRECTIONS_BY_PACKAGE_NAME = 20;
369 private static final int MAX_CORRECTIONS_BY_CATEGORY = 20;
370
Michael Wrighteef0e132017-11-21 17:57:52 +0000371 private float[] mCurveLux;
372 private float[] mCurveNits;
Dan Gittika5a2d632019-01-09 14:25:29 +0000373 private Map<String, BrightnessCorrection> mCorrectionsByPackageName;
374 private Map<Integer, BrightnessCorrection> mCorrectionsByCategory;
Kenny Guy05ce8092018-01-17 13:44:20 +0000375 private String mDescription;
376
377 /**
Kenny Guy05ce8092018-01-17 13:44:20 +0000378 * Constructs the builder with the control points for the brightness curve.
379 *
380 * Brightness curves must have strictly increasing ambient brightness values in lux and
381 * monotonically increasing display brightness values in nits. In addition, the initial
382 * control point must be 0 lux.
383 *
384 * @throws IllegalArgumentException if the initial control point is not at 0 lux.
385 * @throws IllegalArgumentException if the lux levels are not strictly increasing.
386 * @throws IllegalArgumentException if the nit levels are not monotonically increasing.
387 */
388 public Builder(float[] lux, float[] nits) {
Michael Wrighteef0e132017-11-21 17:57:52 +0000389 Preconditions.checkNotNull(lux);
390 Preconditions.checkNotNull(nits);
391 if (lux.length == 0 || nits.length == 0) {
392 throw new IllegalArgumentException("Lux and nits arrays must not be empty");
393 }
394 if (lux.length != nits.length) {
395 throw new IllegalArgumentException("Lux and nits arrays must be the same length");
396 }
397 if (lux[0] != 0) {
398 throw new IllegalArgumentException("Initial control point must be for 0 lux");
399 }
400 Preconditions.checkArrayElementsInRange(lux, 0, Float.MAX_VALUE, "lux");
401 Preconditions.checkArrayElementsInRange(nits, 0, Float.MAX_VALUE, "nits");
Kenny Guyd62c3cf2018-09-11 11:41:06 +0100402 checkMonotonic(lux, true /*strictly increasing*/, "lux");
Michael Wrighteef0e132017-11-21 17:57:52 +0000403 checkMonotonic(nits, false /*strictly increasing*/, "nits");
404 mCurveLux = lux;
405 mCurveNits = nits;
Dan Gittika5a2d632019-01-09 14:25:29 +0000406 mCorrectionsByPackageName = new HashMap<>();
407 mCorrectionsByCategory = new HashMap<>();
408 }
409
410 /**
411 * Returns the maximum number of corrections by package name allowed.
412 *
413 * @return The maximum number of corrections by package name allowed.
414 *
Dan Gittika5a2d632019-01-09 14:25:29 +0000415 */
Dan Gittika5a2d632019-01-09 14:25:29 +0000416 public int getMaxCorrectionsByPackageName() {
417 return MAX_CORRECTIONS_BY_PACKAGE_NAME;
418 }
419
420 /**
421 * Returns the maximum number of corrections by category allowed.
422 *
423 * @return The maximum number of corrections by category allowed.
424 *
Dan Gittika5a2d632019-01-09 14:25:29 +0000425 */
Dan Gittika5a2d632019-01-09 14:25:29 +0000426 public int getMaxCorrectionsByCategory() {
427 return MAX_CORRECTIONS_BY_CATEGORY;
428 }
429
430 /**
431 * Add a brightness correction by app package name.
432 * This correction is applied whenever an app with this package name has the top activity
433 * of the focused stack.
434 *
435 * @param packageName
436 * The app's package name.
437 * @param correction
438 * The brightness correction.
439 *
440 * @return The builder.
441 *
442 * @throws IllegalArgumentExceptions
443 * Maximum number of corrections by package name exceeded (see
444 * {@link #getMaxCorrectionsByPackageName}).
445 *
Dan Gittika5a2d632019-01-09 14:25:29 +0000446 */
Kenny Guy31eb3782019-02-28 14:40:51 +0000447 @NonNull
Kenny Guy0a9e3412019-02-25 16:23:48 +0000448 public Builder addCorrectionByPackageName(@NonNull String packageName,
449 @NonNull BrightnessCorrection correction) {
450 Objects.requireNonNull(packageName, "packageName must not be null");
451 Objects.requireNonNull(correction, "correction must not be null");
Dan Gittika5a2d632019-01-09 14:25:29 +0000452 if (mCorrectionsByPackageName.size() >= getMaxCorrectionsByPackageName()) {
453 throw new IllegalArgumentException("Too many corrections by package name");
454 }
455 mCorrectionsByPackageName.put(packageName, correction);
456 return this;
457 }
458
459 /**
460 * Add a brightness correction by app category.
461 * This correction is applied whenever an app with this category has the top activity of
462 * the focused stack, and only if a correction by package name has not been applied.
463 *
464 * @param category
465 * The {@link android.content.pm.ApplicationInfo#category app category}.
466 * @param correction
467 * The brightness correction.
468 *
469 * @return The builder.
470 *
471 * @throws IllegalArgumentException
472 * Maximum number of corrections by category exceeded (see
473 * {@link #getMaxCorrectionsByCategory}).
474 *
Dan Gittika5a2d632019-01-09 14:25:29 +0000475 */
Kenny Guy31eb3782019-02-28 14:40:51 +0000476 @NonNull
Dan Gittika5a2d632019-01-09 14:25:29 +0000477 public Builder addCorrectionByCategory(@ApplicationInfo.Category int category,
Kenny Guy0a9e3412019-02-25 16:23:48 +0000478 @NonNull BrightnessCorrection correction) {
479 Objects.requireNonNull(correction, "correction must not be null");
Dan Gittika5a2d632019-01-09 14:25:29 +0000480 if (mCorrectionsByCategory.size() >= getMaxCorrectionsByCategory()) {
481 throw new IllegalArgumentException("Too many corrections by category");
482 }
483 mCorrectionsByCategory.put(category, correction);
484 return this;
Michael Wrighteef0e132017-11-21 17:57:52 +0000485 }
486
487 /**
Kenny Guy05ce8092018-01-17 13:44:20 +0000488 * Set description of the brightness curve.
489 *
490 * @param description brief text describing the curve pushed. It maybe truncated
491 * and will not be displayed in the UI
492 */
Kenny Guy31eb3782019-02-28 14:40:51 +0000493 @NonNull
Kenny Guy05ce8092018-01-17 13:44:20 +0000494 public Builder setDescription(@Nullable String description) {
495 mDescription = description;
496 return this;
497 }
498
499 /**
Michael Wrighteef0e132017-11-21 17:57:52 +0000500 * Builds the {@link BrightnessConfiguration}.
Michael Wrighteef0e132017-11-21 17:57:52 +0000501 */
Kenny Guy31eb3782019-02-28 14:40:51 +0000502 @NonNull
Michael Wrighteef0e132017-11-21 17:57:52 +0000503 public BrightnessConfiguration build() {
504 if (mCurveLux == null || mCurveNits == null) {
505 throw new IllegalStateException("A curve must be set!");
506 }
Dan Gittika5a2d632019-01-09 14:25:29 +0000507 return new BrightnessConfiguration(mCurveLux, mCurveNits, mCorrectionsByPackageName,
508 mCorrectionsByCategory, mDescription);
Michael Wrighteef0e132017-11-21 17:57:52 +0000509 }
510
511 private static void checkMonotonic(float[] vals, boolean strictlyIncreasing, String name) {
512 if (vals.length <= 1) {
513 return;
514 }
515 float prev = vals[0];
516 for (int i = 1; i < vals.length; i++) {
517 if (prev > vals[i] || prev == vals[i] && strictlyIncreasing) {
518 String condition = strictlyIncreasing ? "strictly increasing" : "monotonic";
519 throw new IllegalArgumentException(name + " values must be " + condition);
520 }
521 prev = vals[i];
522 }
523 }
524 }
525}