Merge "BrightnessTracker should accomodate multiple ambient sensors"

This commit is contained in:
Piotr Wilczyński
2022-12-06 09:55:49 +00:00
committed by Android (Google) Code Review
6 changed files with 240 additions and 197 deletions

View File

@@ -602,6 +602,14 @@ class AutomaticBrightnessController {
mAmbientBrightnessThresholdsIdle.dump(pw);
}
public float[] getLastSensorValues() {
return mAmbientLightRingBuffer.getAllLuxValues();
}
public long[] getLastSensorTimestamps() {
return mAmbientLightRingBuffer.getAllTimestamps();
}
private String configStateToString(int state) {
switch (state) {
case AUTO_BRIGHTNESS_ENABLED:
@@ -1231,10 +1239,42 @@ class AutomaticBrightnessController {
return mRingLux[offsetOf(index)];
}
public float[] getAllLuxValues() {
float[] values = new float[mCount];
if (mCount == 0) {
return values;
}
if (mStart < mEnd) {
System.arraycopy(mRingLux, mStart, values, 0, mCount);
} else {
System.arraycopy(mRingLux, mStart, values, 0, mCapacity - mStart);
System.arraycopy(mRingLux, 0, values, mCapacity - mStart, mEnd);
}
return values;
}
public long getTime(int index) {
return mRingTime[offsetOf(index)];
}
public long[] getAllTimestamps() {
long[] values = new long[mCount];
if (mCount == 0) {
return values;
}
if (mStart < mEnd) {
System.arraycopy(mRingTime, mStart, values, 0, mCount);
} else {
System.arraycopy(mRingTime, mStart, values, 0, mCapacity - mStart);
System.arraycopy(mRingTime, 0, values, mCapacity - mStart, mEnd);
}
return values;
}
public void push(long time, float lux) {
int next = mEnd;
if (mCount == mCapacity) {

View File

@@ -79,10 +79,8 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Date;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@@ -101,8 +99,6 @@ public class BrightnessTracker {
private static final int MAX_EVENTS = 100;
// Discard events when reading or writing that are older than this.
private static final long MAX_EVENT_AGE = TimeUnit.DAYS.toMillis(30);
// Time over which we keep lux sensor readings.
private static final long LUX_EVENT_HORIZON = TimeUnit.SECONDS.toNanos(10);
private static final String TAG_EVENTS = "events";
private static final String TAG_EVENT = "event";
@@ -174,8 +170,6 @@ public class BrightnessTracker {
// Lock held while collecting data related to brightness changes.
private final Object mDataCollectionLock = new Object();
@GuardedBy("mDataCollectionLock")
private Deque<LightData> mLastSensorReadings = new ArrayDeque<>();
@GuardedBy("mDataCollectionLock")
private float mLastBatteryLevel = Float.NaN;
@GuardedBy("mDataCollectionLock")
private float mLastBrightness = -1;
@@ -327,7 +321,8 @@ public class BrightnessTracker {
*/
public void notifyBrightnessChanged(float brightness, boolean userInitiated,
float powerBrightnessFactor, boolean isUserSetBrightness,
boolean isDefaultBrightnessConfig, String uniqueDisplayId) {
boolean isDefaultBrightnessConfig, String uniqueDisplayId, float[] luxValues,
long[] luxTimestamps) {
if (DEBUG) {
Slog.d(TAG, String.format("notifyBrightnessChanged(brightness=%f, userInitiated=%b)",
brightness, userInitiated));
@@ -335,7 +330,7 @@ public class BrightnessTracker {
Message m = mBgHandler.obtainMessage(MSG_BRIGHTNESS_CHANGED,
userInitiated ? 1 : 0, 0 /*unused*/, new BrightnessChangeValues(brightness,
powerBrightnessFactor, isUserSetBrightness, isDefaultBrightnessConfig,
mInjector.currentTimeMillis(), uniqueDisplayId));
mInjector.currentTimeMillis(), uniqueDisplayId, luxValues, luxTimestamps));
m.sendToTarget();
}
@@ -349,7 +344,8 @@ public class BrightnessTracker {
private void handleBrightnessChanged(float brightness, boolean userInitiated,
float powerBrightnessFactor, boolean isUserSetBrightness,
boolean isDefaultBrightnessConfig, long timestamp, String uniqueDisplayId) {
boolean isDefaultBrightnessConfig, long timestamp, String uniqueDisplayId,
float[] luxValues, long[] luxTimestamps) {
BrightnessChangeEvent.Builder builder;
synchronized (mDataCollectionLock) {
@@ -376,28 +372,22 @@ public class BrightnessTracker {
builder.setIsDefaultBrightnessConfig(isDefaultBrightnessConfig);
builder.setUniqueDisplayId(uniqueDisplayId);
final int readingCount = mLastSensorReadings.size();
if (readingCount == 0) {
if (luxValues.length == 0) {
// No sensor data so ignore this.
return;
}
float[] luxValues = new float[readingCount];
long[] luxTimestamps = new long[readingCount];
long[] luxTimestampsMillis = new long[luxTimestamps.length];
int pos = 0;
// Convert sensor timestamp in elapsed time nanos to current time millis.
// Convert lux timestamp in elapsed time to current time.
long currentTimeMillis = mInjector.currentTimeMillis();
long elapsedTimeNanos = mInjector.elapsedRealtimeNanos();
for (LightData reading : mLastSensorReadings) {
luxValues[pos] = reading.lux;
luxTimestamps[pos] = currentTimeMillis -
TimeUnit.NANOSECONDS.toMillis(elapsedTimeNanos - reading.timestamp);
++pos;
for (int i = 0; i < luxTimestamps.length; i++) {
luxTimestampsMillis[i] = currentTimeMillis - (TimeUnit.NANOSECONDS.toMillis(
elapsedTimeNanos) - luxTimestamps[i]);
}
builder.setLuxValues(luxValues);
builder.setLuxTimestamps(luxTimestamps);
builder.setLuxTimestamps(luxTimestampsMillis);
builder.setBatteryLevel(mLastBatteryLevel);
builder.setLastBrightness(previousBrightness);
@@ -452,9 +442,6 @@ public class BrightnessTracker {
if (mLightSensor != lightSensor) {
mLightSensor = lightSensor;
stopSensorListener();
synchronized (mDataCollectionLock) {
mLastSensorReadings.clear();
}
// Attempt to restart the sensor listener. It will check to see if it should be running
// so there is no need to also check here.
startSensorListener();
@@ -798,12 +785,6 @@ public class BrightnessTracker {
pw.println(" mLightSensor=" + mLightSensor);
pw.println(" mLastBatteryLevel=" + mLastBatteryLevel);
pw.println(" mLastBrightness=" + mLastBrightness);
pw.println(" mLastSensorReadings.size=" + mLastSensorReadings.size());
if (!mLastSensorReadings.isEmpty()) {
pw.println(" mLastSensorReadings time span "
+ mLastSensorReadings.peekFirst().timestamp + "->"
+ mLastSensorReadings.peekLast().timestamp);
}
}
synchronized (mEventsLock) {
pw.println(" mEventsDirty=" + mEventsDirty);
@@ -919,43 +900,6 @@ public class BrightnessTracker {
return ParceledListSlice.emptyList();
}
// Not allowed to keep the SensorEvent so used to copy the data we care about.
private static class LightData {
public float lux;
// Time in elapsedRealtimeNanos
public long timestamp;
}
private void recordSensorEvent(SensorEvent event) {
long horizon = mInjector.elapsedRealtimeNanos() - LUX_EVENT_HORIZON;
synchronized (mDataCollectionLock) {
if (DEBUG) {
Slog.v(TAG, "Sensor event " + event);
}
if (!mLastSensorReadings.isEmpty()
&& event.timestamp < mLastSensorReadings.getLast().timestamp) {
// Ignore event that came out of order.
return;
}
LightData data = null;
while (!mLastSensorReadings.isEmpty()
&& mLastSensorReadings.getFirst().timestamp < horizon) {
// Remove data that has fallen out of the window.
data = mLastSensorReadings.removeFirst();
}
// We put back the last one we removed so we know how long
// the first sensor reading was valid for.
if (data != null) {
mLastSensorReadings.addFirst(data);
}
data = new LightData();
data.timestamp = event.timestamp;
data.lux = event.values[0];
mLastSensorReadings.addLast(data);
}
}
private void recordAmbientBrightnessStats(SensorEvent event) {
mAmbientBrightnessStatsTracker.add(mCurrentUserId, event.values[0]);
}
@@ -969,7 +913,6 @@ public class BrightnessTracker {
private final class SensorListener implements SensorEventListener {
@Override
public void onSensorChanged(SensorEvent event) {
recordSensorEvent(event);
recordAmbientBrightnessStats(event);
}
@@ -1056,7 +999,7 @@ public class BrightnessTracker {
handleBrightnessChanged(values.brightness, userInitiatedChange,
values.powerBrightnessFactor, values.isUserSetBrightness,
values.isDefaultBrightnessConfig, values.timestamp,
values.uniqueDisplayId);
values.uniqueDisplayId, values.luxValues, values.luxTimestamps);
break;
case MSG_START_SENSOR_LISTENER:
startSensorListener();
@@ -1092,16 +1035,20 @@ public class BrightnessTracker {
public final boolean isDefaultBrightnessConfig;
public final long timestamp;
public final String uniqueDisplayId;
public final float[] luxValues;
public final long[] luxTimestamps;
BrightnessChangeValues(float brightness, float powerBrightnessFactor,
boolean isUserSetBrightness, boolean isDefaultBrightnessConfig,
long timestamp, String uniqueDisplayId) {
long timestamp, String uniqueDisplayId, float[] luxValues, long[] luxTimestamps) {
this.brightness = brightness;
this.powerBrightnessFactor = powerBrightnessFactor;
this.isUserSetBrightness = isUserSetBrightness;
this.isDefaultBrightnessConfig = isDefaultBrightnessConfig;
this.timestamp = timestamp;
this.uniqueDisplayId = uniqueDisplayId;
this.luxValues = luxValues;
this.luxTimestamps = luxTimestamps;
}
}

View File

@@ -2435,7 +2435,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
: 1.0f;
mBrightnessTracker.notifyBrightnessChanged(brightnessInNits, userInitiated,
powerFactor, hadUserDataPoint,
mAutomaticBrightnessController.isDefaultConfig(), mUniqueDisplayId);
mAutomaticBrightnessController.isDefaultConfig(), mUniqueDisplayId,
mAutomaticBrightnessController.getLastSensorValues(),
mAutomaticBrightnessController.getLastSensorTimestamps());
}
}

View File

@@ -2141,7 +2141,9 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
: 1.0f;
mBrightnessTracker.notifyBrightnessChanged(brightnessInNits, userInitiated,
powerFactor, hadUserDataPoint,
mAutomaticBrightnessController.isDefaultConfig(), mUniqueDisplayId);
mAutomaticBrightnessController.isDefaultConfig(), mUniqueDisplayId,
mAutomaticBrightnessController.getLastSensorValues(),
mAutomaticBrightnessController.getLastSensorTimestamps());
}
}

View File

@@ -18,6 +18,7 @@ package com.android.server.display;
import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
@@ -176,7 +177,7 @@ public class AutomaticBrightnessControllerTest {
// Send new sensor value and verify
listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux1));
assertEquals(normalizedBrightness1, mController.getAutomaticScreenBrightness(), 0.001f);
assertEquals(normalizedBrightness1, mController.getAutomaticScreenBrightness(), EPSILON);
// Set up system to return 0.0f (minimum possible brightness) as a brightness value
float lux2 = 10.0f;
@@ -190,7 +191,7 @@ public class AutomaticBrightnessControllerTest {
// Send new sensor value and verify
listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux2));
assertEquals(normalizedBrightness2, mController.getAutomaticScreenBrightness(), 0.001f);
assertEquals(normalizedBrightness2, mController.getAutomaticScreenBrightness(), EPSILON);
}
@Test
@@ -219,7 +220,7 @@ public class AutomaticBrightnessControllerTest {
// Send new sensor value and verify
listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux1));
assertEquals(normalizedBrightness1, mController.getAutomaticScreenBrightness(), 0.001f);
assertEquals(normalizedBrightness1, mController.getAutomaticScreenBrightness(), EPSILON);
// Set up system to return 1.0f as a brightness value (brightness_max)
@@ -234,7 +235,7 @@ public class AutomaticBrightnessControllerTest {
// Send new sensor value and verify
listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux2));
assertEquals(normalizedBrightness2, mController.getAutomaticScreenBrightness(), 0.001f);
assertEquals(normalizedBrightness2, mController.getAutomaticScreenBrightness(), EPSILON);
}
@Test
@@ -416,6 +417,12 @@ public class AutomaticBrightnessControllerTest {
// ambient lux goes to 0
listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
assertEquals(0.0f, mController.getAmbientLux(), EPSILON);
// only the values within the horizon should be kept
assertArrayEquals(new float[] {10000, 10000, 0, 0, 0}, mController.getLastSensorValues(),
EPSILON);
assertArrayEquals(new long[] {4000, 4500, 5000, 5500, 6000},
mController.getLastSensorTimestamps());
}
@Test
@@ -487,4 +494,92 @@ public class AutomaticBrightnessControllerTest {
0 /* adjustment */, false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT);
assertEquals(BRIGHTNESS_MAX_FLOAT, mController.getAutomaticScreenBrightness(), 0.0f);
}
@Test
public void testGetSensorReadings() throws Exception {
ArgumentCaptor<SensorEventListener> listenerCaptor =
ArgumentCaptor.forClass(SensorEventListener.class);
verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor),
eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class));
SensorEventListener listener = listenerCaptor.getValue();
// Choose values such that the ring buffer's capacity is extended and the buffer is pruned
int increment = 11;
int lux = 5000;
for (int i = 0; i < 1000; i++) {
lux += increment;
mClock.fastForward(increment);
listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux));
}
int valuesCount = (int) Math.ceil((double) AMBIENT_LIGHT_HORIZON_LONG / increment + 1);
float[] sensorValues = mController.getLastSensorValues();
long[] sensorTimestamps = mController.getLastSensorTimestamps();
// Only the values within the horizon should be kept
assertEquals(valuesCount, sensorValues.length);
assertEquals(valuesCount, sensorTimestamps.length);
long sensorTimestamp = mClock.now();
for (int i = valuesCount - 1; i >= 1; i--) {
assertEquals(lux, sensorValues[i], EPSILON);
assertEquals(sensorTimestamp, sensorTimestamps[i]);
lux -= increment;
sensorTimestamp -= increment;
}
assertEquals(lux, sensorValues[0], EPSILON);
assertEquals(mClock.now() - AMBIENT_LIGHT_HORIZON_LONG, sensorTimestamps[0]);
}
@Test
public void testGetSensorReadingsFullBuffer() throws Exception {
ArgumentCaptor<SensorEventListener> listenerCaptor =
ArgumentCaptor.forClass(SensorEventListener.class);
verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor),
eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class));
SensorEventListener listener = listenerCaptor.getValue();
int initialCapacity = 150;
// Choose values such that the ring buffer is pruned
int increment1 = 200;
int lux = 5000;
for (int i = 0; i < 20; i++) {
lux += increment1;
mClock.fastForward(increment1);
listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux));
}
int valuesCount = (int) Math.ceil((double) AMBIENT_LIGHT_HORIZON_LONG / increment1 + 1);
// Choose values such that the buffer becomes full
int increment2 = 1;
for (int i = 0; i < initialCapacity - valuesCount; i++) {
lux += increment2;
mClock.fastForward(increment2);
listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux));
}
float[] sensorValues = mController.getLastSensorValues();
long[] sensorTimestamps = mController.getLastSensorTimestamps();
// The buffer should be full
assertEquals(initialCapacity, sensorValues.length);
assertEquals(initialCapacity, sensorTimestamps.length);
long sensorTimestamp = mClock.now();
for (int i = initialCapacity - 1; i >= 1; i--) {
assertEquals(lux, sensorValues[i], EPSILON);
assertEquals(sensorTimestamp, sensorTimestamps[i]);
if (i >= valuesCount) {
lux -= increment2;
sensorTimestamp -= increment2;
} else {
lux -= increment1;
sensorTimestamp -= increment1;
}
}
assertEquals(lux, sensorValues[0], EPSILON);
assertEquals(mClock.now() - AMBIENT_LIGHT_HORIZON_LONG, sensorTimestamps[0]);
}
}

