blob: 8502e69dd060b8408b5c8fb77b9c3ca5884e02b3 [file] [log] [blame]
/*
* 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 com.android.server.display;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import android.hardware.display.AmbientBrightnessDayStats;
import android.os.SystemClock;
import android.os.UserManager;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.util.ArrayList;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class AmbientBrightnessStatsTrackerTest {
private TestInjector mTestInjector;
@Before
public void setUp() {
mTestInjector = new TestInjector();
}
@Test
public void testBrightnessStatsTrackerOverSingleDay() {
AmbientBrightnessStatsTracker statsTracker = getTestStatsTracker();
ArrayList<AmbientBrightnessDayStats> userStats;
float[] expectedStats;
// Test case where no user data
userStats = statsTracker.getUserStats(0);
assertNull(userStats);
// Test after adding some user data
statsTracker.start();
statsTracker.add(0, 0);
mTestInjector.incrementTime(1000);
statsTracker.stop();
userStats = statsTracker.getUserStats(0);
assertEquals(1, userStats.size());
assertEquals(mTestInjector.getLocalDate(), userStats.get(0).getLocalDate());
expectedStats = getEmptyStatsArray();
expectedStats[0] = 1;
assertArrayEquals(expectedStats, userStats.get(0).getStats(), 0);
// Test after adding some more user data
statsTracker.start();
statsTracker.add(0, 0.05f);
mTestInjector.incrementTime(1000);
statsTracker.add(0, 0.2f);
mTestInjector.incrementTime(1500);
statsTracker.add(0, 50000);
mTestInjector.incrementTime(2500);
statsTracker.stop();
userStats = statsTracker.getUserStats(0);
assertEquals(1, userStats.size());
assertEquals(mTestInjector.getLocalDate(), userStats.get(0).getLocalDate());
expectedStats = getEmptyStatsArray();
expectedStats[0] = 2;
expectedStats[1] = 1.5f;
expectedStats[11] = 2.5f;
assertArrayEquals(expectedStats, userStats.get(0).getStats(), 0);
}
@Test
public void testBrightnessStatsTrackerOverMultipleDays() {
AmbientBrightnessStatsTracker statsTracker = getTestStatsTracker();
ArrayList<AmbientBrightnessDayStats> userStats;
float[] expectedStats;
// Add data for day 1
statsTracker.start();
statsTracker.add(0, 0.05f);
mTestInjector.incrementTime(1000);
statsTracker.add(0, 0.2f);
mTestInjector.incrementTime(1500);
statsTracker.add(0, 1);
mTestInjector.incrementTime(2500);
statsTracker.stop();
// Add data for day 2
mTestInjector.incrementDate(1);
statsTracker.start();
statsTracker.add(0, 0);
mTestInjector.incrementTime(3500);
statsTracker.add(0, 5);
mTestInjector.incrementTime(5000);
statsTracker.stop();
// Test that the data is tracked as expected
userStats = statsTracker.getUserStats(0);
assertEquals(2, userStats.size());
assertEquals(mTestInjector.getLocalDate().minusDays(1), userStats.get(0).getLocalDate());
expectedStats = getEmptyStatsArray();
expectedStats[0] = 1;
expectedStats[1] = 1.5f;
expectedStats[3] = 2.5f;
assertArrayEquals(expectedStats, userStats.get(0).getStats(), 0);
assertEquals(mTestInjector.getLocalDate(), userStats.get(1).getLocalDate());
expectedStats = getEmptyStatsArray();
expectedStats[0] = 3.5f;
expectedStats[4] = 5;
assertArrayEquals(expectedStats, userStats.get(1).getStats(), 0);
}
@Test
public void testBrightnessStatsTrackerOverMultipleUsers() {
AmbientBrightnessStatsTracker statsTracker = getTestStatsTracker();
ArrayList<AmbientBrightnessDayStats> userStats;
float[] expectedStats;
// Add data for user 1
statsTracker.start();
statsTracker.add(0, 0.05f);
mTestInjector.incrementTime(1000);
statsTracker.add(0, 0.2f);
mTestInjector.incrementTime(1500);
statsTracker.add(0, 1);
mTestInjector.incrementTime(2500);
statsTracker.stop();
// Add data for user 2
mTestInjector.incrementDate(1);
statsTracker.start();
statsTracker.add(1, 0);
mTestInjector.incrementTime(3500);
statsTracker.add(1, 5);
mTestInjector.incrementTime(5000);
statsTracker.stop();
// Test that the data is tracked as expected
userStats = statsTracker.getUserStats(0);
assertEquals(1, userStats.size());
assertEquals(mTestInjector.getLocalDate().minusDays(1), userStats.get(0).getLocalDate());
expectedStats = getEmptyStatsArray();
expectedStats[0] = 1;
expectedStats[1] = 1.5f;
expectedStats[3] = 2.5f;
assertArrayEquals(expectedStats, userStats.get(0).getStats(), 0);
userStats = statsTracker.getUserStats(1);
assertEquals(1, userStats.size());
assertEquals(mTestInjector.getLocalDate(), userStats.get(0).getLocalDate());
expectedStats = getEmptyStatsArray();
expectedStats[0] = 3.5f;
expectedStats[4] = 5;
assertArrayEquals(expectedStats, userStats.get(0).getStats(), 0);
}
@Test
public void testBrightnessStatsTrackerOverMaxDays() {
AmbientBrightnessStatsTracker statsTracker = getTestStatsTracker();
ArrayList<AmbientBrightnessDayStats> userStats;
// Add 10 extra days of data over the buffer limit
for (int i = 0; i < AmbientBrightnessStatsTracker.MAX_DAYS_TO_TRACK + 10; i++) {
mTestInjector.incrementDate(1);
statsTracker.start();
statsTracker.add(0, 10);
mTestInjector.incrementTime(1000);
statsTracker.add(0, 20);
mTestInjector.incrementTime(1000);
statsTracker.stop();
}
// Assert that we are only tracking last "MAX_DAYS_TO_TRACK"
userStats = statsTracker.getUserStats(0);
assertEquals(AmbientBrightnessStatsTracker.MAX_DAYS_TO_TRACK, userStats.size());
LocalDate runningDate = mTestInjector.getLocalDate();
for (int i = AmbientBrightnessStatsTracker.MAX_DAYS_TO_TRACK - 1; i >= 0; i--) {
assertEquals(runningDate, userStats.get(i).getLocalDate());
runningDate = runningDate.minusDays(1);
}
}
@Test
public void testReadAmbientBrightnessStats() throws IOException {
AmbientBrightnessStatsTracker statsTracker = getTestStatsTracker();
LocalDate date = mTestInjector.getLocalDate();
ArrayList<AmbientBrightnessDayStats> userStats;
String statsFile =
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\r\n"
+ "<ambient-brightness-stats>\r\n"
// Old stats that shouldn't be read
+ "<ambient-brightness-day-stats user=\"10\" local-date=\""
+ date.minusDays(AmbientBrightnessStatsTracker.MAX_DAYS_TO_TRACK)
+ "\" bucket-boundaries=\"0.0,1.0,3.0,10.0,30.0,100.0,300.0,1000.0,"
+ "3000.0,10000.0\" bucket-stats=\"1.088,0.0,0.726,0.0,25.868,0.0,0.0,"
+ "0.0,0.0,0.0\" />\r\n"
// Valid stats that should get read
+ "<ambient-brightness-day-stats user=\"10\" local-date=\""
+ date.minusDays(1)
+ "\" bucket-boundaries=\"0.0,1.0,3.0,10.0,30.0,100.0,300.0,1000.0,"
+ "3000.0,10000.0\" bucket-stats=\"1.088,0.0,0.726,0.0,25.868,0.0,0.0,"
+ "0.0,0.0,0.0\" />\r\n"
// Valid stats that should get read
+ "<ambient-brightness-day-stats user=\"10\" local-date=\"" + date
+ "\" bucket-boundaries=\"0.0,1.0,3.0,10.0,30.0,100.0,300.0,1000.0,"
+ "3000.0,10000.0\" bucket-stats=\"0.0,0.0,0.0,0.0,4.482,0.0,0.0,0.0,0.0,"
+ "0.0\" />\r\n"
+ "</ambient-brightness-stats>";
statsTracker.readStats(getInputStream(statsFile));
userStats = statsTracker.getUserStats(0);
assertEquals(2, userStats.size());
assertEquals(new AmbientBrightnessDayStats(date.minusDays(1),
new float[]{0, 1, 3, 10, 30, 100, 300, 1000, 3000, 10000},
new float[]{1.088f, 0, 0.726f, 0, 25.868f, 0, 0, 0, 0, 0}), userStats.get(0));
assertEquals(new AmbientBrightnessDayStats(date,
new float[]{0, 1, 3, 10, 30, 100, 300, 1000, 3000, 10000},
new float[]{0, 0, 0, 0, 4.482f, 0, 0, 0, 0, 0}), userStats.get(1));
}
@Test
public void testFailedReadAmbientBrightnessStatsWithException() {
AmbientBrightnessStatsTracker statsTracker = getTestStatsTracker();
LocalDate date = mTestInjector.getLocalDate();
String statsFile;
// Test with parse error
statsFile =
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\r\n"
+ "<ambient-brightness-stats>\r\n"
// Incorrect since bucket boundaries not parsable
+ "<ambient-brightness-day-stats user=\"10\" local-date=\"" + date
+ "\" bucket-boundaries=\"asdf,1.0,3.0,10.0,30.0,100.0,300.0,1000.0,"
+ "3000.0,10000.0\" bucket-stats=\"1.088,0.0,0.726,0.0,25.868,0.0,0.0,"
+ "0.0,0.0,0.0\" />\r\n"
+ "</ambient-brightness-stats>";
try {
statsTracker.readStats(getInputStream(statsFile));
} catch (IOException e) {
// Expected
}
assertNull(statsTracker.getUserStats(0));
// Test with incorrect data (bucket boundaries length not equal to stats length)
statsFile =
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\r\n"
+ "<ambient-brightness-stats>\r\n"
// Correct data
+ "<ambient-brightness-day-stats user=\"10\" local-date=\""
+ date.minusDays(1)
+ "\" bucket-boundaries=\"0.0,1.0,3.0,10.0,30.0,100.0,300.0,1000.0,"
+ "3000.0,10000.0\" bucket-stats=\"0.0,0.0,0.0,0.0,4.482,0.0,0.0,0.0,0.0,"
+ "0.0\" />\r\n"
// Incorrect data
+ "<ambient-brightness-day-stats user=\"10\" local-date=\"" + date
+ "\" bucket-boundaries=\"0.0,1.0,3.0,10.0,30.0,100.0,1000.0,"
+ "3000.0,10000.0\" bucket-stats=\"1.088,0.0,0.726,0.0,25.868,0.0,0.0,"
+ "0.0,0.0,0.0\" />\r\n"
+ "</ambient-brightness-stats>";
try {
statsTracker.readStats(getInputStream(statsFile));
} catch (Exception e) {
// Expected
}
assertNull(statsTracker.getUserStats(0));
// Test with missing attribute
statsFile =
"<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\r\n"
+ "<ambient-brightness-stats>\r\n"
+ "<ambientBrightnessDayStats user=\"10\" local-date=\"" + date
+ "\" bucket-boundaries=\"0.0,1.0,3.0,10.0,30.0,100.0,300.0,1000.0,"
+ "3000.0,10000.0\" />\r\n"
+ "</ambient-brightness-stats>";
try {
statsTracker.readStats(getInputStream(statsFile));
} catch (Exception e) {
// Expected
}
assertNull(statsTracker.getUserStats(0));
}
@Test
public void testWriteThenReadAmbientBrightnessStats() throws IOException {
AmbientBrightnessStatsTracker statsTracker = getTestStatsTracker();
ArrayList<AmbientBrightnessDayStats> userStats;
float[] expectedStats;
// Generate some dummy data
// Data: very old which should not be read
statsTracker.start();
statsTracker.add(0, 0.05f);
mTestInjector.incrementTime(1000);
statsTracker.add(0, 0.2f);
mTestInjector.incrementTime(1500);
statsTracker.add(0, 1);
mTestInjector.incrementTime(2500);
statsTracker.stop();
// Data: day 1 user 1
mTestInjector.incrementDate(AmbientBrightnessStatsTracker.MAX_DAYS_TO_TRACK - 1);
statsTracker.start();
statsTracker.add(0, 0.05f);
mTestInjector.incrementTime(1000);
statsTracker.add(0, 0.2f);
mTestInjector.incrementTime(1500);
statsTracker.add(0, 1);
mTestInjector.incrementTime(2500);
statsTracker.stop();
// Data: day 1 user 2
statsTracker.start();
statsTracker.add(1, 0);
mTestInjector.incrementTime(3500);
statsTracker.add(1, 5);
mTestInjector.incrementTime(5000);
statsTracker.stop();
// Data: day 2 user 1
mTestInjector.incrementDate(1);
statsTracker.start();
statsTracker.add(0, 0);
mTestInjector.incrementTime(3500);
statsTracker.add(0, 50000);
mTestInjector.incrementTime(5000);
statsTracker.stop();
// Write them
ByteArrayOutputStream baos = new ByteArrayOutputStream();
statsTracker.writeStats(baos);
baos.flush();
// Read them back and assert that it's the same
ByteArrayInputStream input = new ByteArrayInputStream(baos.toByteArray());
AmbientBrightnessStatsTracker newStatsTracker = getTestStatsTracker();
newStatsTracker.readStats(input);
userStats = newStatsTracker.getUserStats(0);
assertEquals(2, userStats.size());
// Check day 1 user 1
assertEquals(mTestInjector.getLocalDate().minusDays(1), userStats.get(0).getLocalDate());
expectedStats = getEmptyStatsArray();
expectedStats[0] = 1;
expectedStats[1] = 1.5f;
expectedStats[3] = 2.5f;
assertArrayEquals(expectedStats, userStats.get(0).getStats(), 0);
// Check day 2 user 1
assertEquals(mTestInjector.getLocalDate(), userStats.get(1).getLocalDate());
expectedStats = getEmptyStatsArray();
expectedStats[0] = 3.5f;
expectedStats[11] = 5;
assertArrayEquals(expectedStats, userStats.get(1).getStats(), 0);
userStats = newStatsTracker.getUserStats(1);
assertEquals(1, userStats.size());
// Check day 1 user 2
assertEquals(mTestInjector.getLocalDate().minusDays(1), userStats.get(0).getLocalDate());
expectedStats = getEmptyStatsArray();
expectedStats[0] = 3.5f;
expectedStats[4] = 5;
assertArrayEquals(expectedStats, userStats.get(0).getStats(), 0);
}
@Test
public void testTimer() {
AmbientBrightnessStatsTracker.Timer timer = new AmbientBrightnessStatsTracker.Timer(
() -> mTestInjector.elapsedRealtimeMillis());
assertEquals(0, timer.totalDurationSec(), 0);
mTestInjector.incrementTime(1000);
assertEquals(0, timer.totalDurationSec(), 0);
assertFalse(timer.isRunning());
// Start timer
timer.start();
assertTrue(timer.isRunning());
assertEquals(0, timer.totalDurationSec(), 0);
mTestInjector.incrementTime(1000);
assertTrue(timer.isRunning());
assertEquals(1, timer.totalDurationSec(), 0);
// Reset timer
timer.reset();
assertEquals(0, timer.totalDurationSec(), 0);
assertFalse(timer.isRunning());
// Start again
timer.start();
assertTrue(timer.isRunning());
assertEquals(0, timer.totalDurationSec(), 0);
mTestInjector.incrementTime(2000);
assertTrue(timer.isRunning());
assertEquals(2, timer.totalDurationSec(), 0);
// Reset again
timer.reset();
assertEquals(0, timer.totalDurationSec(), 0);
assertFalse(timer.isRunning());
}
private class TestInjector extends AmbientBrightnessStatsTracker.Injector {
private long mElapsedRealtimeMillis = SystemClock.elapsedRealtime();
private LocalDate mLocalDate = LocalDate.now();
public void incrementTime(long timeMillis) {
mElapsedRealtimeMillis += timeMillis;
}
public void incrementDate(int numDays) {
mLocalDate = mLocalDate.plusDays(numDays);
}
@Override
public long elapsedRealtimeMillis() {
return mElapsedRealtimeMillis;
}
@Override
public int getUserSerialNumber(UserManager userManager, int userId) {
return userId + 10;
}
@Override
public int getUserId(UserManager userManager, int userSerialNumber) {
return userSerialNumber - 10;
}
@Override
public LocalDate getLocalDate() {
return LocalDate.from(mLocalDate);
}
}
private AmbientBrightnessStatsTracker getTestStatsTracker() {
return new AmbientBrightnessStatsTracker(
InstrumentationRegistry.getContext().getSystemService(UserManager.class),
mTestInjector);
}
private float[] getEmptyStatsArray() {
return new float[AmbientBrightnessStatsTracker.BUCKET_BOUNDARIES_FOR_NEW_STATS.length];
}
private InputStream getInputStream(String data) {
return new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
}
}