Merge "Make ambient brightness day stats a system API"

This commit is contained in:
TreeHugger Robot
2018-02-02 00:18:38 +00:00
committed by Android (Google) Code Review
4 changed files with 150 additions and 49 deletions

View File

@@ -1140,6 +1140,15 @@ package android.hardware.camera2.params {
package android.hardware.display {
public final class AmbientBrightnessDayStats implements android.os.Parcelable {
method public int describeContents();
method public float[] getBucketBoundaries();
method public java.time.LocalDate getLocalDate();
method public float[] getStats();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.hardware.display.AmbientBrightnessDayStats> CREATOR;
}
public final class BrightnessChangeEvent implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);

View File

@@ -298,6 +298,15 @@ package android.hardware.camera2 {
package android.hardware.display {
public final class AmbientBrightnessDayStats implements android.os.Parcelable {
method public int describeContents();
method public float[] getBucketBoundaries();
method public java.time.LocalDate getLocalDate();
method public float[] getStats();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.hardware.display.AmbientBrightnessDayStats> CREATOR;
}
public final class BrightnessChangeEvent implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);

View File

@@ -17,6 +17,8 @@
package android.hardware.display;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -28,11 +30,12 @@ import java.util.Arrays;
/**
* AmbientBrightnessDayStats stores and manipulates brightness stats over a single day.
* {@see DisplayManager.getAmbientBrightnessStats()}
* TODO: Make this system API
*
* @hide
*/
public class AmbientBrightnessDayStats implements Parcelable {
@SystemApi
@TestApi
public final class AmbientBrightnessDayStats implements Parcelable {
/** The localdate for which brightness stats are being tracked */
private final LocalDate mLocalDate;
@@ -48,30 +51,30 @@ public class AmbientBrightnessDayStats implements Parcelable {
*/
public AmbientBrightnessDayStats(@NonNull LocalDate localDate,
@NonNull float[] bucketBoundaries) {
Preconditions.checkNotNull(localDate);
Preconditions.checkNotNull(bucketBoundaries);
int numBuckets = bucketBoundaries.length;
if (numBuckets < 1) {
throw new IllegalArgumentException("Bucket boundaries must contain at least 1 value");
}
mLocalDate = localDate;
mBucketBoundaries = bucketBoundaries;
mStats = new float[numBuckets];
this(localDate, bucketBoundaries, null);
}
/**
* @hide
*/
public AmbientBrightnessDayStats(@NonNull LocalDate localDate,
@NonNull float[] bucketBoundaries, @NonNull float[] stats) {
@NonNull float[] bucketBoundaries, float[] stats) {
Preconditions.checkNotNull(localDate);
Preconditions.checkNotNull(bucketBoundaries);
Preconditions.checkNotNull(stats);
Preconditions.checkArrayElementsInRange(bucketBoundaries, 0, Float.MAX_VALUE,
"bucketBoundaries");
if (bucketBoundaries.length < 1) {
throw new IllegalArgumentException("Bucket boundaries must contain at least 1 value");
}
if (bucketBoundaries.length != stats.length) {
throw new IllegalArgumentException("Bucket boundaries and stats must be of same size.");
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;
@@ -193,4 +196,16 @@ public class AmbientBrightnessDayStats implements Parcelable {
}
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;
}
}

View File

@@ -16,8 +16,11 @@
package android.hardware.display;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.os.Parcel;
import android.support.test.filters.SmallTest;
@@ -27,20 +30,53 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import java.time.LocalDate;
import java.util.Arrays;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class AmbientBrightnessDayStatsTest {
private static final LocalDate LOCAL_DATE = LocalDate.now();
private static final float[] BUCKET_BOUNDARIES = {0, 1, 10, 100};
private static final float[] STATS = {1.3f, 2.6f, 5.8f, 10};
@Test
public void testParamsMustNotBeNull() {
assertThrows(NullPointerException.class,
() -> new AmbientBrightnessDayStats(null, BUCKET_BOUNDARIES));
assertThrows(NullPointerException.class,
() -> new AmbientBrightnessDayStats(LOCAL_DATE, null));
assertThrows(NullPointerException.class,
() -> new AmbientBrightnessDayStats(null, BUCKET_BOUNDARIES, STATS));
assertThrows(NullPointerException.class,
() -> new AmbientBrightnessDayStats(LOCAL_DATE, null, STATS));
}
@Test(expected = IllegalArgumentException.class)
public void testBucketBoundariesMustNotBeEmpty() {
new AmbientBrightnessDayStats(LocalDate.now(), new float[]{});
}
@Test(expected = IllegalArgumentException.class)
public void testStatsAndBoundariesMustHaveSameLength() {
float[] stats = Arrays.copyOf(STATS, STATS.length + 1);
stats[stats.length - 1] = 0;
new AmbientBrightnessDayStats(LOCAL_DATE, BUCKET_BOUNDARIES, stats);
}
@Test
public void testAmbientBrightnessDayStatsAdd() {
AmbientBrightnessDayStats dayStats = new AmbientBrightnessDayStats(LocalDate.now(),
new float[]{0, 1, 10, 100});
AmbientBrightnessDayStats dayStats = new AmbientBrightnessDayStats(LOCAL_DATE,
BUCKET_BOUNDARIES);
dayStats.log(0, 1);
dayStats.log(0.5f, 1.5f);
dayStats.log(50, 12.5f);
dayStats.log(2000, 1.24f);
dayStats.log(-10, 0.5f);
assertEquals(4, dayStats.getStats().length);
assertEquals(2.5f, dayStats.getStats()[0], 0);
assertEquals(0, dayStats.getStats()[1], 0);
assertEquals(12.5f, dayStats.getStats()[2], 0);
@@ -48,38 +84,12 @@ public class AmbientBrightnessDayStatsTest {
}
@Test
public void testAmbientBrightnessDayStatsEquals() {
LocalDate today = LocalDate.now();
AmbientBrightnessDayStats dayStats1 = new AmbientBrightnessDayStats(today,
new float[]{0, 1, 10, 100});
AmbientBrightnessDayStats dayStats2 = new AmbientBrightnessDayStats(today,
new float[]{0, 1, 10, 100}, new float[4]);
AmbientBrightnessDayStats dayStats3 = new AmbientBrightnessDayStats(today,
new float[]{0, 1, 10, 100}, new float[]{1, 3, 5, 7});
AmbientBrightnessDayStats dayStats4 = new AmbientBrightnessDayStats(today,
new float[]{0, 1, 10, 100}, new float[]{1, 3, 5, 0});
assertEquals(dayStats1, dayStats2);
assertEquals(dayStats1.hashCode(), dayStats2.hashCode());
assertNotEquals(dayStats1, dayStats3);
assertNotEquals(dayStats1.hashCode(), dayStats3.hashCode());
dayStats4.log(100, 7);
assertEquals(dayStats3, dayStats4);
assertEquals(dayStats3.hashCode(), dayStats4.hashCode());
}
@Test
public void testAmbientBrightnessDayStatsIncorrectInit() {
try {
new AmbientBrightnessDayStats(LocalDate.now(), new float[]{1, 10, 100},
new float[]{1, 5, 6, 7});
} catch (IllegalArgumentException e) {
// Expected
}
try {
new AmbientBrightnessDayStats(LocalDate.now(), new float[]{});
} catch (IllegalArgumentException e) {
// Expected
}
public void testGetters() {
AmbientBrightnessDayStats dayStats = new AmbientBrightnessDayStats(LOCAL_DATE,
BUCKET_BOUNDARIES, STATS);
assertEquals(LOCAL_DATE, dayStats.getLocalDate());
assertArrayEquals(BUCKET_BOUNDARIES, dayStats.getBucketBoundaries(), 0);
assertArrayEquals(STATS, dayStats.getStats(), 0);
}
@Test
@@ -100,4 +110,62 @@ public class AmbientBrightnessDayStatsTest {
parcel);
assertEquals(stats, statsAgain);
}
@Test
public void testAmbientBrightnessDayStatsEquals() {
AmbientBrightnessDayStats emptyDayStats = new AmbientBrightnessDayStats(LOCAL_DATE,
BUCKET_BOUNDARIES);
AmbientBrightnessDayStats identicalEmptyDayStats = new AmbientBrightnessDayStats(LOCAL_DATE,
BUCKET_BOUNDARIES, new float[BUCKET_BOUNDARIES.length]);
assertEquals(emptyDayStats, identicalEmptyDayStats);
assertEquals(emptyDayStats.hashCode(), identicalEmptyDayStats.hashCode());
AmbientBrightnessDayStats dayStats = new AmbientBrightnessDayStats(LOCAL_DATE,
BUCKET_BOUNDARIES, STATS);
AmbientBrightnessDayStats identicalDayStats = new AmbientBrightnessDayStats(LOCAL_DATE,
BUCKET_BOUNDARIES, STATS);
assertEquals(dayStats, identicalDayStats);
assertEquals(dayStats.hashCode(), identicalDayStats.hashCode());
assertNotEquals(emptyDayStats, dayStats);
assertNotEquals(emptyDayStats.hashCode(), dayStats.hashCode());
AmbientBrightnessDayStats differentDateDayStats = new AmbientBrightnessDayStats(
LOCAL_DATE.plusDays(1), BUCKET_BOUNDARIES, STATS);
assertNotEquals(dayStats, differentDateDayStats);
assertNotEquals(dayStats.hashCode(), differentDateDayStats.hashCode());
float[] differentStats = Arrays.copyOf(STATS, STATS.length);
differentStats[differentStats.length - 1] += 5f;
AmbientBrightnessDayStats differentStatsDayStats = new AmbientBrightnessDayStats(LOCAL_DATE,
BUCKET_BOUNDARIES, differentStats);
assertNotEquals(dayStats, differentDateDayStats);
assertNotEquals(dayStats.hashCode(), differentStatsDayStats.hashCode());
float[] differentBucketBoundaries = Arrays.copyOf(BUCKET_BOUNDARIES,
BUCKET_BOUNDARIES.length);
differentBucketBoundaries[differentBucketBoundaries.length - 1] += 100f;
AmbientBrightnessDayStats differentBoundariesDayStats = new AmbientBrightnessDayStats(
LOCAL_DATE, differentBucketBoundaries, STATS);
assertNotEquals(dayStats, differentBoundariesDayStats);
assertNotEquals(dayStats.hashCode(), differentBoundariesDayStats.hashCode());
}
private interface ExceptionRunnable {
void run() throws Exception;
}
private static void assertThrows(Class<? extends Throwable> exceptionClass,
ExceptionRunnable r) {
try {
r.run();
} catch (Throwable e) {
assertTrue("Expected exception type " + exceptionClass.getName() + " but got "
+ e.getClass().getName(), exceptionClass.isAssignableFrom(e.getClass()));
return;
}
fail("Expected exception type " + exceptionClass.getName()
+ ", but no exception was thrown");
}
}