View File

@@ -136,28 +136,28 @@ public class BrightnessTrackerTest {
assertNull(mInjector.mSensorListener);
assertNotNull(mInjector.mBroadcastReceiver);
assertTrue(mInjector.mIdleScheduled);
mInjector.sendScreenChange(/*screen on */ true);
mInjector.sendScreenChange(/* screenOn= */ true);
assertNotNull(mInjector.mSensorListener);
assertTrue(mInjector.mColorSamplingEnabled);
mInjector.sendScreenChange(/*screen on */ false);
mInjector.sendScreenChange(/* screenOn= */ false);
assertNull(mInjector.mSensorListener);
assertFalse(mInjector.mColorSamplingEnabled);
// Turn screen on while brightness mode is manual
mInjector.setBrightnessMode(/* isBrightnessModeAutomatic */ false);
mInjector.sendScreenChange(/*screen on */ true);
mInjector.setBrightnessMode(/* isBrightnessModeAutomatic= */ false);
mInjector.sendScreenChange(/* screenOn= */ true);
assertNull(mInjector.mSensorListener);
assertFalse(mInjector.mColorSamplingEnabled);
// Set brightness mode to automatic while screen is off.
mInjector.sendScreenChange(/*screen on */ false);
mInjector.setBrightnessMode(/* isBrightnessModeAutomatic */ true);
mInjector.sendScreenChange(/* screenOn= */ false);
mInjector.setBrightnessMode(/* isBrightnessModeAutomatic= */ true);
assertNull(mInjector.mSensorListener);
assertFalse(mInjector.mColorSamplingEnabled);
// Turn on screen while brightness mode is automatic.
mInjector.sendScreenChange(/*screen on */ true);
mInjector.sendScreenChange(/* screenOn= */ true);
assertNotNull(mInjector.mSensorListener);
assertTrue(mInjector.mColorSamplingEnabled);
@@ -188,14 +188,14 @@ public class BrightnessTrackerTest {
assertFalse(mInjector.mColorSamplingEnabled);
// Pretend screen is off, update config to turn on color sampling.
mInjector.sendScreenChange(/*screen on */ false);
mInjector.sendScreenChange(/* screenOn= */ false);
mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
/* collectColorSamples= */ true));
mInjector.waitForHandler();
assertFalse(mInjector.mColorSamplingEnabled);
// Pretend screen is on.
mInjector.sendScreenChange(/*screen on */ true);
mInjector.sendScreenChange(/* screenOn= */ true);
assertTrue(mInjector.mColorSamplingEnabled);
mTracker.stop();
@@ -261,7 +261,7 @@ public class BrightnessTrackerTest {
assertFalse(mInjector.mColorSamplingEnabled);
assertNull(mInjector.mDisplayListener);
mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ true);
mInjector.setBrightnessMode(/* isBrightnessModeAutomatic= */ true);
assertNotNull(mInjector.mSensorListener);
assertTrue(mInjector.mColorSamplingEnabled);
assertNotNull(mInjector.mDisplayListener);
@@ -272,16 +272,15 @@ public class BrightnessTrackerTest {
mInjector.mColorSamplingEnabled = false;
mInjector.mDisplayListener = null;
// Duplicate notification
mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ true);
mInjector.setBrightnessMode(/* isBrightnessModeAutomatic= */ true);
// Sensor shouldn't have been registered as it was already registered.
assertNull(mInjector.mSensorListener);
assertFalse(mInjector.mColorSamplingEnabled);
assertNull(mInjector.mDisplayListener);
mInjector.mSensorListener = listener;
mInjector.mDisplayListener = displayListener;
mInjector.mColorSamplingEnabled = true;
mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ false);
mInjector.setBrightnessMode(/* isBrightnessModeAutomatic= */ false);
assertNull(mInjector.mSensorListener);
assertFalse(mInjector.mColorSamplingEnabled);
assertNull(mInjector.mDisplayListener);
@@ -301,19 +300,21 @@ public class BrightnessTrackerTest {
final String displayId = "1234";
startTracker(mTracker);
mInjector.mSensorListener.onSensorChanged(createSensorEvent(1.0f));
final long sensorTime = TimeUnit.NANOSECONDS.toMillis(mInjector.elapsedRealtimeNanos());
mInjector.incrementTime(TimeUnit.SECONDS.toMillis(2));
notifyBrightnessChanged(mTracker, brightness, displayId);
final long currentTime = mInjector.currentTimeMillis();
notifyBrightnessChanged(mTracker, brightness, displayId, new float[] {1.0f},
new long[] {sensorTime});
List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
mTracker.stop();
assertEquals(1, events.size());
BrightnessChangeEvent event = events.get(0);
assertEquals(mInjector.currentTimeMillis(), event.timeStamp);
assertEquals(currentTime, event.timeStamp);
assertEquals(displayId, event.uniqueDisplayId);
assertEquals(1, event.luxValues.length);
assertEquals(1.0f, event.luxValues[0], FLOAT_DELTA);
assertEquals(mInjector.currentTimeMillis() - TimeUnit.SECONDS.toMillis(2),
assertEquals(currentTime - TimeUnit.SECONDS.toMillis(2),
event.luxTimestamps[0]);
assertEquals(brightness, event.brightness, FLOAT_DELTA);
assertEquals(DEFAULT_INITIAL_BRIGHTNESS, event.lastBrightness, FLOAT_DELTA);
@@ -339,9 +340,9 @@ public class BrightnessTrackerTest {
startTracker(mTracker, initialBrightness, DEFAULT_COLOR_SAMPLING_ENABLED);
mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(),
batteryChangeEvent(30, 60));
mInjector.mSensorListener.onSensorChanged(createSensorEvent(1000.0f));
final long sensorTime = mInjector.currentTimeMillis();
notifyBrightnessChanged(mTracker, brightness, displayId);
final long currentTime = mInjector.currentTimeMillis();
notifyBrightnessChanged(mTracker, brightness, displayId, new float[] {1000.0f},
new long[] {TimeUnit.NANOSECONDS.toMillis(mInjector.elapsedRealtimeNanos())});
List<BrightnessChangeEvent> eventsNoPackage
= mTracker.getEvents(0, false).getList();
List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
@@ -349,10 +350,10 @@ public class BrightnessTrackerTest {
assertEquals(1, events.size());
BrightnessChangeEvent event = events.get(0);
assertEquals(event.timeStamp, mInjector.currentTimeMillis());
assertEquals(event.timeStamp, currentTime);
assertEquals(displayId, event.uniqueDisplayId);
assertArrayEquals(new float[] {1000.0f}, event.luxValues, 0.01f);
assertArrayEquals(new long[] {sensorTime}, event.luxTimestamps);
assertArrayEquals(new float[] {1000.0f}, event.luxValues, FLOAT_DELTA);
assertArrayEquals(new long[] {currentTime}, event.luxTimestamps);
assertEquals(brightness, event.brightness, FLOAT_DELTA);
assertEquals(initialBrightness, event.lastBrightness, FLOAT_DELTA);
assertEquals(0.5, event.batteryLevel, FLOAT_DELTA);
@@ -374,13 +375,12 @@ public class BrightnessTrackerTest {
public void testIgnoreAutomaticBrightnessChange() {
final int initialBrightness = 30;
startTracker(mTracker, initialBrightness, DEFAULT_COLOR_SAMPLING_ENABLED);
mInjector.mSensorListener.onSensorChanged(createSensorEvent(1.0f));
mInjector.incrementTime(TimeUnit.SECONDS.toMillis(1));
final int systemUpdatedBrightness = 20;
notifyBrightnessChanged(mTracker, systemUpdatedBrightness, false /*userInitiated*/,
0.5f /*powerBrightnessFactor(*/, false /*isUserSetBrightness*/,
false /*isDefaultBrightnessConfig*/, DEFAULT_DISPLAY_ID);
notifyBrightnessChanged(mTracker, systemUpdatedBrightness, /* userInitiated= */ false,
/* powerBrightnessFactor= */ 0.5f, /* isUserSetBrightness= */ false,
/* isDefaultBrightnessConfig= */ false, DEFAULT_DISPLAY_ID);
List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
// No events because we filtered out our change.
assertEquals(0, events.size());
@@ -408,10 +408,8 @@ public class BrightnessTrackerTest {
@Test
public void testLimitedBufferSize() {
startTracker(mTracker);
mInjector.mSensorListener.onSensorChanged(createSensorEvent(1.0f));
for (int brightness = 0; brightness <= 255; ++brightness) {
mInjector.mSensorListener.onSensorChanged(createSensorEvent(1.0f));
mInjector.incrementTime(TimeUnit.SECONDS.toNanos(1));
notifyBrightnessChanged(mTracker, brightness);
}
@@ -426,33 +424,6 @@ public class BrightnessTrackerTest {
}
}
@Test
public void testLimitedSensorEvents() {
final int brightness = 20;
startTracker(mTracker);
// 20 Sensor events 1 second apart.
for (int i = 0; i < 20; ++i) {
mInjector.incrementTime(TimeUnit.SECONDS.toMillis(1));
mInjector.mSensorListener.onSensorChanged(createSensorEvent(i + 1.0f));
}
notifyBrightnessChanged(mTracker, 20);
List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
mTracker.stop();
assertEquals(1, events.size());
BrightnessChangeEvent event = events.get(0);
assertEquals(mInjector.currentTimeMillis(), event.timeStamp);
// 12 sensor events, 11 for 0->10 seconds + 1 previous event.
assertEquals(12, event.luxValues.length);
for (int i = 0; i < 12; ++i) {
assertEquals(event.luxTimestamps[11 - i],
mInjector.currentTimeMillis() - i * TimeUnit.SECONDS.toMillis(1));
}
assertEquals(brightness, event.brightness, FLOAT_DELTA);
}
@Test
public void testReadEvents() throws Exception {
BrightnessTracker tracker = new BrightnessTracker(InstrumentationRegistry.getContext(),
@@ -607,15 +578,16 @@ public class BrightnessTrackerTest {
startTracker(mTracker);
mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(),
batteryChangeEvent(30, 100));
mInjector.mSensorListener.onSensorChanged(createSensorEvent(2000.0f));
final long firstSensorTime = mInjector.currentTimeMillis();
final long elapsedTime1 = TimeUnit.NANOSECONDS.toMillis(mInjector.elapsedRealtimeNanos());
final long currentTime1 = mInjector.currentTimeMillis();
mInjector.incrementTime(TimeUnit.SECONDS.toMillis(2));
mInjector.mSensorListener.onSensorChanged(createSensorEvent(3000.0f));
final long secondSensorTime = mInjector.currentTimeMillis();
final long elapsedTime2 = TimeUnit.NANOSECONDS.toMillis(mInjector.elapsedRealtimeNanos());
final long currentTime2 = mInjector.currentTimeMillis();
mInjector.incrementTime(TimeUnit.SECONDS.toMillis(3));
notifyBrightnessChanged(mTracker, brightness, true /*userInitiated*/,
0.5f /*powerBrightnessFactor*/, true /*hasUserBrightnessPoints*/,
false /*isDefaultBrightnessConfig*/, displayId);
notifyBrightnessChanged(mTracker, brightness, /* userInitiated= */ true,
/* powerBrightnessFactor= */ 0.5f, /* isUserSetBrightness= */ true,
/* isDefaultBrightnessConfig= */ false, displayId, new float[] {2000.0f, 3000.0f},
new long[] {elapsedTime1, elapsedTime2});
ByteArrayOutputStream baos = new ByteArrayOutputStream();
mTracker.writeEventsLocked(baos);
mTracker.stop();
@@ -631,7 +603,7 @@ public class BrightnessTrackerTest {
BrightnessChangeEvent event = events.get(0);
assertEquals(displayId, event.uniqueDisplayId);
assertArrayEquals(new float[] {2000.0f, 3000.0f}, event.luxValues, FLOAT_DELTA);
assertArrayEquals(new long[] {firstSensorTime, secondSensorTime}, event.luxTimestamps);
assertArrayEquals(new long[] {currentTime1, currentTime2}, event.luxTimestamps);
assertEquals(brightness, event.brightness, FLOAT_DELTA);
assertEquals(0.3, event.batteryLevel, FLOAT_DELTA);
assertTrue(event.nightMode);
@@ -646,53 +618,6 @@ public class BrightnessTrackerTest {
assertEquals(10000, event.colorSampleDuration);
}
@Test
public void testWritePrunesOldEvents() throws Exception {
final int brightness = 20;
mInjector.mSecureIntSettings.put(Settings.Secure.NIGHT_DISPLAY_ACTIVATED, 1);
mInjector.mSecureIntSettings.put(Settings.Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, 3339);
mInjector.mSecureIntSettings.put(Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 1);
mInjector.mSecureIntSettings.put(Settings.Secure.REDUCE_BRIGHT_COLORS_LEVEL, 40);
startTracker(mTracker);
mInjector.mBroadcastReceiver.onReceive(InstrumentationRegistry.getContext(),
batteryChangeEvent(30, 100));
mInjector.mSensorListener.onSensorChanged(createSensorEvent(1000.0f));
mInjector.incrementTime(TimeUnit.SECONDS.toMillis(1));
mInjector.mSensorListener.onSensorChanged(createSensorEvent(2000.0f));
final long sensorTime = mInjector.currentTimeMillis();
notifyBrightnessChanged(mTracker, brightness);
// 31 days later
mInjector.incrementTime(TimeUnit.DAYS.toMillis(31));
mInjector.mSensorListener.onSensorChanged(createSensorEvent(3000.0f));
notifyBrightnessChanged(mTracker, brightness);
final long eventTime = mInjector.currentTimeMillis();
List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
assertEquals(2, events.size());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
mTracker.writeEventsLocked(baos);
events = mTracker.getEvents(0, true).getList();
mTracker.stop();
assertEquals(1, events.size());
BrightnessChangeEvent event = events.get(0);
assertEquals(eventTime, event.timeStamp);
// We will keep one of the old sensor events because we keep 1 event outside the window.
assertArrayEquals(new float[] {2000.0f, 3000.0f}, event.luxValues, FLOAT_DELTA);
assertArrayEquals(new long[] {sensorTime, eventTime}, event.luxTimestamps);
assertEquals(brightness, event.brightness, FLOAT_DELTA);
assertEquals(0.3, event.batteryLevel, FLOAT_DELTA);
assertTrue(event.nightMode);
assertTrue(event.reduceBrightColors);
assertEquals(3339, event.colorTemperature);
}
@Test
public void testParcelUnParcel() {
Parcel parcel = Parcel.obtain();
@@ -796,9 +721,10 @@ public class BrightnessTrackerTest {
// Send an event.
long eventTime = mInjector.currentTimeMillis();
mTracker.notifyBrightnessChanged(brightness, true /*userInitiated*/,
1.0f /*powerBrightnessFactor*/, false /*isUserSetBrightness*/,
false /*isDefaultBrightnessConfig*/, DEFAULT_DISPLAY_ID);
mTracker.notifyBrightnessChanged(brightness, /* userInitiated= */ true,
/* powerBrightnessFactor= */ 1.0f, /* isUserSetBrightness= */ false,
/* isDefaultBrightnessConfig= */ false, DEFAULT_DISPLAY_ID, new float[10],
new long[10]);
// Time passes before handler can run.
mInjector.incrementTime(TimeUnit.SECONDS.toMillis(2));
@@ -890,20 +816,33 @@ public class BrightnessTrackerTest {
public void testOnlyOneReceiverRegistered() {
assertNull(mInjector.mLightSensor);
assertNull(mInjector.mSensorListener);
assertNull(mInjector.mContentObserver);
assertNull(mInjector.mBroadcastReceiver);
assertFalse(mInjector.mIdleScheduled);
startTracker(mTracker, 0.3f, false);
assertNotNull(mInjector.mLightSensor);
assertNotNull(mInjector.mSensorListener);
assertNotNull(mInjector.mContentObserver);
assertNotNull(mInjector.mBroadcastReceiver);
assertTrue(mInjector.mIdleScheduled);
Sensor registeredLightSensor = mInjector.mLightSensor;
SensorEventListener registeredSensorListener = mInjector.mSensorListener;
ContentObserver registeredContentObserver = mInjector.mContentObserver;
BroadcastReceiver registeredBroadcastReceiver = mInjector.mBroadcastReceiver;
mTracker.start(0.3f);
assertSame(registeredLightSensor, mInjector.mLightSensor);
assertSame(registeredSensorListener, mInjector.mSensorListener);
assertSame(registeredContentObserver, mInjector.mContentObserver);
assertSame(registeredBroadcastReceiver, mInjector.mBroadcastReceiver);
mTracker.stop();
assertNull(mInjector.mLightSensor);
assertNull(mInjector.mSensorListener);
assertNull(mInjector.mContentObserver);
assertNull(mInjector.mBroadcastReceiver);
assertFalse(mInjector.mIdleScheduled);
// mInjector asserts that we aren't removing a null receiver
mTracker.stop();
@@ -954,23 +893,41 @@ public class BrightnessTrackerTest {
private void notifyBrightnessChanged(BrightnessTracker tracker, float brightness,
String displayId) {
notifyBrightnessChanged(tracker, brightness, true /*userInitiated*/,
1.0f /*powerBrightnessFactor*/, false /*isUserSetBrightness*/,
false /*isDefaultBrightnessConfig*/, displayId);
notifyBrightnessChanged(tracker, brightness, /* userInitiated= */ true,
/* powerBrightnessFactor= */ 1.0f, /* isUserSetBrightness= */ false,
/* isDefaultBrightnessConfig= */ false, displayId, new float[10], new long[10]);
}
private void notifyBrightnessChanged(BrightnessTracker tracker, float brightness,
String displayId, float[] luxValues, long[] luxTimestamps) {
notifyBrightnessChanged(tracker, brightness, /* userInitiated= */ true,
/* powerBrightnessFactor= */ 1.0f, /* isUserSetBrightness= */ false,
/* isDefaultBrightnessConfig= */ false, displayId, luxValues, luxTimestamps);
}
private void notifyBrightnessChanged(BrightnessTracker tracker, float brightness,
boolean userInitiated, float powerBrightnessFactor, boolean isUserSetBrightness,
boolean isDefaultBrightnessConfig, String displayId) {
tracker.notifyBrightnessChanged(brightness, userInitiated, powerBrightnessFactor,
isUserSetBrightness, isDefaultBrightnessConfig, displayId);
isUserSetBrightness, isDefaultBrightnessConfig, displayId, new float[10],
new long[10]);
mInjector.waitForHandler();
}
private void notifyBrightnessChanged(BrightnessTracker tracker, float brightness,
boolean userInitiated, float powerBrightnessFactor, boolean isUserSetBrightness,
boolean isDefaultBrightnessConfig, String displayId, float[] luxValues,
long[] luxTimestamps) {
tracker.notifyBrightnessChanged(brightness, userInitiated, powerBrightnessFactor,
isUserSetBrightness, isDefaultBrightnessConfig, displayId, luxValues,
luxTimestamps);
mInjector.waitForHandler();
}
private BrightnessConfiguration buildBrightnessConfiguration(boolean collectColorSamples) {
BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(
/* lux = */ new float[] {0f, 10f, 100f},
/* nits = */ new float[] {1f, 90f, 100f});
/* lux= */ new float[] {0f, 10f, 100f},
/* nits= */ new float[] {1f, 90f, 100f});
builder.setShouldCollectColorSamples(collectColorSamples);
return builder.build();
}