242 lines
8.1 KiB
Java
242 lines
8.1 KiB
Java
/*
|
|
* Copyright 2018 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package android.hardware.display;
|
|
|
|
import android.annotation.NonNull;
|
|
import android.annotation.Nullable;
|
|
import android.annotation.SystemApi;
|
|
import android.os.Parcel;
|
|
import android.os.Parcelable;
|
|
|
|
import com.android.internal.util.Preconditions;
|
|
|
|
import java.time.LocalDate;
|
|
import java.util.Arrays;
|
|
import java.util.Objects;
|
|
|
|
/**
|
|
* AmbientBrightnessDayStats stores and manipulates brightness stats over a single day.
|
|
* {@see DisplayManager.getAmbientBrightnessStats()}
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public final class AmbientBrightnessDayStats implements Parcelable {
|
|
|
|
/** The localdate for which brightness stats are being tracked */
|
|
private final LocalDate mLocalDate;
|
|
|
|
/** Ambient brightness values for creating bucket boundaries from */
|
|
private final float[] mBucketBoundaries;
|
|
|
|
/** Stats of how much time (in seconds) was spent in each of the buckets */
|
|
private final float[] mStats;
|
|
|
|
/**
|
|
* Initialize day stats from the given state. The time spent in each of the bucket is
|
|
* initialized to 0.
|
|
*
|
|
* @param localDate The date for which stats are being tracked
|
|
* @param bucketBoundaries Bucket boundaries used from creating the buckets from
|
|
* @hide
|
|
*/
|
|
public AmbientBrightnessDayStats(@NonNull LocalDate localDate,
|
|
@NonNull float[] bucketBoundaries) {
|
|
this(localDate, bucketBoundaries, null);
|
|
}
|
|
|
|
/**
|
|
* Initialize day stats from the given state
|
|
*
|
|
* @param localDate The date for which stats are being tracked
|
|
* @param bucketBoundaries Bucket boundaries used from creating the buckets from
|
|
* @param stats Time spent in each of the buckets (in seconds)
|
|
* @hide
|
|
*/
|
|
public AmbientBrightnessDayStats(@NonNull LocalDate localDate,
|
|
@NonNull float[] bucketBoundaries, float[] stats) {
|
|
Objects.requireNonNull(localDate);
|
|
Objects.requireNonNull(bucketBoundaries);
|
|
Preconditions.checkArrayElementsInRange(bucketBoundaries, 0, Float.MAX_VALUE,
|
|
"bucketBoundaries");
|
|
if (bucketBoundaries.length < 1) {
|
|
throw new IllegalArgumentException("Bucket boundaries must contain at least 1 value");
|
|
}
|
|
checkSorted(bucketBoundaries);
|
|
if (stats == null) {
|
|
stats = new float[bucketBoundaries.length];
|
|
} else {
|
|
Preconditions.checkArrayElementsInRange(stats, 0, Float.MAX_VALUE, "stats");
|
|
if (bucketBoundaries.length != stats.length) {
|
|
throw new IllegalArgumentException(
|
|
"Bucket boundaries and stats must be of same size.");
|
|
}
|
|
}
|
|
mLocalDate = localDate;
|
|
mBucketBoundaries = bucketBoundaries;
|
|
mStats = stats;
|
|
}
|
|
|
|
/**
|
|
* @return The {@link LocalDate} for which brightness stats are being tracked.
|
|
*/
|
|
public LocalDate getLocalDate() {
|
|
return mLocalDate;
|
|
}
|
|
|
|
/**
|
|
* @return Aggregated stats of time spent (in seconds) in various buckets.
|
|
*/
|
|
public float[] getStats() {
|
|
return mStats;
|
|
}
|
|
|
|
/**
|
|
* Returns the bucket boundaries (in lux) used for creating buckets. For eg., if the bucket
|
|
* boundaries array is {b1, b2, b3}, the buckets will be [b1, b2), [b2, b3), [b3, inf).
|
|
*
|
|
* @return The list of bucket boundaries.
|
|
*/
|
|
public float[] getBucketBoundaries() {
|
|
return mBucketBoundaries;
|
|
}
|
|
|
|
private AmbientBrightnessDayStats(Parcel source) {
|
|
mLocalDate = LocalDate.parse(source.readString());
|
|
mBucketBoundaries = source.createFloatArray();
|
|
mStats = source.createFloatArray();
|
|
}
|
|
|
|
public static final @android.annotation.NonNull Creator<AmbientBrightnessDayStats> CREATOR =
|
|
new Creator<AmbientBrightnessDayStats>() {
|
|
|
|
@Override
|
|
public AmbientBrightnessDayStats createFromParcel(Parcel source) {
|
|
return new AmbientBrightnessDayStats(source);
|
|
}
|
|
|
|
@Override
|
|
public AmbientBrightnessDayStats[] newArray(int size) {
|
|
return new AmbientBrightnessDayStats[size];
|
|
}
|
|
};
|
|
|
|
@Override
|
|
public boolean equals(@Nullable Object obj) {
|
|
if (this == obj) {
|
|
return true;
|
|
}
|
|
if (obj == null) {
|
|
return false;
|
|
}
|
|
if (getClass() != obj.getClass()) {
|
|
return false;
|
|
}
|
|
AmbientBrightnessDayStats other = (AmbientBrightnessDayStats) obj;
|
|
return mLocalDate.equals(other.mLocalDate) && Arrays.equals(mBucketBoundaries,
|
|
other.mBucketBoundaries) && Arrays.equals(mStats, other.mStats);
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
final int prime = 31;
|
|
int result = 1;
|
|
result = result * prime + mLocalDate.hashCode();
|
|
result = result * prime + Arrays.hashCode(mBucketBoundaries);
|
|
result = result * prime + Arrays.hashCode(mStats);
|
|
return result;
|
|
}
|
|
|
|
@NonNull
|
|
@Override
|
|
public String toString() {
|
|
StringBuilder bucketBoundariesString = new StringBuilder();
|
|
StringBuilder statsString = new StringBuilder();
|
|
for (int i = 0; i < mBucketBoundaries.length; i++) {
|
|
if (i != 0) {
|
|
bucketBoundariesString.append(", ");
|
|
statsString.append(", ");
|
|
}
|
|
bucketBoundariesString.append(mBucketBoundaries[i]);
|
|
statsString.append(mStats[i]);
|
|
}
|
|
return new StringBuilder()
|
|
.append(mLocalDate).append(" ")
|
|
.append("{").append(bucketBoundariesString).append("} ")
|
|
.append("{").append(statsString).append("}").toString();
|
|
}
|
|
|
|
@Override
|
|
public int describeContents() {
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public void writeToParcel(Parcel dest, int flags) {
|
|
dest.writeString(mLocalDate.toString());
|
|
dest.writeFloatArray(mBucketBoundaries);
|
|
dest.writeFloatArray(mStats);
|
|
}
|
|
|
|
/**
|
|
* Updates the stats by incrementing the time spent for the appropriate bucket based on ambient
|
|
* brightness reading.
|
|
*
|
|
* @param ambientBrightness Ambient brightness reading (in lux)
|
|
* @param durationSec Time spent with the given reading (in seconds)
|
|
* @hide
|
|
*/
|
|
public void log(float ambientBrightness, float durationSec) {
|
|
int bucketIndex = getBucketIndex(ambientBrightness);
|
|
if (bucketIndex >= 0) {
|
|
mStats[bucketIndex] += durationSec;
|
|
}
|
|
}
|
|
|
|
private int getBucketIndex(float ambientBrightness) {
|
|
if (ambientBrightness < mBucketBoundaries[0] || Float.isNaN(ambientBrightness)) {
|
|
return -1;
|
|
}
|
|
int low = 0;
|
|
int high = mBucketBoundaries.length - 1;
|
|
while (low < high) {
|
|
int mid = (low + high) / 2;
|
|
if (mBucketBoundaries[mid] <= ambientBrightness
|
|
&& ambientBrightness < mBucketBoundaries[mid + 1]) {
|
|
return mid;
|
|
} else if (mBucketBoundaries[mid] < ambientBrightness) {
|
|
low = mid + 1;
|
|
} else if (mBucketBoundaries[mid] > ambientBrightness) {
|
|
high = mid - 1;
|
|
}
|
|
}
|
|
return low;
|
|
}
|
|
|
|
private static void checkSorted(float[] values) {
|
|
if (values.length <= 1) {
|
|
return;
|
|
}
|
|
float prevValue = values[0];
|
|
for (int i = 1; i < values.length; i++) {
|
|
Preconditions.checkState(prevValue < values[i]);
|
|
prevValue = values[i];
|
|
}
|
|
return;
|
|
}
|
|
}
|